Advertisement
Guest User

Native MenuStrip

a guest
Dec 3rd, 2012
2,449
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 13.57 KB | None | 0 0
  1.   using System;
  2.   using System.Drawing;
  3.   using System.Runtime.InteropServices;
  4.   using System.Windows.Forms;
  5.   using System.Windows.Forms.Layout;
  6.   using System.Windows.Forms.VisualStyles;
  7.  
  8.   public class NativeRenderer : ToolStripSystemRenderer
  9.   {
  10.     private static readonly int RebarBackground = 6;
  11.     private VisualStyleRenderer renderer;
  12.  
  13.     public ToolbarTheme Theme { get; set; }
  14.  
  15.     private string RebarClass
  16.     {
  17.       get
  18.       {
  19.         return this.SubclassPrefix + "Rebar";
  20.       }
  21.     }
  22.  
  23.     private string ToolbarClass
  24.     {
  25.       get
  26.       {
  27.         return this.SubclassPrefix + "ToolBar";
  28.       }
  29.     }
  30.  
  31.     private string MenuClass
  32.     {
  33.       get
  34.       {
  35.         return this.SubclassPrefix + "Menu";
  36.       }
  37.     }
  38.  
  39.     private string SubclassPrefix
  40.     {
  41.       get
  42.       {
  43.         switch (this.Theme)
  44.         {
  45.           case ToolbarTheme.MediaToolbar:
  46.             return "Media::";
  47.           case ToolbarTheme.CommunicationsToolbar:
  48.             return "Communications::";
  49.           case ToolbarTheme.BrowserTabBar:
  50.             return "BrowserTabBar::";
  51.           case ToolbarTheme.HelpBar:
  52.             return "Help::";
  53.           default:
  54.             return string.Empty;
  55.         }
  56.       }
  57.     }
  58.  
  59.     public bool IsSupported
  60.     {
  61.       get
  62.       {
  63.         if (!VisualStyleRenderer.IsSupported)
  64.           return false;
  65.         else
  66.           return VisualStyleRenderer.IsElementDefined(VisualStyleElement.CreateElement("Menu", 7, 1));
  67.       }
  68.     }
  69.  
  70.     static NativeRenderer()
  71.     {
  72.     }
  73.  
  74.     public NativeRenderer(ToolbarTheme theme)
  75.     {
  76.       this.Theme = theme;
  77.     }
  78.  
  79.     private Padding GetThemeMargins(IDeviceContext dc, NativeRenderer.MarginTypes marginType)
  80.     {
  81.       try
  82.       {
  83.         NativeRenderer.NativeMethods.MARGINS pMargins;
  84.         if (NativeRenderer.NativeMethods.GetThemeMargins(this.renderer.Handle, dc.GetHdc(), this.renderer.Part, this.renderer.State, (int) marginType, IntPtr.Zero, out pMargins) == 0)
  85.           return new Padding(pMargins.cxLeftWidth, pMargins.cyTopHeight, pMargins.cxRightWidth, pMargins.cyBottomHeight);
  86.         else
  87.           return new Padding(0);
  88.       }
  89.       finally
  90.       {
  91.         dc.ReleaseHdc();
  92.       }
  93.     }
  94.  
  95.     private static int GetItemState(ToolStripItem item)
  96.     {
  97.       bool selected = item.Selected;
  98.       if (item.IsOnDropDown)
  99.       {
  100.         if (item.Enabled)
  101.           return !selected ? 1 : 2;
  102.         else
  103.           return !selected ? 3 : 4;
  104.       }
  105.       else if (item.Pressed)
  106.         return !item.Enabled ? 6 : 3;
  107.       else if (item.Enabled)
  108.         return !selected ? 1 : 2;
  109.       else
  110.         return !selected ? 4 : 5;
  111.     }
  112.  
  113.     private VisualStyleElement Subclass(VisualStyleElement element)
  114.     {
  115.       return VisualStyleElement.CreateElement(this.SubclassPrefix + element.ClassName, element.Part, element.State);
  116.     }
  117.  
  118.     private bool EnsureRenderer()
  119.     {
  120.       if (!this.IsSupported)
  121.         return false;
  122.       if (this.renderer == null)
  123.         this.renderer = new VisualStyleRenderer(VisualStyleElement.Button.PushButton.Normal);
  124.       return true;
  125.     }
  126.  
  127.     protected override void Initialize(ToolStrip toolStrip)
  128.     {
  129.       if (toolStrip.Parent is ToolStripPanel)
  130.         toolStrip.BackColor = Color.Transparent;
  131.       base.Initialize(toolStrip);
  132.     }
  133.  
  134.     protected override void InitializePanel(ToolStripPanel toolStripPanel)
  135.     {
  136.       foreach (Control control in (ArrangedElementCollection) toolStripPanel.Controls)
  137.       {
  138.         if (control is ToolStrip)
  139.           this.Initialize((ToolStrip) control);
  140.       }
  141.       base.InitializePanel(toolStripPanel);
  142.     }
  143.  
  144.     protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
  145.     {
  146.       if (this.EnsureRenderer())
  147.       {
  148.         this.renderer.SetParameters(this.MenuClass, 10, 0);
  149.         if (!e.ToolStrip.IsDropDown)
  150.           return;
  151.         Region clip = e.Graphics.Clip;
  152.         Rectangle clientRectangle = e.ToolStrip.ClientRectangle;
  153.         clientRectangle.Inflate(-1, -1);
  154.         e.Graphics.ExcludeClip(clientRectangle);
  155.         this.renderer.DrawBackground((IDeviceContext) e.Graphics, e.ToolStrip.ClientRectangle, e.AffectedBounds);
  156.         e.Graphics.Clip = clip;
  157.       }
  158.       else
  159.         base.OnRenderToolStripBorder(e);
  160.     }
  161.  
  162.     private Rectangle GetBackgroundRectangle(ToolStripItem item)
  163.     {
  164.       if (!item.IsOnDropDown)
  165.         return new Rectangle(new Point(), item.Bounds.Size);
  166.       Rectangle bounds = item.Bounds;
  167.       bounds.X = item.ContentRectangle.X + 1;
  168.       bounds.Width = item.ContentRectangle.Width - 1;
  169.       bounds.Y = 0;
  170.       return bounds;
  171.     }
  172.  
  173.     protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
  174.     {
  175.       if (this.EnsureRenderer())
  176.       {
  177.         this.renderer.SetParameters(this.MenuClass, e.Item.IsOnDropDown ? 14 : 8, NativeRenderer.GetItemState(e.Item));
  178.         Rectangle backgroundRectangle = this.GetBackgroundRectangle(e.Item);
  179.         this.renderer.DrawBackground((IDeviceContext) e.Graphics, backgroundRectangle, backgroundRectangle);
  180.       }
  181.       else
  182.         base.OnRenderMenuItemBackground(e);
  183.     }
  184.  
  185.     protected override void OnRenderToolStripPanelBackground(ToolStripPanelRenderEventArgs e)
  186.     {
  187.       if (this.EnsureRenderer())
  188.       {
  189.         if (VisualStyleRenderer.IsElementDefined(VisualStyleElement.CreateElement(this.RebarClass, NativeRenderer.RebarBackground, 0)))
  190.           this.renderer.SetParameters(this.RebarClass, NativeRenderer.RebarBackground, 0);
  191.         else
  192.           this.renderer.SetParameters(this.RebarClass, 0, 0);
  193.         if (this.renderer.IsBackgroundPartiallyTransparent())
  194.           this.renderer.DrawParentBackground((IDeviceContext) e.Graphics, e.ToolStripPanel.ClientRectangle, (Control) e.ToolStripPanel);
  195.         this.renderer.DrawBackground((IDeviceContext) e.Graphics, e.ToolStripPanel.ClientRectangle);
  196.         e.Handled = true;
  197.       }
  198.       else
  199.         base.OnRenderToolStripPanelBackground(e);
  200.     }
  201.  
  202.     protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
  203.     {
  204.       if (this.EnsureRenderer())
  205.       {
  206.         if (e.ToolStrip.IsDropDown)
  207.         {
  208.           this.renderer.SetParameters(this.MenuClass, 9, 0);
  209.         }
  210.         else
  211.         {
  212.           if (e.ToolStrip.Parent is ToolStripPanel)
  213.             return;
  214.           if (VisualStyleRenderer.IsElementDefined(VisualStyleElement.CreateElement(this.RebarClass, NativeRenderer.RebarBackground, 0)))
  215.             this.renderer.SetParameters(this.RebarClass, NativeRenderer.RebarBackground, 0);
  216.           else
  217.             this.renderer.SetParameters(this.RebarClass, 0, 0);
  218.         }
  219.         if (this.renderer.IsBackgroundPartiallyTransparent())
  220.           this.renderer.DrawParentBackground((IDeviceContext) e.Graphics, e.ToolStrip.ClientRectangle, (Control) e.ToolStrip);
  221.         this.renderer.DrawBackground((IDeviceContext) e.Graphics, e.ToolStrip.ClientRectangle, e.AffectedBounds);
  222.       }
  223.       else
  224.         base.OnRenderToolStripBackground(e);
  225.     }
  226.  
  227.     protected override void OnRenderSplitButtonBackground(ToolStripItemRenderEventArgs e)
  228.     {
  229.       if (this.EnsureRenderer())
  230.       {
  231.         ToolStripSplitButton stripSplitButton = (ToolStripSplitButton) e.Item;
  232.         base.OnRenderSplitButtonBackground(e);
  233.         this.OnRenderArrow(new ToolStripArrowRenderEventArgs(e.Graphics, (ToolStripItem) stripSplitButton, stripSplitButton.DropDownButtonBounds, Color.Red, ArrowDirection.Down));
  234.       }
  235.       else
  236.         base.OnRenderSplitButtonBackground(e);
  237.     }
  238.  
  239.     private Color GetItemTextColor(ToolStripItem item)
  240.     {
  241.       this.renderer.SetParameters(this.MenuClass, item.IsOnDropDown ? 14 : 8, NativeRenderer.GetItemState(item));
  242.       return this.renderer.GetColor(ColorProperty.TextColor);
  243.     }
  244.  
  245.     protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
  246.     {
  247.       if (this.EnsureRenderer())
  248.         e.TextColor = this.GetItemTextColor(e.Item);
  249.       base.OnRenderItemText(e);
  250.     }
  251.  
  252.     protected override void OnRenderImageMargin(ToolStripRenderEventArgs e)
  253.     {
  254.       if (this.EnsureRenderer())
  255.       {
  256.         if (!e.ToolStrip.IsDropDown)
  257.           return;
  258.         this.renderer.SetParameters(this.MenuClass, 13, 0);
  259.         Padding themeMargins = this.GetThemeMargins((IDeviceContext) e.Graphics, NativeRenderer.MarginTypes.Sizing);
  260.         int num = e.ToolStrip.Width - e.ToolStrip.DisplayRectangle.Width - themeMargins.Left - themeMargins.Right - 1 - e.AffectedBounds.Width;
  261.         Rectangle bounds = e.AffectedBounds;
  262.         bounds.Y += 2;
  263.         bounds.Height -= 4;
  264.         int width = this.renderer.GetPartSize((IDeviceContext) e.Graphics, ThemeSizeType.True).Width;
  265.         if (e.ToolStrip.RightToLeft == RightToLeft.Yes)
  266.         {
  267.           bounds = new Rectangle(bounds.X - num, bounds.Y, width, bounds.Height);
  268.           bounds.X += width;
  269.         }
  270.         else
  271.           bounds = new Rectangle(bounds.Width + num - width, bounds.Y, width, bounds.Height);
  272.         this.renderer.DrawBackground((IDeviceContext) e.Graphics, bounds);
  273.       }
  274.       else
  275.         base.OnRenderImageMargin(e);
  276.     }
  277.  
  278.     protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
  279.     {
  280.       if (e.ToolStrip.IsDropDown && this.EnsureRenderer())
  281.       {
  282.         this.renderer.SetParameters(this.MenuClass, 15, 0);
  283.         Rectangle rectangle = new Rectangle(e.ToolStrip.DisplayRectangle.Left, 0, e.ToolStrip.DisplayRectangle.Width, e.Item.Height);
  284.         this.renderer.DrawBackground((IDeviceContext) e.Graphics, rectangle, rectangle);
  285.       }
  286.       else
  287.         base.OnRenderSeparator(e);
  288.     }
  289.  
  290.     protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
  291.     {
  292.       if (this.EnsureRenderer())
  293.       {
  294.         Rectangle bounds = this.GetBackgroundRectangle(e.Item);
  295.         bounds.Width = bounds.Height;
  296.         if (e.Item.RightToLeft == RightToLeft.Yes)
  297.           bounds = new Rectangle(e.ToolStrip.ClientSize.Width - bounds.X - bounds.Width, bounds.Y, bounds.Width, bounds.Height);
  298.         this.renderer.SetParameters(this.MenuClass, 12, e.Item.Enabled ? 2 : 1);
  299.         this.renderer.DrawBackground((IDeviceContext) e.Graphics, bounds);
  300.         Rectangle imageRectangle = e.ImageRectangle;
  301.         imageRectangle.X = bounds.X + bounds.Width / 2 - imageRectangle.Width / 2;
  302.         imageRectangle.Y = bounds.Y + bounds.Height / 2 - imageRectangle.Height / 2;
  303.         this.renderer.SetParameters(this.MenuClass, 11, e.Item.Enabled ? 1 : 2);
  304.         this.renderer.DrawBackground((IDeviceContext) e.Graphics, imageRectangle);
  305.       }
  306.       else
  307.         base.OnRenderItemCheck(e);
  308.     }
  309.  
  310.     protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
  311.     {
  312.       if (this.EnsureRenderer())
  313.         e.ArrowColor = this.GetItemTextColor(e.Item);
  314.       base.OnRenderArrow(e);
  315.     }
  316.  
  317.     protected override void OnRenderOverflowButtonBackground(ToolStripItemRenderEventArgs e)
  318.     {
  319.       if (this.EnsureRenderer())
  320.       {
  321.         string className = this.RebarClass;
  322.         if (this.Theme == ToolbarTheme.BrowserTabBar)
  323.           className = "Rebar";
  324.         int state = VisualStyleElement.Rebar.Chevron.Normal.State;
  325.         if (e.Item.Pressed)
  326.           state = VisualStyleElement.Rebar.Chevron.Pressed.State;
  327.         else if (e.Item.Selected)
  328.           state = VisualStyleElement.Rebar.Chevron.Hot.State;
  329.         this.renderer.SetParameters(className, VisualStyleElement.Rebar.Chevron.Normal.Part, state);
  330.         this.renderer.DrawBackground((IDeviceContext) e.Graphics, new Rectangle(Point.Empty, e.Item.Size));
  331.       }
  332.       else
  333.         base.OnRenderOverflowButtonBackground(e);
  334.     }
  335.  
  336.     internal static class NativeMethods
  337.     {
  338.       [DllImport("uxtheme.dll")]
  339.       public static int GetThemeMargins(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, int iPropId, IntPtr rect, out NativeRenderer.NativeMethods.MARGINS pMargins);
  340.  
  341.       public struct MARGINS
  342.       {
  343.         public int cxLeftWidth;
  344.         public int cxRightWidth;
  345.         public int cyTopHeight;
  346.         public int cyBottomHeight;
  347.       }
  348.     }
  349.  
  350.     private enum MenuParts
  351.     {
  352.       ItemTMSchema = 1,
  353.       DropDownTMSchema = 2,
  354.       BarItemTMSchema = 3,
  355.       BarDropDownTMSchema = 4,
  356.       ChevronTMSchema = 5,
  357.       SeparatorTMSchema = 6,
  358.       BarBackground = 7,
  359.       BarItem = 8,
  360.       PopupBackground = 9,
  361.       PopupBorders = 10,
  362.       PopupCheck = 11,
  363.       PopupCheckBackground = 12,
  364.       PopupGutter = 13,
  365.       PopupItem = 14,
  366.       PopupSeparator = 15,
  367.       PopupSubmenu = 16,
  368.       SystemClose = 17,
  369.       SystemMaximize = 18,
  370.       SystemMinimize = 19,
  371.       SystemRestore = 20,
  372.     }
  373.  
  374.     private enum MenuBarStates
  375.     {
  376.       Active = 1,
  377.       Inactive = 2,
  378.     }
  379.  
  380.     private enum MenuBarItemStates
  381.     {
  382.       Normal = 1,
  383.       Hover = 2,
  384.       Pushed = 3,
  385.       Disabled = 4,
  386.       DisabledHover = 5,
  387.       DisabledPushed = 6,
  388.     }
  389.  
  390.     private enum MenuPopupItemStates
  391.     {
  392.       Normal = 1,
  393.       Hover = 2,
  394.       Disabled = 3,
  395.       DisabledHover = 4,
  396.     }
  397.  
  398.     private enum MenuPopupCheckStates
  399.     {
  400.       CheckmarkNormal = 1,
  401.       CheckmarkDisabled = 2,
  402.       BulletNormal = 3,
  403.       BulletDisabled = 4,
  404.     }
  405.  
  406.     private enum MenuPopupCheckBackgroundStates
  407.     {
  408.       Disabled = 1,
  409.       Normal = 2,
  410.       Bitmap = 3,
  411.     }
  412.  
  413.     private enum MenuPopupSubMenuStates
  414.     {
  415.       Normal = 1,
  416.       Disabled = 2,
  417.     }
  418.  
  419.     private enum MarginTypes
  420.     {
  421.       Sizing = 3601,
  422.       Content = 3602,
  423.       Caption = 3603,
  424.     }
  425.   }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement