Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Border Color of Controls Using VisualStyles

Microsoft's visual styles for winforms have always befuddled me.

I am trying to have a Panel sit next to a TreeView and just have the same VisualStyle border.

Border Colors

As you can see, the TreeView border is different than my drawing attempts in my Panel. The panel's BorderStyle is set to None.

I've tried this:

  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);

and I've tried this:

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);

Any suggestions for the correct visual border color or visual element to use?

like image 210
LarsTech Avatar asked Aug 20 '11 14:08

LarsTech


2 Answers

This issue isn't limited to WinForms... Since the WinForms TreeView control is simply a wrapper around the native Win32 TreeView control, it's drawing the same border style as a TreeView control would anywhere else in the system, such as Windows Explorer. And as you've observed, the 3D border style looks different with visual styles enabled than it did on previous versions of Windows. It actually doesn't look 3D at all—the effect is closer if you set the border to Single/FixedSingle, except that it's a little too dark compared to the one around the TreeView.

As far as how to replicate that for a Panel control, I think the trick lies not in drawing an edge, but rather in drawing a background.

There might be a more elegant solution if you P/Invoke the DrawThemeBackground function directly along with some of the Parts and States that aren't exposed in the .NET VisualStyleRenderer wrapper, but this one looks pretty good to me:

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

   

   (The TreeView is on the left; the Panel is on the right.)


If you want to draw the border yourself and match the colors used when visual styles are enabled, you can do that, too. This would simply be a matter of determining the correct color, and then using the standard GDI+ drawing routines to draw a line or two around the control.

But don't fire up Photoshop just yet! The colors are all documented in a file named AeroStyle.xml, located in the include folder of the Windows SDK. You're interested in the globals values; these:

<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>
like image 81
Cody Gray Avatar answered Oct 27 '22 12:10

Cody Gray


for all of you interested, here I found the solution, how you can let draw Windows the correct background for your control (use RECT definition from pinvoke.net):

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);
    }
}
like image 44
Baloo Avatar answered Oct 27 '22 11:10

Baloo