影响ListView标头的Windows主题

时间:2012-04-11 09:52:24

标签: c# winforms visual-c++ listview windows-xp

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

这是Windows XP上使用Windows经典主题的外观:
enter image description here

以下是Windows XP主题的结果:
enter image description here

通过删除Application.EnableVisualStyles()调用或更改,我可以阻止我的应用程序的外观受到Visual Styles的影响 Application.VisualStyleStateenter image description here
虽然此更改使ListView具有所需的外观,但它也会影响其他控件的外观。我希望我的ListView是唯一不受视觉样式影响的控件

我也发现了类似的问题,试图解决它:
Can you turn off visual styles/theming for just a single windows control?
How do I disable visual styles for just one control, and not its children?

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

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

5 个答案:

答案 0 :(得分:3)

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

  

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

但是您可以自己绘制列标题。有关如何操作的详细信息,请参阅this article on MSDN,并查看listView1_DrawColumnHeader

答案 1 :(得分:2)

禁用视觉样式怎么样?

使用此代码可以禁用一个控件的样式(只使用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);
  }
}

答案 2 :(得分:2)

经过深思熟虑的研究后,我发现了它。问题是,当你打电话

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<IntPtr> list = gch.Target as List<IntPtr>;
    if (list == null)
        throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
    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<IntPtr> children = new List<IntPtr>();
    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);
}

答案 3 :(得分:0)

正如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字体的影响。 Check MSDN了解更多详情。

答案 4 :(得分:0)

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

C# - Listview colum header height (Windows Form)