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。有什么想法吗?
答案 0 :(得分:3)
WM_NOTIFY
消息不会发送到控件(列表视图),而是发送到父级(表单)。这在Win32世界中是有意义的,因为这些消息对于拦截非常有用,但是对控件进行子类化是非常痛苦的,特别是当你想要在每种情况下都有不同的行为时。使用.NET不再是这种情况。
方便地,标准的.NET消息处理在消息中“反映”消息,以便您可以拦截消息并在控件的WndProc中处理它 - 但反射的消息不再是WM_NOTIFY
( 0x004E),而是WM_REFLECT
| WM_NOTIFY
(0x204E)。
因此,如果您修改WndProc以查找该值,那么它应该可以正常工作。
答案 1 :(得分:0)
您是否尝试在控件上调用SetWindowTheme
,如this article?
答案 2 :(得分: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!
}
}
那些来自记忆,但你应该明白这一点。
希望有所帮助。
答案 3 :(得分:0)
我自己也很努力。
要使原始问题中的代码生效,请使用[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]标记NMLVEMPTYMARKUP结构(CharSet.Unicode很重要)。
此外,在设置标记值后,调用Marshal.StructureToPtr(nmlvemptymarkup,m.LParam,false)将数据复制回LParam指向的缓冲区。