影响ListView标头的Windows主题

Lih*_*ihO 10 c# listview windows-xp visual-c++ winforms

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

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

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

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

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

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

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

Lih*_*ihO 3

经过一番研究,我发现了。问题是当你打电话时

SetWindowTheme(this.Handle, "", "");
Run Code Online (Sandbox Code Playgroud)

在自定义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);
}
Run Code Online (Sandbox Code Playgroud)