影响ListView标头的Windows主题

我用一个包含ListView的简单表单创建了新的Windows窗体应用程序(C#)。 然后我将View属性更改为Details,并增加了此ListView中使用的字体的大小,这是结果:

这是它在具有Windows经典主题的Windows XP上的外观:
在此处输入图像描述

这是Windows XP主题的结果:
在此处输入图像描述

我可以通过删除Application.EnableVisualStyles()调用或更改Application.VisualStyleState来阻止我的应用程序的外观受Visual Styles的影响: 在此处输入图像描述
虽然此更改使ListView具有所需的外观,但它也会影响其他控件的外观。 我希望我的ListView是唯一不受Visual Styles影响的控件

我也发现了类似的问题试图解决它:
你能为一个窗口控件关闭视觉样式/主题吗?
如何仅为一个控件而不是其子控件禁用视觉样式?

不幸的是,没有提到的解决方案有效 看起来标题本身将由一些受视觉样式影响的控件组成,即使禁用了ListView控件的视觉样式也是如此。

任何阻止视觉样式影响ListView标题外观的C#解决方案都将受到赞赏。

看起来这是一个已知的bug ,没有简单的解决方法。 根据答案:

在对此问题进行了大量研究之后,我们发现这是一个Windows操作系统错误,ComCtl6.0标头控件忘记将字体信息应用于绘图DC。

但是,您可以自己绘制列标题。 有关如何执行此操作的详细信息,请参阅MSDN上的这篇文章,另请参阅listView1_DrawColumnHeader

禁用视觉样式怎么样?

使用此代码,您可以禁用一个控件的样式(只使用ListViewConstrol而不是ListView):

 using System; using System.Windows.Forms; using System.Runtime.InteropServices; public class ListViewControl : ListView { [DllImportAttribute("uxtheme.dll")] private static extern int SetWindowTheme(IntPtr hWnd, string appname, string idlist); protected override void OnHandleCreated(EventArgs e) { SetWindowTheme(this.Handle, "", ""); base.OnHandleCreated(e); } } 

经过深思熟虑的研究,我发现了它。 那就是你打电话的时候

 SetWindowTheme(this.Handle, "", ""); 

在自定义ListView类中,它可以防止视觉样式影响ListView控件的外观,但不会影响ListView头控件( SysHeader32窗口),它是ListView子窗口。 因此,在调用SetWindowTheme函数时,我们需要提供头窗口的句柄而不是ListView的句柄:

 [DllImportAttribute("uxtheme.dll")] private static extern int SetWindowTheme(IntPtr hWnd, string appname, string idlist); [DllImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i); // Callback method to be used when enumerating windows: private static bool EnumWindow(IntPtr handle, IntPtr pointer) { GCHandle gch = GCHandle.FromIntPtr(pointer); List list = gch.Target as List; if (list == null) throw new InvalidCastException("GCHandle Target could not be cast as List"); list.Add(handle); return true; } // delegate for the EnumChildWindows method: private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter); // get first child: private static void DisableVisualStylesForFirstChild(IntPtr parent) { List children = new List(); GCHandle listHandle = GCHandle.Alloc(children); try { EnumWindowProc childProc = new EnumWindowProc(EnumWindow); EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle)); if (children.Count > 0) SetWindowTheme(children[0], "", ""); } finally { if (listHandle.IsAllocated) listHandle.Free(); } } protected override void OnHandleCreated(EventArgs e) { DisableVisualStylesForFirstChild(this.Handle); base.OnHandleCreated(e); } 

正如Botz3000在他的回答中提到的那样,它是Windows XP中ListView一个众所周知的问题。 另一种解决方法是注册ListView.DrawColumnHeader事件并重置其中的标题字体。 您必须将ListView.OwnerDraw属性设置为true 。 MSDN代码如下;

 // Draws column headers. private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e) { using (StringFormat sf = new StringFormat()) { // Store the column text alignment, letting it default // to Left if it has not been set to Center or Right. switch (e.Header.TextAlign) { case HorizontalAlignment.Center: sf.Alignment = StringAlignment.Center; break; case HorizontalAlignment.Right: sf.Alignment = StringAlignment.Far; break; } // Draw the standard header background. e.DrawBackground(); // Draw the header text. using (Font headerFont = new Font("Helvetica", 10, FontStyle.Bold)) { e.Graphics.DrawString(e.Header.Text, headerFont, Brushes.Black, e.Bounds, sf); } } return; } 

在这种情况下,标题字体将始终为"Helvetica", 10, FontStyle.Bold并且不受listview字体的影响。 查看MSDN以获取更多详细信息。

以下是如何使ListView标头具有您想要的高度:

C# – Listview colum标题高度(Windows窗体)