10

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

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

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

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

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

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

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

4

5 回答 5

3

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

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

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

于 2012-04-13T11:13:28.620 回答
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);
  }
}
于 2012-04-13T11:01:57.790 回答
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);
}
于 2012-04-17T14:02:08.960 回答
0

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

C# - Listview 列标题高度(Windows 窗体)

于 2012-04-17T05:39:55.273 回答
0

正如Botz3000ListView在他的回答中提到的那样,它在 Windows XP 中是一个众所周知的问题。另一种解决方法是注册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不受列表视图字体的影响。查看 MSDN以获取更多详细信息。

于 2012-04-13T11:58:51.963 回答