13

微软winforms的视觉风格一直让我迷惑。

我正在尝试Panel坐在 a 旁边,TreeView并且具有相同的 VisualStyle 边框。

边框颜色

如您所见,TreeView边框与我在Panel. 面板的 BorderStyle 设置为 None。

我试过这个:

  Rectangle r = new Rectangle(0, 0, panel1.ClientRectangle.Width - 1, panel1.ClientRectangle.Height - 1);
  using (Pen p = new Pen(VisualStyleInformation.TextControlBorder))
    e.Graphics.DrawRectangle(p, r);

我试过这个:

VisualStyleRenderer renderer = new VisualStyleRenderer(VisualStyleElement.TextBox.TextEdit.Normal);
renderer.DrawEdge(e.Graphics, panel1.ClientRectangle, 
         Edges.Bottom | Edges.Left | Edges.Right | Edges.Top,
         EdgeStyle.Sunken, EdgeEffects.Flat);

对使用正确的视觉边框颜色或视觉元素有什么建议吗?

4

2 回答 2

8

这个问题不仅限于 WinForms... 由于 WinFormsTreeView控件只是原生 Win32 TreeView 控件的包装器,它绘制的边框样式与 TreeView 控件在系统中其他任何地方(例如 Windows 资源管理器)的边框样式相同。正如您所观察到的,启用视觉样式后的 3D 边框样式看起来与以前版本的 Windows 不同。它实际上看起来根本不是 3D 的——如果将边框设置为Single/效果会更接近FixedSingle,除了它与 TreeView 周围的边框相比有点太暗。

至于如何为Panel控件复制它,我认为诀窍不在于绘制边缘,而在于绘制背景

如果您直接 P/InvokeDrawThemeBackground函数以及未在 .NET 包装器中公开的一些部件和VisualStyleRenderer状态,可能会有一个更优雅的解决方案,但这个对我来说看起来不错:

VisualStyleRenderer renderer =
              new VisualStyleRenderer(VisualStyleElement.Tab.Pane.Normal);
renderer.DrawBackground(e.Graphics, panel1.ClientRectangle);

   

   (树视图在左边;面板在右边。)


如果您想自己绘制边框并匹配启用视觉样式时使用的颜色,您也可以这样做。这只是确定正确颜色的问题,然后使用标准 GDI+ 绘图例程在控件周围绘制一两条线。

但暂时不要启动 Photoshop!这些颜色都记录在一个名为的文件中,该文件AeroStyle.xml位于includeWindows SDK 的文件夹中。你对globals价值观感兴趣;这些:

<globals>
    <EdgeDkShadowColor> 100 100 100</EdgeDkShadowColor>
    <EdgeFillColor>     220 220 220</EdgeFillColor>
    <EdgeHighLightColor>244 247 252</EdgeHighLightColor>
    <EdgeLightColor>    180 180 180</EdgeLightColor>
    <EdgeShadowColor>   180 180 180</EdgeShadowColor>
    <GlowColor>         255 255 255</GlowColor>
</globals>
于 2011-08-20T15:14:42.703 回答
2

对于所有感兴趣的人,在这里我找到了解决方案,如何让 Windows 为您的控件绘制正确的背景(使用 pinvoke.net 中的 RECT 定义):

const string CLASS_LISTVIEW = "LISTVIEW";
const int LVP_LISTGROUP = 2;

[DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
private extern static int DrawThemeBackground(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, ref RECT pRect, IntPtr pClipRect);

public static void DrawWindowBackground(IntPtr hWnd, Graphics g, Rectangle bounds)
{
    IntPtr theme = OpenThemeData(hWnd, CLASS_LISTVIEW);
    if (theme != IntPtr.Zero)
    {
      IntPtr hdc = g.GetHdc();
      RECT area = new RECT(bounds);
      DrawThemeBackground(theme, hdc, LVP_LISTGROUP, 0, ref area, IntPtr.Zero);
      g.ReleaseHdc();
      CloseThemeData(theme);
    }
}
于 2012-09-13T11:55:42.717 回答