I have my own TreeView control which is completely OwnerDraw'n:
myTreeView.DrawMode = TreeViewDrawMode.OwnerDrawAll;
What I try to achieve is to draw the opened/closed glyph according to the current explorer theme. Especially on Vista and Win7 boxes I'd like to see the new glyphes (black triangles) instead of the plus/minus signs. I know, for a non-OwnerDraw'n TreeView this can be achieved as follows which works perfectly:
myTreeView.HandleCreated += delegate(object sender, EventArgs args)
{
MyNativeMethods.SetWindowTheme(myTreeView.Handle, "explor开发者_JS百科er", null);
};
I thought a VisualStyleRenderer let me paint the glyphs theme-aware:
VisualStyleRenderer r = new VisualStyleRenderer(VisualStyleElement.TreeView.Glyph.Opened);
r.DrawBackground(e.Graphics, e.Bounds);
The code above unfortunately draws the minus sign in all cases. It looks like the VisualStyleRenderer does not honour the theme setting.
Can someone shed some light on this? Thanks!
I guess its a good thing I stumbled across this post, I wanted to know the same thing when I started updating the Owner-Drawn TreeView control used by some of my projects, after some uxtheme hacking last week I found the states used by explorer and later posted them here for others: http://www.codeproject.com/KB/list/ObjectListView.aspx?msg=3492581#xx3492581xx
Here are the undocumented styles set by Windows when the SetWindowTheme API is used, There are a few other Part and State IDs not listed here but they dont seem useful, I have ommited error checking and VisualStyleRenderer.IsElementDefined() for brevity.
These class names, states and part IDs can also be used by the OpenThemeData/OpenThemeDataEx and DrawThemeBackground API's if you require their usage in native code.
Explorer TreeView Styles:
(These are used by the Glyph +/- expando icons)
VisualStyleRenderer OpenedRenderer = new VisualStyleRenderer("Explorer::TreeView", 2, 2);
VisualStyleRenderer ClosedRenderer = new VisualStyleRenderer("Explorer::TreeView", 2, 1);
(These two are used when the mouse is positioned over the above two Glyph's)
VisualStyleRenderer HoverOpenedRenderer = new VisualStyleRenderer("Explorer::TreeView", 4, 2);
VisualStyleRenderer HoverClosedRenderer = new VisualStyleRenderer("Explorer::TreeView", 4, 1);
(Hovering state over TreeView item)
VisualStyleRenderer ItemHoverRenderer = new VisualStyleRenderer("Explorer::TreeView", 1, 2);
(Selected state TreeView item)
VisualStyleRenderer ItemSelectedRenderer = new VisualStyleRenderer("Explorer::TreeView", 1, 3);
(Selected but when control has lost focus (when this.HideSelecton = False))
VisualStyleRenderer LostFocusSelectedRenderer = new VisualStyleRenderer("Explorer::TreeView", 1, 5);
(there is also another SelectedTreeView state thats a little darker than the default one (1-3) used for showing what item is currently selected when all items are currently selected??)
VisualStyleRenderer Selectedx2Renderer = new VisualStyleRenderer("Explorer::TreeView", 1, 6);
Explorer ListView Styles:
(Hovering state over ListView item)
VisualStyleRenderer ItemHoverRenderer = new VisualStyleRenderer("Explorer::ListView", 1, 2);
(Selected state TreeView item)
VisualStyleRenderer ItemSelectedRenderer = new VisualStyleRenderer("Explorer::ListView", 1, 3);
(Selected but when control has lost focus (when this.HideSelecton = False))
VisualStyleRenderer LostFocusSelectedRenderer = new VisualStyleRenderer("Explorer::ListView", 1, 5);
(again there is also another Selected state thats a little darker than the default one (1-3) used for showing what item is currently selected when all items are currently selected??)
VisualStyleRenderer Selectedx2Renderer = new VisualStyleRenderer("Explorer::ListView", 1, 6);
Example: (Taken from ObjectListView)
protected virtual void DrawExpansionGlyphStyled(Graphics g, Rectangle r, bool isExpanded)
{
VisualStyleElement glowelement = VisualStyleElement.CreateElement("Explorer::TreeView", 2, 1);
if (isExpanded)
glowelement = VisualStyleElement.CreateElement("Explorer::TreeView", 2, 2);
VisualStyleRenderer renderer = new VisualStyleRenderer(glowelement);
renderer.DrawBackground(g, r);
}
Just make sure you cache the creation of the VisualStyleRenderer with a property so your not reading the uxtheme.dll 100's of times a second when your control is getting painted ;)
private static VisualStyleRenderer closedRenderer;
public static VisualStyleRenderer ClosedRenderer
{
get
{
if (closedRenderer == null)
closedRenderer = new VisualStyleRenderer("Explorer::TreeView", 2, 1);
return closedRenderer;
}
}
above example using cached VisualStyleRenderer:
protected virtual void DrawExpansionGlyphStyled(Graphics g, Rectangle r, bool isExpanded)
{
if (isExpanded)
OpenedRenderer.DrawBackground(g, r);
else
ClosedRenderer.DrawBackground(g, r);
}
Enjoy. dmex
精彩评论