├── README.md
├── LICENSE
├── MenuColorTable.cs
├── MenuRenderer.cs
└── RJDropdownMenu.cs
/README.md:
--------------------------------------------------------------------------------
1 | # Dropdown-Menu-CSharp-WinForms
2 | How to create a Dropdown Menu (Custom ContextMenuStrip) with C# and Windows Forms.
3 |
4 |
VIDEO:
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/MenuColorTable.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 | using System.Drawing;
8 |
9 | namespace CustomControls.RJControls
10 | {
11 | public class MenuColorTable : ProfessionalColorTable
12 | {
13 | //Fields
14 | private Color backColor;
15 | private Color leftColumnColor;
16 | private Color borderColor;
17 | private Color menuItemBorderColor;
18 | private Color menuItemSelectedColor;
19 |
20 | //Constructor
21 | public MenuColorTable(bool isMainMenu, Color primaryColor)
22 | {
23 | if (isMainMenu)
24 | {
25 | backColor = Color.FromArgb(37, 39, 60);
26 | leftColumnColor = Color.FromArgb(32, 33, 51);
27 | borderColor = Color.FromArgb(32, 33, 51);
28 | menuItemBorderColor = primaryColor;
29 | menuItemSelectedColor = primaryColor;
30 | }
31 | else
32 | {
33 | backColor = Color.White;
34 | leftColumnColor = Color.LightGray;
35 | borderColor = Color.LightGray;
36 | menuItemBorderColor = primaryColor;
37 | menuItemSelectedColor = primaryColor;
38 | }
39 | }
40 |
41 | //Overrides
42 | public override Color ToolStripDropDownBackground { get { return backColor; } }
43 | public override Color MenuBorder { get { return borderColor; } }
44 | public override Color MenuItemBorder { get { return menuItemBorderColor; } }
45 | public override Color MenuItemSelected { get { return menuItemSelectedColor; } }
46 | public override Color ImageMarginGradientBegin { get { return leftColumnColor; } }
47 | public override Color ImageMarginGradientMiddle { get { return leftColumnColor; } }
48 | public override Color ImageMarginGradientEnd { get { return leftColumnColor; } }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/MenuRenderer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 | using System.Drawing;
8 | using System.Drawing.Drawing2D;
9 |
10 | namespace CustomControls.RJControls
11 | {
12 | public class MenuRenderer : ToolStripProfessionalRenderer
13 | {
14 | //Fields
15 | private Color primaryColor;
16 | private Color textColor;
17 | private int arrowThickness;
18 |
19 | //Constructor
20 | public MenuRenderer(bool isMainMenu, Color primaryColor, Color textColor)
21 | : base(new MenuColorTable(isMainMenu, primaryColor))
22 | {
23 | this.primaryColor = primaryColor;
24 | if (isMainMenu)
25 | {
26 | arrowThickness = 3;
27 | if (textColor == Color.Empty) //Set Default Color
28 | this.textColor = Color.Gainsboro;
29 | else//Set custom text color
30 | this.textColor = textColor;
31 | }
32 | else
33 | {
34 | arrowThickness = 2;
35 | if (textColor == Color.Empty) //Set Default Color
36 | this.textColor = Color.DimGray;
37 | else//Set custom text color
38 | this.textColor = textColor;
39 | }
40 | }
41 |
42 | //Overrides
43 | protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
44 | {
45 | base.OnRenderItemText(e);
46 | e.Item.ForeColor = e.Item.Selected ? Color.White : textColor;
47 | }
48 |
49 | protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
50 | {
51 | //Fields
52 | var graph = e.Graphics;
53 | var arrowSize = new Size(5, 12);
54 | var arrowColor = e.Item.Selected ? Color.White : primaryColor;
55 | var rect = new Rectangle(e.ArrowRectangle.Location.X, (e.ArrowRectangle.Height - arrowSize.Height) / 2,
56 | arrowSize.Width, arrowSize.Height);
57 | using (GraphicsPath path = new GraphicsPath())
58 | using (Pen pen = new Pen(arrowColor, arrowThickness))
59 | {
60 | //Drawing
61 | graph.SmoothingMode = SmoothingMode.AntiAlias;
62 | path.AddLine(rect.Left, rect.Top, rect.Right, rect.Top + rect.Height / 2);
63 | path.AddLine(rect.Right, rect.Top + rect.Height / 2, rect.Left, rect.Top + rect.Height);
64 | graph.DrawPath(pen, path);
65 | }
66 | }
67 |
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/RJDropdownMenu.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using System.Windows.Forms;
8 | using System.Drawing;
9 | using System.Drawing.Drawing2D;
10 | using System.ComponentModel;
11 |
12 | namespace CustomControls.RJControls
13 | {
14 | public class RJDropdownMenu : ContextMenuStrip
15 | {
16 | //Fields
17 | private bool isMainMenu;
18 | private int menuItemHeight = 25;
19 | private Color menuItemTextColor = Color.Empty;//No color, The default color is set in the MenuRenderer class
20 | private Color primaryColor = Color.Empty;//No color, The default color is set in the MenuRenderer class
21 |
22 | private Bitmap menuItemHeaderSize;
23 |
24 | //Constructor
25 | public RJDropdownMenu(IContainer container)
26 | : base(container)
27 | {
28 |
29 | }
30 |
31 | //Properties
32 | //Optionally, hide the properties in the toolbox to avoid the problem of displaying and/or
33 | //saving control property changes in the designer at design time in Visual Studio.
34 | //If the problem I mention does not occur you can expose the properties and manipulate them from the toolbox.
35 | [Browsable(false)]
36 | public bool IsMainMenu
37 | {
38 | get { return isMainMenu; }
39 | set { isMainMenu = value; }
40 | }
41 |
42 | [Browsable(false)]
43 | public int MenuItemHeight
44 | {
45 | get { return menuItemHeight; }
46 | set { menuItemHeight = value; }
47 | }
48 |
49 | [Browsable(false)]
50 | public Color MenuItemTextColor
51 | {
52 | get { return menuItemTextColor; }
53 | set { menuItemTextColor = value; }
54 | }
55 |
56 | [Browsable(false)]
57 | public Color PrimaryColor
58 | {
59 | get { return primaryColor; }
60 | set { primaryColor = value; }
61 | }
62 |
63 | //Private methods
64 | private void LoadMenuItemHeight()
65 | {
66 | if (isMainMenu)
67 | menuItemHeaderSize = new Bitmap(25, 45);
68 | else menuItemHeaderSize = new Bitmap(20, menuItemHeight);
69 |
70 | foreach (ToolStripMenuItem menuItemL1 in this.Items)
71 | {
72 | menuItemL1.ImageScaling = ToolStripItemImageScaling.None;
73 | if (menuItemL1.Image == null) menuItemL1.Image = menuItemHeaderSize;
74 |
75 | foreach (ToolStripMenuItem menuItemL2 in menuItemL1.DropDownItems)
76 | {
77 | menuItemL2.ImageScaling = ToolStripItemImageScaling.None;
78 | if (menuItemL2.Image == null) menuItemL2.Image = menuItemHeaderSize;
79 |
80 | foreach (ToolStripMenuItem menuItemL3 in menuItemL2.DropDownItems)
81 | {
82 | menuItemL3.ImageScaling = ToolStripItemImageScaling.None;
83 | if (menuItemL3.Image == null) menuItemL3.Image = menuItemHeaderSize;
84 |
85 | foreach (ToolStripMenuItem menuItemL4 in menuItemL3.DropDownItems)
86 | {
87 | menuItemL4.ImageScaling = ToolStripItemImageScaling.None;
88 | if (menuItemL4.Image == null) menuItemL4.Image = menuItemHeaderSize;
89 | ///Level 5++
90 | }
91 | }
92 | }
93 | }
94 | }
95 |
96 | //Overrides
97 | protected override void OnHandleCreated(EventArgs e)
98 | {
99 | base.OnHandleCreated(e);
100 | if (this.DesignMode == false)
101 | {
102 | this.Renderer = new MenuRenderer(isMainMenu, primaryColor, menuItemTextColor);
103 | LoadMenuItemHeight();
104 | }
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------