2

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

4 回答 4

3

WM_NOTIFY消息不会发送到控件(列表视图),而是发送到父级(表单)。这在 Win32 世界中是有道理的,因为这些消息对于拦截非常有用,但是对控件进行子类化是相当痛苦的,尤其是当您希望在每种情况下都有不同的行为时。有了 .NET,情况就不再如此了。

方便的是,标准的 .NET 消息处理将消息“反射”回控件,以便您可以截获消息并在控件的 WndProc 中处理它——但反射的消息不再是WM_NOTIFY(0x004E),而是WM_REFLECT| WM_NOTIFY(0x204E)。

因此,如果您修改 WndProc 以查找该值,那么它应该可以工作。

于 2008-12-29T05:16:32.313 回答
0

如本文所述,您是否尝试过调用SetWindowTheme控件?

于 2008-11-13T15:54:14.250 回答
0

另一种解决方案(这样您就不必监视 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!
  }
}

那是凭记忆,但你应该明白。

希望这对您有所帮助。

于 2008-11-13T15:59:17.830 回答
0

我自己在这个问题上挣扎了很多。

要使原始问题中的代码正常工作,请使用 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 标记 NMLVEMPTYMARKUP 结构(CharSet.Unicode 很重要)。

此外,在设置标记值后,调用 Marshal.StructureToPtr(nmlvemptymarkup, m.LParam, false) 将数据复制回 LParam 指向的缓冲区。

于 2009-05-04T15:11:20.193 回答