积极答复者
ListView 的 Empty Markup 不能与 SetWindowTheme 和 AutoResizeColumns 同时工作

问题
-
我想对一个 ListView 设定 Empty Markup,就是当 ListView 为空时所显示的文本提示信息。但如果我使用了 SetWindowTheme 或 AutoResizeColumns,这个标记就会消失。这是我的部分代码:
internal static class ExtensionMethods { public static void SetDoubleBuffered(this ListView listview, bool value) { PropertyInfo pi = typeof(ListView).GetProperty("DoubleBuffered", BindingFlags.NonPublic | BindingFlags.Instance); pi.SetValue(listview, value); } public static void SetWindowTheme(this ListView listview, string pszSubAppName, string pszSubIdList) { NativeMethods.SetWindowTheme(listview.Handle, pszSubAppName, pszSubIdList); } } internal static class NativeMethods { public const Int32 WM_NOTIFY = 0x004e; public const Int32 WM_LBUTTONDBLCLK = 0x0203; public const Int32 WM_USER = 0x0400; public const UInt32 LVN_FIRST = unchecked(0u - 100u); public const UInt32 LVN_GETEMPTYMARKUP = LVN_FIRST - 87; public const Int32 L_MAX_URL_LENGTH = 2084; [StructLayout(LayoutKind.Sequential)] public struct NMHDR { public IntPtr hwndFrom; public IntPtr idFrom; public UInt32 code; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct NMLVEMPTYMARKUP { public NMHDR hdr; public UInt32 dwFlags; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = L_MAX_URL_LENGTH)] public String szMarkup; } [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)] public static extern Int32 SetWindowTheme(IntPtr hWnd, String pszSubAppName, String pszSubIdList); } public partial class MainForm : Form { private ListView listView1 = new ListView(); public MainForm() { InitializeComponent(); this.Controls.Add(listView1); listView1.Dock = DockStyle.Fill; listView1.View = View.Details; listView1.Columns.Add("Test"); listView1.SetDoubleBuffered(true); // listView1.SetWindowTheme("Explorer", null); // listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); } protected override void WndProc(ref Message m) { switch (m.Msg) { case NativeMethods.WM_NOTIFY: var nmhdr = (NativeMethods.NMHDR)m.GetLParam(typeof(NativeMethods.NMHDR)); switch (nmhdr.code) { case NativeMethods.LVN_GETEMPTYMARKUP: if (Control.FromHandle(nmhdr.hwndFrom) == listView1) { var markup = (NativeMethods.NMLVEMPTYMARKUP)m.GetLParam(typeof(NativeMethods.NMLVEMPTYMARKUP)); markup.szMarkup = "This is an empty ListView."; Marshal.StructureToPtr(markup, m.LParam, false); m.Result = new IntPtr(1); return; } break; } break; } base.WndProc(ref m); } }
这个例子可以显示标记,但如果我取消注释下面的任意一行:
// listView1.SetWindowTheme("Explorer", null); // listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
这个标记就会消失。
我已经证实了在 Win32 层次上这个是可以实现的,参见 http://stackoverflow.com/questions/12106631/listviews-empty-markup-cant-work-with-setwindowtheme-and-autoresizecolumns,但不知为何 C# 下就不行。请问该如何解决?
- 已编辑 EFanZh 2012年8月27日 8:22
答案
-
可以将
listView1.SetWindowTheme("Explorer", null); listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
放入 Form 的 Load 事件中就行了,原因未知。参见:http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/168c2b98-aefe-4c17-8ffc-cf15485a84ad。
另外,也可重写 OnHandleCreated 方法,在其中执行上两行,原因未知。
EFanZh
- 已标记为答案 EFanZh 2012年9月6日 10:47
全部回复
-
Hi EFanZh,
因为你即设置了半透明的主题又想用markup标记,因为markup标记也设置在半透明标记上的,所以你看不到这个This is an empty ListView.因为ListView控件的背景本身就不能设置alpha数值,而markup标记作为半透明的属性本身不能更改,所以你仍然使用半透明主题的话,那么就看不到这个标记的,实际它还在,就像在黑色的背景上显示黑色字体一样是看不见的。
Jason Wang [MSFT]
MSDN Community Support | Feedback to us
-
可以将
listView1.SetWindowTheme("Explorer", null); listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
放入 Form 的 Load 事件中就行了,原因未知。参见:http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/168c2b98-aefe-4c17-8ffc-cf15485a84ad。
另外,也可重写 OnHandleCreated 方法,在其中执行上两行,原因未知。
EFanZh
- 已标记为答案 EFanZh 2012年9月6日 10:47