ListView Пустой текст разметки - PullRequest
2 голосов
/ 13 ноября 2008

Vista представила новый API для отображения текста в элементе управления списком, когда у него нет элементов. Как говорится в библиотеке MSDN, я должен обработать уведомление LVN_GETEMPTYMARKUP.

В унаследованном элементе управления ListView метод WndProc переопределяется:

protected override void WndProc(ref Message m) {
  try {
    if(m.Msg == 78 /* WM_NOTIFY */) {
      var nmhdr = (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR));
      if(nmhdr.code == -187 /* LVN_GETEMPTYMARKUP */) {
        var nmlvemptymarkup =
          (NMLVEMPTYMARKUP)Marshal.PtrToStructure(m.LParam, typeof(NMLVEMPTYMARKUP));
        nmlvemptymarkup.szMarkup = "The ListView is empty.";
        m.Result = (IntPtr)1;
      }
    }
  } finally {
    base.WndProc(ref m);
  }
}

Тем не менее, это не работает (хотя и не выдает никаких исключений). На самом деле я никогда не получаю nmhdr.code равно -187. Есть идеи?

Ответы [ 4 ]

3 голосов
/ 29 декабря 2008

WM_NOTIFY сообщения отправляются не элементу управления (просмотр списка), а, скорее, родительскому элементу (форма). Это имело смысл в мире Win32, потому что эти сообщения очень полезны для перехвата, но подкласс управления был умеренно болезненным, особенно когда вы хотели различного поведения в каждом случае. С .NET это больше не так.

Удобно, что стандартная обработка сообщений .NET «отражает» сообщение обратно в элемент управления, так что вы можете перехватить сообщение и обработать его в WndProc элемента управления, но отраженное сообщение больше не WM_NOTIFY (0x004E) , а точнее WM_REFLECT | WM_NOTIFY (0x204E).

Так что, если вы измените свой WndProc для поиска этого значения, то оно должно работать.

0 голосов
/ 04 мая 2009

Я много боролся с этим сам.

Чтобы код в исходном вопросе работал, пометьте структуру NMLVEMPTYMARKUP [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)] (CharSet.Unicode важен).

Кроме того, после установки значений разметки вызовите Marshal.StructureToPtr (nmlvemptymarkup, m.LParam, false), чтобы скопировать данные обратно в буфер, на который указывает LParam.

0 голосов
/ 13 ноября 2008

Альтернативное решение (чтобы вам не приходилось отслеживать WndProc) - добавить обработчик рисования примерно так:

listview_onPaint(object sender, eventargs e)
{
  if ( listview.items.count <= 0 )
  {
     e.graphics.drawstring("The Listview is empty"); //put all the proper args in here!
  }
}

это по памяти, но вы должны понять.

надеюсь, что это поможет.

0 голосов
/ 13 ноября 2008

Вы пытались вызвать SetWindowTheme на контроле, как указано в этой статье ?

...