Reputation: 15623
Vista has introduced a new API to display a text in the list view control when it doesn't have any items. As the MSDN library states, I should process the LVN_GETEMPTYMARKUP
notification.
In the inherited ListView
control the WndProc
method is overriden:
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);
}
}
However, it doesn't work (although it doesn't throw any exception). Actually I never get nmhdr.code
equals to -187. Any ideas?
Upvotes: 2
Views: 1187
Reputation: 832
I struggled a lot with this one myself.
To get the code in the original question to work, mark the NMLVEMPTYMARKUP struct with [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] (the CharSet.Unicode is important).
Also, after setting the markup-values, call Marshal.StructureToPtr(nmlvemptymarkup, m.LParam, false) to copy the data back to the buffer pointed to by LParam.
Upvotes: 0
Reputation: 13030
WM_NOTIFY
messages are not sent to the control (the listview), but rather to the parent (the form). This made sense in the Win32 world because these messages are very useful to intercept but it was moderately painful to subclass the control, especially when you wanted different behaviour in each case. With .NET that's no longer the case.
Conveniently, the standard .NET message processing "reflects" the message back at the control, so that you can intercept the message and handle it within the control's WndProc -- but the reflected message is no longer WM_NOTIFY
(0x004E), but rather WM_REFLECT
|WM_NOTIFY
(0x204E).
So if you modify your WndProc to look for that value instead then it should work.
Upvotes: 3
Reputation: 11627
An alternative solution (so that you don't have to monitor the WndProc), would be to add a paint handler something like this:
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!
}
}
thats from memory, but you should get the idea.
hope thats of some help.
Upvotes: 0
Reputation: 2113
Have you tried calling SetWindowTheme
on the control, as indicated in this article?
Upvotes: 0