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.
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?
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>
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With