VisualStyleRenderer和主题(WinForms)

Yve*_*ves 12 .net winforms

我有自己的TreeView控件,完全是OwnerDraw'n:

  myTreeView.DrawMode = TreeViewDrawMode.OwnerDrawAll;
Run Code Online (Sandbox Code Playgroud)

我试图实现的是根据当前的资源管理器主题绘制打开/关闭的字形.特别是在Vista和Win7盒子上,我希望看到新的支架(黑色三角形)而不是加号/减号.我知道,对于非OwnerDraw'n TreeView,这可以通过以下方式实现:

  myTreeView.HandleCreated += delegate(object sender, EventArgs args)
  {
     MyNativeMethods.SetWindowTheme(myTreeView.Handle, "explorer", null);
  };
Run Code Online (Sandbox Code Playgroud)

我认为VisualStyleRenderer让我绘制主题感知的字形:

  VisualStyleRenderer r = new VisualStyleRenderer(VisualStyleElement.TreeView.Glyph.Opened);
  r.DrawBackground(e.Graphics, e.Bounds);
Run Code Online (Sandbox Code Playgroud)

不幸的是,上面的代码在所有情况下都会绘制减号.看起来VisualStyleRenderer不尊重主题设置.

有人可以对此有所了解吗?谢谢!

dme*_*mex 19

我觉得我偶然发现这篇文章是件好事,当我开始更新我的一些项目所使用的所有者绘制的TreeView控件时,我想知道同样的事情,在上周的一些uxtheme hacking之后我发现了explorer使用的状态后来在这里发布了其他人:http://www.codeproject.com/KB/list/ObjectListView.aspx?msg = 3492581#xx3492581xx

以下是使用SetWindowTheme API时由Windows设置的未记录样式,此处未列出其他一些部件和状态ID,但它们似乎没用,我为了简洁我省略了错误检查和VisualStyleRenderer.IsElementDefined().

如果您需要在本机代码中使用它们,OpenThemeData/OpenThemeDataEx和DrawThemeBackground API也可以使用这些类名,状态和部件ID.

Explorer TreeView样式:

(这些由Glyph +/- expando图标使用)

VisualStyleRenderer OpenedRenderer = new VisualStyleRenderer("Explorer::TreeView", 2, 2);
VisualStyleRenderer ClosedRenderer = new VisualStyleRenderer("Explorer::TreeView", 2, 1); 
Run Code Online (Sandbox Code Playgroud)

(当鼠标位于上面两个雕文上方时使用这两个)

VisualStyleRenderer HoverOpenedRenderer = new VisualStyleRenderer("Explorer::TreeView", 4, 2);
VisualStyleRenderer HoverClosedRenderer = new VisualStyleRenderer("Explorer::TreeView", 4, 1); 
Run Code Online (Sandbox Code Playgroud)

(在TreeView项目上悬停状态)

VisualStyleRenderer ItemHoverRenderer = new VisualStyleRenderer("Explorer::TreeView", 1, 2); 
Run Code Online (Sandbox Code Playgroud)

(选择状态TreeView项)

VisualStyleRenderer ItemSelectedRenderer = new VisualStyleRenderer("Explorer::TreeView", 1, 3);
Run Code Online (Sandbox Code Playgroud)

(选中但控制失去焦点时(此时.HideSelecton = False))

VisualStyleRenderer LostFocusSelectedRenderer = new VisualStyleRenderer("Explorer::TreeView", 1, 5); 
Run Code Online (Sandbox Code Playgroud)

(还有另一个SelectedTreeView状态比默认状态(1-3)更暗,用于显示当前所有项目都被选中时当前选择的项目??)

VisualStyleRenderer Selectedx2Renderer = new VisualStyleRenderer("Explorer::TreeView", 1, 6); 
Run Code Online (Sandbox Code Playgroud)

Explorer ListView样式:

(将状态悬停在ListView项目上)

VisualStyleRenderer ItemHoverRenderer = new VisualStyleRenderer("Explorer::ListView", 1, 2); 
Run Code Online (Sandbox Code Playgroud)

(选择状态TreeView项)

VisualStyleRenderer ItemSelectedRenderer = new VisualStyleRenderer("Explorer::ListView", 1, 3);
Run Code Online (Sandbox Code Playgroud)

(选中但控制失去焦点时(此时.HideSelecton = False))

VisualStyleRenderer LostFocusSelectedRenderer = new VisualStyleRenderer("Explorer::ListView", 1, 5); 
Run Code Online (Sandbox Code Playgroud)

(同样还有另一个选定状态比默认状态(1-3)稍暗,用于显示当前所有项目都被选中时当前选择的项目??)

VisualStyleRenderer Selectedx2Renderer = new VisualStyleRenderer("Explorer::ListView", 1, 6); 
Run Code Online (Sandbox Code Playgroud)

示例:(取自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);
} 
Run Code Online (Sandbox Code Playgroud)

只需确保使用属性缓存VisualStyleRenderer的创建,这样当您的控件被绘制时,您不会读取uxtheme.dll 100次;)

private static VisualStyleRenderer closedRenderer;
public static VisualStyleRenderer ClosedRenderer
{
   get
   {
       if (closedRenderer == null)
          closedRenderer = new VisualStyleRenderer("Explorer::TreeView", 2, 1);

       return closedRenderer;
   }    
}
Run Code Online (Sandbox Code Playgroud)

上面的示例使用缓存的VisualStyleRenderer:

protected virtual void DrawExpansionGlyphStyled(Graphics g, Rectangle r, bool isExpanded)
{

if (isExpanded)
   OpenedRenderer.DrawBackground(g, r);
else
   ClosedRenderer.DrawBackground(g, r);
} 
Run Code Online (Sandbox Code Playgroud)

请享用.dmex