├── .gitattributes
├── .gitignore
├── ISSUE_TEMPLATE.md
├── LICENSE
├── ModernUIDoneRight.dt
├── ModernUIDoneRight.sln
├── ModernUIDoneRight
├── Controls
│ ├── AppBar.cs
│ ├── ModernButton.cs
│ ├── ModernShadowPanel.cs
│ ├── ModernTileReborn.cs
│ ├── ModernToolTIp.cs
│ └── SidebarControl.cs
├── Forms
│ ├── AlphaWindow.cs
│ ├── GlowShadowForm.cs
│ ├── GlowShadowFormAaaaaa.cs
│ ├── ModernForm.cs
│ ├── PerPixelAlphaForm.cs
│ └── ShadowForm.cs
├── ModernUIDoneRight.csproj
├── Native
│ └── DwmNative.cs
├── Objects
│ ├── Action.cs
│ ├── Colors
│ │ ├── ColorScheme.cs
│ │ ├── DefaultColorSchemes.cs
│ │ └── DefaultColors.cs
│ ├── Interaction
│ │ ├── ModernTitlebarButton.cs
│ │ ├── NativeTitlebarButton.cs
│ │ └── WindowHitTestResult.cs
│ ├── MenuItems
│ │ ├── AppBarMenuForm.cs
│ │ ├── AppBarMenuItem.cs
│ │ ├── AppBarMenuTextItem.cs
│ │ ├── MeasureMenuItemEventArgs.cs
│ │ └── RenderMenuItemEventArgs.cs
│ ├── ShadowType.cs
│ └── TileText.cs
├── Properties
│ └── AssemblyInfo.cs
├── SidebarTextItem.cs
└── Utils
│ ├── Animation.cs
│ ├── ColorSchemeConverter.cs
│ ├── ControlPaintWrapper.cs
│ ├── FormUtils.cs
│ ├── GaussianBlur.cs
│ ├── GraphicUtils.cs
│ └── ShadowUtils.cs
├── ModernUITest
├── App.config
├── Form1.Designer.cs
├── Form1.cs
├── Form1.resx
├── ModernUITest.csproj
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
└── Resources
│ └── 64px-Speaker_Icon.svg.png
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | # Issue Report
2 | ### Expected Behaviour
3 |
4 |
5 | ### Actual Behaviour
6 |
7 |
8 | ### Steps to Reproduce
9 |
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 NickAc
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/ModernUIDoneRight.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26730.12
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernUIDoneRight", "ModernUIDoneRight\ModernUIDoneRight.csproj", "{2B12BD1B-9601-4B60-9515-F9A756D10753}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernUITest", "ModernUITest\ModernUITest.csproj", "{E874F220-2A5A-4038-BD42-302ED1EA6A48}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {2B12BD1B-9601-4B60-9515-F9A756D10753}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {2B12BD1B-9601-4B60-9515-F9A756D10753}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {2B12BD1B-9601-4B60-9515-F9A756D10753}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {2B12BD1B-9601-4B60-9515-F9A756D10753}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {E874F220-2A5A-4038-BD42-302ED1EA6A48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {E874F220-2A5A-4038-BD42-302ED1EA6A48}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {E874F220-2A5A-4038-BD42-302ED1EA6A48}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {E874F220-2A5A-4038-BD42-302ED1EA6A48}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {E5FEA6EB-FDCC-4D85-A735-F14C81737F3B}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Controls/AppBar.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Forms;
2 | using NickAc.ModernUIDoneRight.Objects;
3 | using NickAc.ModernUIDoneRight.Objects.MenuItems;
4 | using NickAc.ModernUIDoneRight.Utils;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.ComponentModel;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Windows.Forms;
11 |
12 | namespace NickAc.ModernUIDoneRight.Controls
13 | {
14 | public class AppBar : Control
15 | {
16 | #region Fields
17 |
18 | private ColorScheme _colorScheme = DefaultColorSchemes.Blue;
19 |
20 | private bool _hasStartedYet;
21 | private string _text = "";
22 | private bool _iconVisible;
23 | private bool _overrideParentText;
24 | private ToolTip _toolTip;
25 |
26 | #endregion
27 |
28 | #region Constructors
29 |
30 | public AppBar()
31 | {
32 | DoubleBuffered = true;
33 | SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
34 | SetStyle(ControlStyles.AllPaintingInWmPaint, true);
35 | SetStyle(ControlStyles.ResizeRedraw, true);
36 | Size = new Size(10, RoundUp((int)(ModernForm.DefaultTitlebarHeight * 1.5d)));
37 | Dock = DockStyle.Top;
38 | Load += AppBar_Load;
39 | }
40 |
41 | #endregion
42 |
43 | #region Events
44 |
45 | ///
46 | /// Called to signal to subscribers that this control loaded
47 | ///
48 | public event EventHandler Load;
49 |
50 | #endregion
51 |
52 | #region Properties
53 |
54 | public bool OverrideParentText
55 | {
56 | get => _overrideParentText;
57 | set
58 | {
59 | _overrideParentText = value;
60 | Invalidate();
61 | }
62 | }
63 |
64 | [Browsable(false)]
65 | [EditorBrowsable(EditorBrowsableState.Never)]
66 | public bool IsSideBarAvailable => Parent != null && Parent.Controls.OfType().Any();
67 |
68 | public bool CastShadow { get; set; } = true;
69 |
70 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
71 | public List Actions { get; set; } = new List();
72 |
73 | public ColorScheme ColorScheme
74 | {
75 | get => Parent != null && Parent is ModernForm ? ((ModernForm)Parent).ColorScheme : _colorScheme;
76 | set => _colorScheme = value;
77 | }
78 |
79 | public int HamburgerButtonSize { get; set; } = 32;
80 |
81 | public Rectangle ControlBounds => new Rectangle(Point.Empty, Size);
82 |
83 | public bool IconVisible
84 | {
85 | get => _iconVisible;
86 | set
87 | {
88 | _iconVisible = value;
89 | Invalidate();
90 | }
91 | }
92 |
93 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
94 | public List MenuItems { get; set; } = new List();
95 |
96 |
97 | [Browsable(true)]
98 | public override string Text
99 | {
100 | get => !OverrideParentText ? FindForm()?.Text : _text;
101 | set
102 | {
103 | if (OverrideParentText)
104 | _text = value;
105 | else
106 | {
107 | var findForm = FindForm();
108 | if (findForm == null) return;
109 | findForm.Text = value;
110 | findForm.Invalidate();
111 | }
112 | Invalidate();
113 | }
114 | }
115 |
116 | public Font TextFont { get; set; } = new Font(SystemFonts.CaptionFont.FontFamily, 14f);
117 |
118 | public Rectangle TextRectangle =>
119 | Rectangle.FromLTRB((IsSideBarAvailable ? HamburgerButtonSize : 0) + XTextOffset * (IconVisible ? 2 : 1), 0,
120 | ControlBounds.Right - XTextOffset, ControlBounds.Bottom);
121 |
122 | public Rectangle HamburgerRectangle => IsSideBarAvailable
123 | ? Rectangle.FromLTRB(TextRectangle.Left - 8 - HamburgerButtonSize, TextRectangle.Top + 8,
124 | TextRectangle.Left - 8, TextRectangle.Bottom - 8)
125 | : Rectangle.Empty;
126 |
127 | public int XTextOffset => 20;
128 |
129 | public ToolTip ToolTip { get => _toolTip; set => _toolTip = value; }
130 |
131 | #endregion
132 |
133 | #region Methods
134 |
135 | public Rectangle GetMenuRectangle()
136 | {
137 | int index = 0;
138 | int xTextOffset = XTextOffset;
139 | int size = Height - xTextOffset;
140 | int xTextOffsetHalf = XTextOffset / 2;
141 | int right = Width - xTextOffsetHalf - (index * size + xTextOffsetHalf * index);
142 | return Rectangle.FromLTRB(right - size, xTextOffsetHalf, right, Height - xTextOffsetHalf);
143 | }
144 |
145 | protected virtual void OnLoad(EventArgs e)
146 | {
147 | EventHandler eh = Load;
148 |
149 | eh?.Invoke(this, e);
150 | }
151 |
152 | protected override void OnMouseDown(MouseEventArgs e)
153 | {
154 | base.OnMouseDown(e);
155 | if (IsSideBarAvailable) Invalidate(HamburgerRectangle);
156 | }
157 |
158 | protected override void OnMouseUp(MouseEventArgs e)
159 | {
160 | base.OnMouseUp(e);
161 | if (IsSideBarAvailable) Invalidate(HamburgerRectangle);
162 | }
163 |
164 | protected override void OnMouseMove(MouseEventArgs e)
165 | {
166 | base.OnMouseMove(e);
167 |
168 | foreach (AppAction action in this.Actions)
169 | {
170 | var rect = action.GetRectangle(this, this.Actions);
171 | if (rect.Contains(e.Location))
172 | {
173 | if (ToolTip != null)
174 | {
175 | ToolTip.SetToolTip(this, action.ToolTip);
176 | if (ToolTip is ModernToolTip mtp)
177 | {
178 | mtp.Caption = action.ToolTip;
179 | }
180 | }
181 | if (action.Cursor != null)
182 | {
183 | Cursor = action.Cursor;
184 | }
185 | return;
186 | }
187 | }
188 | Cursor = Cursors.Default;
189 | if (ToolTip != null)
190 | {
191 | ToolTip.SetToolTip(this, "");
192 | }
193 | }
194 |
195 | protected override void OnMouseClick(MouseEventArgs e)
196 | {
197 | base.OnMouseClick(e);
198 | if (IsSideBarAvailable && HamburgerRectangle.Contains(e.Location))
199 | {
200 | Parent.Controls.OfType().All(c =>
201 | {
202 | if (c.IsClosed)
203 | {
204 | c.ShowSidebar();
205 | }
206 | else
207 | c.HideSidebar();
208 |
209 | return true;
210 | });
211 | }
212 |
213 | Rectangle menuRect = GetMenuRectangle();
214 | if (MenuItems != null && MenuItems.Count > 0 && menuRect.Contains(e.Location))
215 | {
216 | //Open new "window" to act as menu
217 | Color splitterColor = Color.Gray;
218 | const float splitterPercentage = 0.75f;
219 | var form = new AppBarMenuForm
220 | {
221 | TitlebarVisible = false,
222 | Tag = MenuItems,
223 | Text = "ModernMenu",
224 | ShowInTaskbar = false,
225 | TopMost = true,
226 | Sizable = false,
227 | };
228 |
229 | bool mouseDown = false;
230 | form.MouseDown += (s, ee) =>
231 | {
232 | mouseDown = true;
233 | form.Invalidate();
234 | };
235 | form.MouseUp += (s, ee) =>
236 | {
237 | mouseDown = false;
238 | form.Invalidate();
239 | };
240 | form.MouseMove += (s, ee) => { form.Refresh(); };
241 |
242 | form.Click += (s, ee) =>
243 | {
244 | //Check the click
245 | if (form.Tag != null)
246 | {
247 | if (form.Tag is List items)
248 | {
249 | using (var g = form.CreateGraphics())
250 | {
251 | int yOffset = 0;
252 | foreach (var item in items)
253 | {
254 | Size itemSize = item.GetSize(Font, g);
255 | Rectangle rect =
256 | new Rectangle(
257 | new Point(form.DisplayRectangle.Left, yOffset + form.DisplayRectangle.Top),
258 | new Size(itemSize.Width, itemSize.Height - 1));
259 |
260 | if (rect.Contains(form.PointToClient(Cursor.Position)))
261 | {
262 | item.PerformClick();
263 | return;
264 | }
265 |
266 | yOffset += itemSize.Height;
267 | }
268 | }
269 | }
270 | }
271 | };
272 |
273 | form.Deactivate += (s, ee) =>
274 | {
275 | if (Parent is Form frm)
276 | {
277 | frm.Activate();
278 | }
279 |
280 | form.Dispose();
281 | };
282 |
283 | form.Paint += (s, ee) =>
284 | {
285 | //Draw the menu
286 | int yOffset = 0;
287 | using (var splitterPen = new Pen(splitterColor))
288 | {
289 | for (int i = 0, menuItemsCount = MenuItems.Count; i < menuItemsCount; i++)
290 | {
291 | var item = MenuItems[i];
292 | Size itemSize = item.GetSize(Font, ee.Graphics);
293 | Rectangle rect =
294 | new Rectangle(
295 | new Point(form.DisplayRectangle.Left, yOffset + form.DisplayRectangle.Top),
296 | new Size(itemSize.Width, itemSize.Height - 1));
297 |
298 | if (mouseDown && rect.Contains(form.PointToClient(Cursor.Position)))
299 | {
300 | ee.Graphics.FillRectangle(Brushes.LightGray, rect);
301 | }
302 |
303 | item.DrawItem(ee.Graphics, rect, Font);
304 | if (i < menuItemsCount - 1)
305 | {
306 | int lineWidth = (int)(form.Width * splitterPercentage);
307 | int side = (form.Width - lineWidth) / 2;
308 | ee.Graphics.DrawLine(splitterPen, side, (yOffset + (itemSize.Height)),
309 | form.Width - side, (yOffset + (itemSize.Height)));
310 | }
311 |
312 | yOffset += itemSize.Height;
313 | }
314 | }
315 | };
316 |
317 | int maxWidth = -1;
318 | int maxHeight = -1;
319 | using (Graphics g = CreateGraphics())
320 | {
321 | foreach (var item in MenuItems)
322 | {
323 | var size = item.GetSize(Font, g);
324 |
325 | maxWidth = Math.Max(maxWidth, size.Width);
326 | maxHeight += size.Height;
327 | }
328 | }
329 |
330 | form.Size = new Size(maxWidth + 2, maxHeight + 2);
331 | Point screenLoc = PointToScreen(new Point(menuRect.Right, menuRect.Top));
332 | form.Location = new Point(screenLoc.X - maxWidth, screenLoc.Y);
333 | form.Show(this.Parent);
334 | }
335 |
336 | if (Actions != null)
337 | {
338 | Actions.ForEach(a =>
339 | {
340 | Rectangle rect = a.GetRectangle(this, Actions);
341 | if (rect != Rectangle.Empty && rect.Contains(e.Location))
342 | {
343 | a.OnClick(EventArgs.Empty);
344 | }
345 | });
346 | }
347 | }
348 |
349 | protected override void OnPaint(PaintEventArgs e)
350 | {
351 | if (!_hasStartedYet)
352 | {
353 | _hasStartedYet = true;
354 | OnLoad(EventArgs.Empty);
355 | }
356 |
357 | if (Actions != null)
358 | {
359 | Actions.ForEach(a =>
360 | {
361 | Rectangle rect = a.GetRectangle(this, Actions);
362 | if (rect != Rectangle.Empty && a.Image != null)
363 | {
364 | ControlPaintWrapper.ZoomDrawImage(e.Graphics, a.Image, rect);
365 | }
366 | });
367 | }
368 |
369 | base.OnPaint(e);
370 | }
371 |
372 |
373 | protected override void OnPaintBackground(PaintEventArgs pevent)
374 | {
375 | base.OnPaintBackground(pevent);
376 | using (var primary = new SolidBrush(ColorScheme.PrimaryColor))
377 | {
378 | using (var secondary = new SolidBrush(ColorScheme.SecondaryColor))
379 | {
380 | using (var foreColor = new SolidBrush(ColorScheme.ForegroundColor))
381 | {
382 | pevent.Graphics.FillRectangle(primary, ControlBounds);
383 | if (IconVisible)
384 | {
385 | pevent.Graphics.DrawIcon(((Form)Parent).Icon,
386 | Rectangle.FromLTRB(XTextOffset / 2, XTextOffset / 2, XTextOffset * 2,
387 | Height - (XTextOffset / 2)));
388 | }
389 |
390 | GraphicUtils.DrawCenteredText(pevent.Graphics, Text, TextFont, TextRectangle,
391 | ColorScheme.ForegroundColor, false, true);
392 |
393 | if (MenuItems != null && MenuItems.Count > 0)
394 | {
395 | //Draw menu icon
396 | Rectangle rect = GetMenuRectangle();
397 | const int circleRadius = 2;
398 | const int interval = 3;
399 | int centerX = rect.Right - (rect.Width / 2);
400 | int centerY = rect.Bottom - (rect.Height / 2);
401 | int topCircle = centerY - (circleRadius * 2) - interval;
402 | int bottomCircle = centerY + (circleRadius * 2) + interval;
403 |
404 | var oldMode = pevent.Graphics.SmoothingMode;
405 | pevent.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
406 |
407 | //Top
408 | pevent.Graphics.FillEllipse(foreColor, centerX - circleRadius, topCircle - circleRadius,
409 | circleRadius * 2, circleRadius * 2);
410 |
411 | //Middle
412 | pevent.Graphics.FillEllipse(foreColor, centerX - circleRadius, centerY - circleRadius,
413 | circleRadius * 2, circleRadius * 2);
414 |
415 | //Bottom
416 | pevent.Graphics.FillEllipse(foreColor, centerX - circleRadius, bottomCircle - circleRadius,
417 | circleRadius * 2, circleRadius * 2);
418 |
419 | pevent.Graphics.SmoothingMode = oldMode;
420 | }
421 |
422 | if (IsSideBarAvailable)
423 | GraphicUtils.DrawHamburgerButton(pevent.Graphics, secondary, HamburgerRectangle,
424 | ColorScheme.ForegroundColor, this);
425 | }
426 | }
427 | }
428 | }
429 |
430 | private void AppBar_Load(object sender, EventArgs e)
431 | {
432 | if (!CastShadow) return;
433 | //The control was drawn.
434 | //This means we can add the drop shadow
435 | this.CreateDropShadow();
436 | if (Parent != null)
437 | {
438 | Parent.Invalidate();
439 | }
440 | }
441 |
442 | private int RoundDown(int toRound) => toRound - toRound % 10;
443 |
444 | private int RoundUp(int toRound) => (10 - toRound % 10) + toRound;
445 |
446 | #endregion
447 | }
448 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/Controls/ModernButton.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Forms;
2 | using NickAc.ModernUIDoneRight.Objects;
3 | using NickAc.ModernUIDoneRight.Utils;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Drawing;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Windows.Forms;
11 |
12 | namespace NickAc.ModernUIDoneRight.Controls
13 | {
14 | public class ModernButton : Button
15 | {
16 | #region Fields
17 |
18 | private ColorScheme _colorScheme = DefaultColorSchemes.Blue;
19 | private bool _customColorScheme;
20 |
21 | #endregion
22 |
23 | #region Properties
24 |
25 | public bool CustomColorScheme
26 | {
27 | get => _customColorScheme;
28 | set
29 | {
30 | if (!_customColorScheme && value && _colorScheme == DefaultColorSchemes.Blue)
31 | _colorScheme = ColorScheme;
32 | _customColorScheme = value;
33 | Refresh();
34 | }
35 | }
36 |
37 | public ColorScheme ColorScheme
38 | {
39 | get
40 | {
41 | var form = FindForm();
42 | return form != null && form is ModernForm mdF && !CustomColorScheme ? mdF.ColorScheme : _colorScheme;
43 | }
44 | set
45 | {
46 | _colorScheme = value;
47 | Refresh();
48 | }
49 | }
50 |
51 | [Browsable(false)]
52 | [EditorBrowsable(EditorBrowsableState.Never)]
53 | public Rectangle ControlBounds => new Rectangle(Point.Empty, Size);
54 |
55 | #endregion
56 |
57 | #region Methods
58 |
59 | protected override void OnMouseDown(MouseEventArgs mevent)
60 | {
61 | base.OnMouseDown(mevent);
62 | Invalidate();
63 | }
64 |
65 | protected override void OnMouseUp(MouseEventArgs mevent)
66 | {
67 | base.OnMouseUp(mevent);
68 | Invalidate();
69 | }
70 |
71 | protected override void OnPaint(PaintEventArgs pevent)
72 | {
73 | var cursorLoc = PointToClient(Cursor.Position);
74 | base.OnPaint(pevent);
75 | using (var primary = new SolidBrush(ColorScheme.PrimaryColor))
76 | {
77 | using (var mouseDown = new SolidBrush(ColorScheme.MouseDownColor))
78 | {
79 | using (var mouseHover = new SolidBrush(ColorScheme.MouseHoverColor))
80 | {
81 | var isHover = DisplayRectangle.Contains(cursorLoc);
82 | var isDown = MouseButtons == MouseButtons.Left;
83 | pevent.Graphics.FillRectangle(
84 | isDown && isHover && !DesignMode ? mouseDown : isHover && !DesignMode ? mouseHover : primary,
85 | ControlBounds);
86 | using (var sF = ControlPaintWrapper.StringFormatForAlignment(TextAlign))
87 | {
88 | using (var brush = new SolidBrush(ColorScheme.ForegroundColor))
89 | {
90 | pevent.Graphics.DrawString(Text, Font, brush, DisplayRectangle, sF);
91 | }
92 | }
93 | }
94 | }
95 | }
96 | }
97 |
98 | #endregion
99 | }
100 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/Controls/ModernShadowPanel.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Utils;
2 | using System;
3 | using System.Drawing;
4 | using System.Windows.Forms;
5 |
6 | namespace NickAc.ModernUIDoneRight.Controls
7 | {
8 | public class ModernShadowPanel : Panel
9 | {
10 | private Bitmap FrozenImage { get; set; }
11 |
12 | public ModernShadowPanel()
13 | {
14 | SetStyle(ControlStyles.AllPaintingInWmPaint, true);
15 | SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
16 | }
17 |
18 | public void Freeze()
19 | {
20 | FrozenImage = new Bitmap(Size.Width, Size.Height);
21 | using (var g = Graphics.FromImage(FrozenImage)) {
22 | DrawControlShadow(g);
23 | }
24 | Refresh();
25 | }
26 |
27 | public void Unfreeze()
28 | {
29 | FrozenImage = null;
30 | Refresh();
31 | }
32 |
33 | protected override void OnSizeChanged(EventArgs e)
34 | {
35 | base.OnSizeChanged(e);
36 | if (FrozenImage != null)
37 | Freeze();
38 | }
39 |
40 | protected override void OnControlAdded(ControlEventArgs e)
41 | {
42 | base.OnControlAdded(e);
43 | if (FrozenImage != null)
44 | Freeze();
45 | }
46 |
47 | protected override void OnControlRemoved(ControlEventArgs e)
48 | {
49 | base.OnControlRemoved(e);
50 | if (FrozenImage != null)
51 | Freeze();
52 | }
53 |
54 | protected override void OnPaint(PaintEventArgs e)
55 | {
56 | base.OnPaint(e);
57 | if (FrozenImage != null) {
58 | e.Graphics.DrawImage(FrozenImage, Point.Empty);
59 | return;
60 | }
61 | DrawControlShadow(e.Graphics);
62 | }
63 |
64 | private const int SHADOW_OFFSET = 3;
65 | private const int HALF_SHADOW_OFFSET = SHADOW_OFFSET / 2;
66 | private const int HALF_HALF_SHADOW_OFFSET = HALF_SHADOW_OFFSET / 2;
67 | private void DrawControlShadow(Graphics g)
68 | {
69 | using (var brush = new SolidBrush(Color.FromArgb(150, Color.Black))) {
70 | using (var img = new Bitmap(Width, Height)) {
71 | using (var gp = Graphics.FromImage(img)) {
72 | foreach (Control c in Controls) {
73 | //gp.DrawRoundedRectangle(rInner, 5, Pens.Transparent, Color.Black);
74 | gp.FillRectangle(brush, Rectangle.Inflate(c.Bounds, HALF_SHADOW_OFFSET, HALF_SHADOW_OFFSET));
75 | //ShadowUtils.DrawOutsetShadow(gp, Color.Black, 0, 0, 20, 1, c);
76 | }
77 | }
78 | var gaussian = new GaussianBlur(img);
79 | using (var result = gaussian.Process(SHADOW_OFFSET)) {
80 | g.DrawImageUnscaled(result, Point.Empty);
81 | }
82 | }
83 | }
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/Controls/ModernTileReborn.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Objects;
2 | using NickAc.ModernUIDoneRight.Utils;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Drawing;
7 | using System.Drawing.Drawing2D;
8 | using System.Windows.Forms;
9 |
10 | namespace NickAc.ModernUIDoneRight.Controls
11 | {
12 | ///
13 | /// TilePanel Reborn.
14 | ///
15 | public class TilePanelReborn : Control
16 | {
17 | #region Fields
18 |
19 | private bool brandedTile;
20 |
21 | private bool canBeHovered;
22 |
23 | private bool checkable;
24 |
25 | private bool hasDrawn;
26 |
27 | private Image image;
28 |
29 | private bool isHovered;
30 |
31 | private Color lightBackColor;
32 |
33 | private Color lightlightBackColor;
34 |
35 | private List texts = new List();
36 |
37 | #endregion
38 |
39 | #region Constructors
40 |
41 | public TilePanelReborn()
42 | {
43 | DoubleBuffered = true;
44 | SetStyle(ControlStyles.AllPaintingInWmPaint, true);
45 | }
46 |
47 | #endregion
48 |
49 | #region Properties
50 | public override Color BackColor {
51 | get {
52 | return base.BackColor;
53 | }
54 | set {
55 | base.BackColor = value;
56 | lightBackColor = ControlPaint.Light(value);
57 | lightlightBackColor = ControlPaint.LightLight(value);
58 | }
59 | }
60 |
61 | public bool BrandedTile {
62 | get {
63 | return brandedTile;
64 | }
65 | set {
66 | brandedTile = value;
67 | Refresh();
68 | }
69 | }
70 |
71 | public bool CanBeHovered {
72 | get {
73 | return canBeHovered;
74 | }
75 | set {
76 | canBeHovered = value;
77 | //UpdateParentHoverEvent(value);
78 | }
79 | }
80 |
81 | public bool Checkable {
82 | get { return checkable; }
83 | set {
84 | checkable = value;
85 | UpdateSurface();
86 | Refresh();
87 | }
88 | }
89 |
90 | public bool Flat { get; set; }
91 | public Image Image {
92 | get {
93 | return image;
94 | }
95 | set {
96 | image = value;
97 | UpdateSurface();
98 | Refresh();
99 | }
100 | }
101 |
102 | [Browsable(true)]
103 | public override string Text {
104 | get {
105 | return base.Text;
106 | }
107 | set {
108 | base.Text = value;
109 | Refresh();
110 | }
111 | }
112 |
113 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
114 | public List Texts {
115 | get {
116 | return texts;
117 | }
118 | set {
119 | texts = value;
120 | }
121 | }
122 |
123 | #endregion
124 |
125 | #region Methods
126 |
127 | public Rectangle GetImageRect()
128 | {
129 | if (brandedTile)
130 | return DisplayRectangle;
131 |
132 | return new Rectangle(0, 0, GetPercentage(Width, 50), GetPercentage(Height, 50));
133 | }
134 |
135 | public Rectangle GetOuterRectangle()
136 | {
137 | var rectangle = Bounds;
138 | rectangle.Inflate(3, 3);
139 | return rectangle;
140 | }
141 |
142 | public int GetPercentage(int size, int percent)
143 | {
144 | return size * percent / 100;
145 | }
146 |
147 | public Rectangle GetTextRectangle()
148 | {
149 | var rectangle = Rectangle.FromLTRB(8, Height - 32, Width - 8, Height - 8);
150 | return rectangle;
151 | }
152 |
153 | protected override void OnMouseEnter(EventArgs e)
154 | {
155 | base.OnMouseEnter(e);
156 | isHovered = true;
157 | if (CanBeHovered) {
158 | Parent.Invalidate(GetOuterRectangle());
159 | }
160 | }
161 |
162 | protected override void OnMouseLeave(EventArgs e)
163 | {
164 | base.OnMouseLeave(e);
165 | isHovered = false;
166 | if (CanBeHovered) {
167 | Parent.Invalidate(GetOuterRectangle());
168 | }
169 | }
170 |
171 | protected override void OnPaint(PaintEventArgs e)
172 | {
173 | if (!hasDrawn) {
174 | hasDrawn = true;
175 | OnLoad();
176 | }
177 | //Draw the outer Rectangle
178 | using (var solidBrush = new SolidBrush(lightlightBackColor)) {
179 | e.Graphics.FillRectangle(solidBrush, DisplayRectangle);
180 | }
181 |
182 | //Draw the inside color
183 | Rectangle displayRectangle = DisplayRectangle;
184 | displayRectangle.Inflate(-1, -1);
185 | using (var solidBrush = new SolidBrush(BackColor)) {
186 | e.Graphics.FillRectangle(solidBrush, DisplayRectangle);
187 | }
188 | if (!Flat) {
189 | //Draw gradient
190 | using (LinearGradientBrush brush = new LinearGradientBrush(displayRectangle, Color.FromArgb(75, 0, 0, 0), Color.FromArgb(7, 0, 0, 0), LinearGradientMode.Horizontal)) {
191 | e.Graphics.FillRectangle(brush, displayRectangle);
192 | }
193 | }
194 | else {
195 | using (SolidBrush sb = new SolidBrush(Color.FromArgb(35, Color.Black))) {
196 | e.Graphics.FillRectangle(sb, displayRectangle);
197 | }
198 | }
199 |
200 | if (Image != null) {
201 | Rectangle imgRect = GetImageRect();
202 | //Draw Image
203 | if (!brandedTile) {
204 | ControlPaintWrapper.ZoomDrawImage(e.Graphics, Image, imgRect.Center(Rectangle.FromLTRB(displayRectangle.Left, displayRectangle.Top, displayRectangle.Right, ((string.Empty.Equals(Text.Trim()) ? displayRectangle.Bottom : GetTextRectangle().Top)))));
205 | }
206 | else {
207 | e.Graphics.DrawImage(image, imgRect);
208 | }
209 | }
210 | if (!brandedTile) {
211 | using (var sb = new SolidBrush(ForeColor)) {
212 | using (var tF = ControlPaintWrapper.CreateStringFormat(this, ContentAlignment.BottomLeft, false)) {
213 | tF.FormatFlags = tF.FormatFlags | StringFormatFlags.NoWrap;
214 | e.Graphics.DrawString(Text, Font, sb, GetTextRectangle(), tF);
215 | foreach (var t in texts) {
216 | if (t != null) {
217 | e.Graphics.DrawString(t.Text, t.Font, sb, t.Location.X, t.Location.Y);
218 | }
219 | }
220 | }
221 | }
222 | }
223 | }
224 |
225 | protected void OnPaintOuterRectParent(object sender, PaintEventArgs pevent)
226 | {
227 | if (isHovered && CanBeHovered) {
228 | using (var br = new SolidBrush(lightBackColor)) {
229 | pevent.Graphics.FillRectangle(br, GetOuterRectangle());
230 | }
231 | }
232 | }
233 |
234 | protected void UpdateSurface()
235 | {
236 | Refresh();
237 | }
238 |
239 | private void OnLoad()
240 | {
241 | if (Parent != null) {
242 | Parent.Paint += OnPaintOuterRectParent;
243 | }
244 | }
245 |
246 | #endregion
247 | }
248 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/Controls/ModernToolTIp.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Drawing.Drawing2D;
4 | using System.Windows.Forms;
5 | using NickAc.ModernUIDoneRight.Forms;
6 | using NickAc.ModernUIDoneRight.Objects;
7 |
8 | namespace NickAc.ModernUIDoneRight.Controls
9 | {
10 | public class ModernToolTip : ToolTip
11 | {
12 | #region Fields
13 | private readonly int _opacity = 128;
14 | private Font _font = new Font("Segoe UI", 10F, FontStyle.Regular, GraphicsUnit.Point);
15 | private Size _size = new Size(300, 100);
16 | private bool _autoSize = true;
17 | private int _margin = 5;
18 | private string _caption;
19 | #endregion
20 |
21 | #region Properties
22 | public Font Font { get => _font; set => _font = value; }
23 | public Size Size { get => _size; set => _size = value; }
24 | public int Margin { get => _margin; set => _margin = value; }
25 | public bool AutoSize { get => _autoSize; set => _autoSize = value; }
26 | internal string Caption { set => _caption = value; }
27 | #endregion
28 |
29 | public ModernToolTip()
30 | {
31 | this.OwnerDraw = true;
32 | this.Draw += Handle_Draw;
33 | this.Popup += Handle_Popup;
34 | }
35 |
36 | void Handle_Popup(object sender, PopupEventArgs e)
37 | {
38 | if (_autoSize)
39 | {
40 | Graphics g = Graphics.FromImage(new Bitmap(1, 1));
41 | SizeF size = g.MeasureString(_caption, Font, Size.Width);
42 | size.Width += Margin * 2;
43 | size.Height += Margin * 2;
44 | e.ToolTipSize = new Size((int)size.Width, (int)size.Height);
45 | }
46 | else
47 | {
48 | e.ToolTipSize = Size;
49 | }
50 | }
51 |
52 | private void Handle_Draw(object sender, DrawToolTipEventArgs e)
53 | {
54 | if (string.IsNullOrEmpty(e.ToolTipText))
55 | {
56 | return;
57 | }
58 |
59 | ColorScheme colorScheme = GetColorScheme(e.AssociatedControl);
60 | Graphics g = e.Graphics;
61 |
62 | SolidBrush brush = new SolidBrush(Color.FromArgb(_opacity, colorScheme.SecondaryColor));
63 | g.FillRectangle(brush, e.Bounds);
64 |
65 | Rectangle border = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width - 1, e.Bounds.Height - 1);
66 | g.DrawRectangle(new Pen(colorScheme.PrimaryColor, 1), border);
67 |
68 | Rectangle textRect = new Rectangle(e.Bounds.X + Margin, e.Bounds.Y + Margin, e.Bounds.Width - Margin, e.Bounds.Height - Margin);
69 | SolidBrush textBrush = new SolidBrush(colorScheme.ForegroundColor);
70 | g.DrawString(e.ToolTipText, Font, textBrush, textRect);
71 |
72 | brush.Dispose();
73 | }
74 |
75 | private ColorScheme GetColorScheme(Control associatedControl)
76 | {
77 | if (associatedControl != null)
78 | {
79 | if (associatedControl.FindForm() is ModernForm form)
80 | {
81 | return form.ColorScheme;
82 | }
83 | }
84 | return DefaultColorSchemes.Blue;
85 | }
86 |
87 |
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Controls/SidebarControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Windows.Forms;
6 | using NickAc.ModernUIDoneRight.Forms;
7 | using NickAc.ModernUIDoneRight.Objects;
8 | using static NickAc.ModernUIDoneRight.Utils.Animation;
9 | using static NickAc.ModernUIDoneRight.Utils.ShadowUtils;
10 |
11 | namespace NickAc.ModernUIDoneRight.Controls
12 | {
13 | ///
14 | /// The sidebar control (use with AppBar)
15 | ///
16 | public class SidebarControl : Control, IShadowController
17 | {
18 | private ColorScheme _colorScheme;
19 |
20 | private bool _isAnimating;
21 | private bool _wasPainted;
22 |
23 | public SidebarControl()
24 | {
25 | Dock = DockStyle.Left;
26 | }
27 |
28 | public ColorScheme ColorScheme
29 | {
30 | get => Parent is ModernForm ? ((ModernForm) Parent).ColorScheme : _colorScheme;
31 | set => _colorScheme = value;
32 | }
33 |
34 | private int OriginalWidth { get; set; } = -1;
35 | public bool IsClosed { get; set; }
36 | public int TopBarSize { get; set; } = 100;
37 | public Color TopBarColor { get; set; } = Color.FromArgb(189, 189, 189);
38 | public int TopBarSpacing { get; set; } = 32;
39 |
40 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
41 | public IList Items { get; set; } = new List();
42 |
43 | public bool ShouldShowShadow()
44 | {
45 | return !(_isAnimating || IsClosed);
46 | }
47 |
48 |
49 | ///
50 | /// Called to signal to subscribers that
51 | ///
52 | public event EventHandler AnimationStart;
53 | protected virtual void OnAnimationStart(EventArgs e)
54 | {
55 | EventHandler eh = AnimationStart;
56 |
57 | eh?.Invoke(this, e);
58 | }
59 |
60 | ///
61 | /// Called to signal to subscribers that Description
62 | ///
63 | public event EventHandler AnimationStop;
64 | protected virtual void OnAnimationStop(EventArgs e)
65 | {
66 | EventHandler eh = AnimationStop;
67 |
68 | eh?.Invoke(this, e);
69 | }
70 |
71 |
72 | protected override void OnPaintBackground(PaintEventArgs pevent)
73 | {
74 | base.OnPaintBackground(pevent);
75 | if (TopBarSize <= 0) return;
76 | using (var sB = new SolidBrush(TopBarColor))
77 | {
78 | pevent.Graphics.FillRectangle(sB, 0, 0, Width, TopBarSize);
79 | }
80 | }
81 |
82 | protected override void OnPaint(PaintEventArgs e)
83 | {
84 | base.OnPaint(e);
85 | if (!_wasPainted)
86 | {
87 | if (IsClosed && !DesignMode)
88 | {
89 | OriginalWidth = Width;
90 | Width = 0;
91 | }
92 |
93 | _wasPainted = true;
94 | this.CreateDropShadow();
95 | }
96 |
97 | if (IsClosed || _isAnimating) return;
98 |
99 | var yPos = TopBarSize + TopBarSpacing;
100 | using (var altColor = new SolidBrush(ColorScheme.SecondaryColor))
101 | {
102 | using (var backColor = new SolidBrush(BackColor))
103 | {
104 | foreach (var item in Items)
105 | {
106 | item.MeasureItem(this, e.Graphics, out var height);
107 | if (height < 1) continue;
108 | var itemRect = new Rectangle(0, yPos, Width, height);
109 |
110 | using (var bmp = new Bitmap(Width, height))
111 | {
112 | using (var g = Graphics.FromImage(bmp))
113 | {
114 | var mouseHere = itemRect.Contains(PointToClient(Cursor.Position)) &&
115 | MouseButtons == MouseButtons.Left;
116 | g.FillRectangle(mouseHere ? altColor : backColor, 0, 0, Width, height);
117 | item.DrawItem(this, g, new Size(Width, height), mouseHere);
118 | }
119 |
120 | e.Graphics.DrawImageUnscaled(bmp, 0, yPos);
121 | yPos += height;
122 | }
123 | }
124 | }
125 | }
126 | }
127 |
128 | protected override void OnMouseDown(MouseEventArgs e)
129 | {
130 | base.OnMouseDown(e);
131 | Refresh();
132 | }
133 |
134 | protected override void OnMouseUp(MouseEventArgs e)
135 | {
136 | base.OnMouseUp(e);
137 | Refresh();
138 | var yPos = TopBarSize + TopBarSpacing;
139 | using (var bmpOrig = new Bitmap(Width, Height))
140 | {
141 | using (var g = Graphics.FromImage(bmpOrig))
142 | {
143 | foreach (var item in Items)
144 | {
145 | item.MeasureItem(this, g, out var height);
146 | if (height < 1) continue;
147 | var itemRect = new Rectangle(0, yPos, Width, height);
148 |
149 | var mouseHere = itemRect.Contains(e.Location) && e.Button == MouseButtons.Left;
150 | if (mouseHere)
151 | {
152 | item.OnClick(e);
153 | return;
154 | }
155 |
156 | yPos += height;
157 | }
158 | }
159 | }
160 | }
161 |
162 | public void ShowSidebar()
163 | {
164 | if (!IsClosed) return;
165 | var originalRect = Rectangle.FromLTRB(Bounds.Left, Bounds.Top, Bounds.Right + 8 * 2, Bounds.Bottom);
166 | if (OriginalWidth == -1)
167 | OriginalWidth = Width;
168 | Width = 0;
169 | IsClosed = false;
170 | var animIn = new AnimationBuilder()
171 | .WithAction(a => { Width++; })
172 | .WithCountLimit(OriginalWidth)
173 | .WithMultiplier(7)
174 | .WithInterval(8)
175 | .Build();
176 | Show();
177 | animIn.End(a =>
178 | {
179 | _isAnimating = false;
180 | Parent?.ResumeLayout();
181 | Parent?.Refresh();
182 | OnAnimationStop(EventArgs.Empty);
183 | });
184 | OnAnimationStart(EventArgs.Empty);
185 | _isAnimating = true;
186 | Parent?.Invalidate(originalRect);
187 | Parent?.SuspendLayout();
188 | animIn.Start();
189 | }
190 |
191 | public void HideSidebar()
192 | {
193 | if (IsClosed) return;
194 | var originalRect = Rectangle.FromLTRB(Bounds.Left, Bounds.Top, Bounds.Right + 8 * 2, Bounds.Bottom);
195 | if (OriginalWidth == -1)
196 | OriginalWidth = Width;
197 | IsClosed = true;
198 | var animOut = new AnimationBuilder()
199 | .WithAction(a => Width--)
200 | .WithCountLimit(OriginalWidth)
201 | .WithMultiplier(7)
202 | .WithInterval(8)
203 | .Build();
204 | animOut.End(a =>
205 | {
206 | Hide();
207 | _isAnimating = false;
208 | Parent?.ResumeLayout();
209 | OnAnimationStop(EventArgs.Empty);
210 | });
211 | OnAnimationStart(EventArgs.Empty);
212 | _isAnimating = true;
213 | Parent?.Invalidate(originalRect);
214 | Parent?.SuspendLayout();
215 | animOut.Start();
216 | }
217 |
218 | public abstract class SideBarItem
219 | {
220 | ///
221 | /// Called to signal to subscribers that the item was clicked
222 | ///
223 | public event MouseEventHandler Click;
224 |
225 | public abstract void DrawItem(SidebarControl c, Graphics g, Size itemSize, bool isSelected = false);
226 | public abstract void MeasureItem(SidebarControl c, Graphics g, out int itemHeight);
227 |
228 | public virtual void OnClick(MouseEventArgs e)
229 | {
230 | var eh = Click;
231 | eh?.Invoke(this, e);
232 | }
233 | }
234 | }
235 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/Forms/AlphaWindow.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2002 Rui Godinho Lopes
3 | // All rights reserved.
4 | //
5 | // This source file(s) may be redistributed unmodified by any means
6 | // PROVIDING they are not sold for profit without the authors expressed
7 | // written consent, and providing that this notice and the authors name
8 | // and all copyright notices remain intact.
9 | //
10 | // Any use of the software in source or binary forms, with or without
11 | // modification, must include, in the user documentation ("About" box and
12 | // printed documentation) and internal comments to the code, notices to
13 | // the end user as follows:
14 | //
15 | // "Portions Copyright © 2002 Rui Godinho Lopes"
16 | //
17 | // An email letting me know that you are using it would be nice as well.
18 | // That's not much to ask considering the amount of work that went into
19 | // this.
20 | //
21 | // THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED. USE IT AT YOUT OWN RISK. THE AUTHOR ACCEPTS NO
23 | // LIABILITY FOR ANY DATA DAMAGE/LOSS THAT THIS PRODUCT MAY CAUSE.
24 | //
25 |
26 | using System;
27 | using System.Drawing;
28 | using System.Drawing.Imaging;
29 | using System.Windows.Forms;
30 | using System.Runtime.InteropServices;
31 |
32 |
33 | // a static class to expose needed win32 gdi functions.
34 | class Win32 {
35 |
36 | public enum Bool {
37 | False= 0,
38 | True
39 | };
40 |
41 | [StructLayout(LayoutKind.Sequential)]
42 | public struct Point {
43 | public Int32 x;
44 | public Int32 y;
45 |
46 | public Point(Int32 x, Int32 y) { this.x= x; this.y= y; }
47 | }
48 |
49 | [StructLayout(LayoutKind.Sequential)]
50 | public struct Size {
51 | public Int32 cx;
52 | public Int32 cy;
53 |
54 | public Size(Int32 cx, Int32 cy) { this.cx= cx; this.cy= cy; }
55 | }
56 |
57 | [StructLayout(LayoutKind.Sequential, Pack=1)]
58 | struct ARGB {
59 | public byte Blue;
60 | public byte Green;
61 | public byte Red;
62 | public byte Alpha;
63 | }
64 |
65 | [StructLayout(LayoutKind.Sequential, Pack=1)]
66 | public struct BLENDFUNCTION {
67 | public byte BlendOp;
68 | public byte BlendFlags;
69 | public byte SourceConstantAlpha;
70 | public byte AlphaFormat;
71 | }
72 |
73 |
74 | public const Int32 ULW_COLORKEY = 0x00000001;
75 | public const Int32 ULW_ALPHA = 0x00000002;
76 | public const Int32 ULW_OPAQUE = 0x00000004;
77 |
78 | public const byte AC_SRC_OVER = 0x00;
79 | public const byte AC_SRC_ALPHA = 0x01;
80 |
81 |
82 | [DllImport("user32.dll", ExactSpelling=true, SetLastError=true)]
83 | public static extern Bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);
84 |
85 | [DllImport("user32.dll", ExactSpelling=true, SetLastError=true)]
86 | public static extern IntPtr GetDC(IntPtr hWnd);
87 |
88 | [DllImport("user32.dll", ExactSpelling=true)]
89 | public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
90 |
91 | [DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
92 | public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
93 |
94 | [DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
95 | public static extern Bool DeleteDC(IntPtr hdc);
96 |
97 | [DllImport("gdi32.dll", ExactSpelling=true)]
98 | public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
99 |
100 | [DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
101 | public static extern Bool DeleteObject(IntPtr hObject);
102 | }
103 |
104 |
105 | /// PerPixel forms should derive from this base class
106 | /// Rui Godinho Lopesrui@ruilopes.com
107 | public class PerPixelAlphaForm : Form {
108 |
109 | /// Changes the current bitmap.
110 | public void SetBitmap(Bitmap bitmap) {
111 | SetBitmap(bitmap, 255);
112 | }
113 |
114 | /// Changes the current bitmap with a custom opacity level. Here is where all happens!
115 | public void SetBitmap(Bitmap bitmap, byte opacity) {
116 | if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
117 | throw new ApplicationException("The bitmap must be 32ppp with alpha-channel.");
118 |
119 | // The ideia of this is very simple,
120 | // 1. Create a compatible DC with screen;
121 | // 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC;
122 | // 3. Call the UpdateLayeredWindow.
123 |
124 | IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
125 | IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
126 | IntPtr hBitmap = IntPtr.Zero;
127 | IntPtr oldBitmap = IntPtr.Zero;
128 |
129 | try {
130 | hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap
131 | oldBitmap = Win32.SelectObject(memDc, hBitmap);
132 |
133 | Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height);
134 | Win32.Point pointSource = new Win32.Point(0, 0);
135 | Win32.Point topPos = new Win32.Point(Left, Top);
136 | Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
137 | blend.BlendOp = Win32.AC_SRC_OVER;
138 | blend.BlendFlags = 0;
139 | blend.SourceConstantAlpha = opacity;
140 | blend.AlphaFormat = Win32.AC_SRC_ALPHA;
141 |
142 | Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA);
143 | }
144 | finally {
145 | Win32.ReleaseDC(IntPtr.Zero, screenDc);
146 | if (hBitmap != IntPtr.Zero) {
147 | Win32.SelectObject(memDc, oldBitmap);
148 | //Windows.DeleteObject(hBitmap); // The documentation says that we have to use the Windows.DeleteObject... but since there is no such method I use the normal DeleteObject from Win32 GDI and it's working fine without any resource leak.
149 | Win32.DeleteObject(hBitmap);
150 | }
151 | Win32.DeleteDC(memDc);
152 | }
153 | }
154 |
155 | protected override CreateParams CreateParams {
156 | get {
157 | CreateParams cp = base.CreateParams;
158 | cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
159 | return cp;
160 | }
161 | }
162 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/Forms/GlowShadowForm.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) NickAc. All rights reserved.
3 | // Licensed under the MIT License. See LICENSE file in the project root for full license information.
4 | //
5 |
6 | namespace NickAc.ModernUIDoneRight.Forms
7 | {
8 | public class GlowShadowForm : PerPixelAlphaForm
9 | {
10 |
11 | }
12 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/Forms/GlowShadowFormAaaaaa.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Drawing.Drawing2D;
4 | using System.Drawing.Imaging;
5 | using System.Runtime.InteropServices;
6 | using System.Windows.Forms;
7 |
8 | namespace NickAc.ModernUIDoneRight.Forms
9 | {
10 | ///
11 | /// Dropshadow.
12 | /// Add a shadow to a winform
13 | ///
14 | public class GlowShadowFormAaaaaa : Form
15 | {
16 | private Bitmap _shadowBitmap;
17 | private Color _shadowColor;
18 | private int _shadowH;
19 | private byte _shadowOpacity = 255;
20 | private int _shadowV;
21 |
22 | public GlowShadowFormAaaaaa(Form f)
23 | {
24 | Owner = f;
25 | ShadowColor = Color.Black;
26 |
27 | // default style
28 | FormBorderStyle = FormBorderStyle.None;
29 | ShowInTaskbar = false;
30 |
31 | // bind event
32 | Owner.LocationChanged += UpdateLocation;
33 | Owner.FormClosing += (sender, eventArgs) => Close();
34 | Owner.VisibleChanged += (sender, eventArgs) =>
35 | {
36 | if (Owner != null)
37 | Visible = Owner.Visible;
38 | };
39 |
40 | Owner.Activated += (sender, args) => Owner.BringToFront();
41 | }
42 |
43 | public Color ShadowColor
44 | {
45 | get { return _shadowColor; }
46 | set
47 | {
48 | _shadowColor = value;
49 | _shadowOpacity = _shadowColor.A;
50 | }
51 | }
52 |
53 | public Bitmap ShadowBitmap
54 | {
55 | get { return _shadowBitmap; }
56 | set
57 | {
58 | _shadowBitmap = value;
59 | SetBitmap(_shadowBitmap, ShadowOpacity);
60 | }
61 | }
62 |
63 | public byte ShadowOpacity
64 | {
65 | get { return _shadowOpacity; }
66 | set
67 | {
68 | _shadowOpacity = value;
69 | SetBitmap(ShadowBitmap, _shadowOpacity);
70 | }
71 | }
72 |
73 | public int ShadowH
74 | {
75 | get { return _shadowH; }
76 | set
77 | {
78 | _shadowH = value;
79 | RefreshShadow(false);
80 | }
81 | }
82 |
83 | ///
84 | /// Offset X relate to Owner
85 | ///
86 | public int OffsetX
87 | {
88 | get { return ShadowH - (ShadowBlur + ShadowSpread); }
89 | }
90 |
91 | ///
92 | /// Offset Y relate to Owner
93 | ///
94 | public int OffsetY
95 | {
96 | get { return ShadowV - (ShadowBlur + ShadowSpread); }
97 | }
98 |
99 | public new int Width
100 | {
101 | get { return Owner.Width + (ShadowSpread + ShadowBlur) * 2; }
102 | }
103 |
104 | public new int Height
105 | {
106 | get { return Owner.Height + (ShadowSpread + ShadowBlur) * 2; }
107 | }
108 |
109 | public int ShadowV
110 | {
111 | get { return _shadowV; }
112 | set
113 | {
114 | _shadowV = value;
115 | RefreshShadow(false);
116 | }
117 | }
118 |
119 | public int ShadowBlur { get; set; }
120 | public int ShadowSpread { get; set; }
121 |
122 | protected override CreateParams CreateParams
123 | {
124 | get
125 | {
126 | CreateParams cp = base.CreateParams;
127 | cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
128 | return cp;
129 | }
130 | }
131 |
132 | public static Bitmap DrawShadowBitmap(int width, int height, int borderRadius, int blur, int spread,
133 | Color color)
134 | {
135 | int ex = blur + spread;
136 | int w = width + ex * 2;
137 | int h = height + ex * 2;
138 | int solidW = width + spread * 2;
139 | int solidH = height + spread * 2;
140 |
141 | var bitmap = new Bitmap(w, h);
142 | Graphics g = Graphics.FromImage(bitmap);
143 | // fill background
144 | //g.FillRectangle(new SolidBrush(color)
145 | // , blur, blur, width + spread * 2 + 1, height + spread * 2 + 1);
146 | // +1 to fill the gap
147 |
148 | if (blur > 0)
149 | {
150 | // four dir gradiant
151 | {
152 | // left
153 | var brush = new LinearGradientBrush(new Point(0, 0), new Point(blur, 0), Color.Transparent, color);
154 | // will thorw ArgumentException
155 | // brush.WrapMode = WrapMode.Clamp;
156 |
157 |
158 | g.FillRectangle(brush, blur, blur, blur, solidH);
159 | // up
160 | brush.RotateTransform(90);
161 | g.FillRectangle(brush, blur, 0, solidW, blur);
162 |
163 | // right
164 | // make sure parttern is currect
165 | brush.ResetTransform();
166 | brush.TranslateTransform(w % blur, h % blur);
167 |
168 | brush.RotateTransform(180);
169 | g.FillRectangle(brush, w - blur, blur, blur, solidH);
170 | // down
171 | brush.RotateTransform(90);
172 | g.FillRectangle(brush, blur, h - blur, solidW, blur);
173 | }
174 |
175 |
176 | // four corner
177 | {
178 | var gp = new GraphicsPath();
179 | //gp.AddPie(0,0,blur*2,blur*2, 180, 90);
180 | gp.AddEllipse(0, 0, blur * 2, blur * 2);
181 |
182 |
183 | var pgb = new PathGradientBrush(gp);
184 | pgb.CenterColor = color;
185 | pgb.SurroundColors = new[] {Color.Transparent};
186 | pgb.CenterPoint = new Point(blur, blur);
187 |
188 | // lt
189 | g.FillPie(pgb, 0, 0, blur * 2, blur * 2, 180, 90);
190 | // rt
191 | var matrix = new Matrix();
192 | matrix.Translate(w - blur * 2, 0);
193 |
194 | pgb.Transform = matrix;
195 | //pgb.Transform.Translate(w-blur*2, 0);
196 | g.FillPie(pgb, w - blur * 2, 0, blur * 2, blur * 2, 270, 90);
197 | // rb
198 | matrix.Translate(0, h - blur * 2);
199 | pgb.Transform = matrix;
200 | g.FillPie(pgb, w - blur * 2, h - blur * 2, blur * 2, blur * 2, 0, 90);
201 | // lb
202 | matrix.Reset();
203 | matrix.Translate(0, h - blur * 2);
204 | pgb.Transform = matrix;
205 | g.FillPie(pgb, 0, h - blur * 2, blur * 2, blur * 2, 90, 90);
206 | }
207 | }
208 |
209 | //
210 | return bitmap;
211 | }
212 |
213 | public void UpdateLocation(Object sender = null, EventArgs eventArgs = null)
214 | {
215 | Point pos = Owner.Location;
216 |
217 | pos.Offset(OffsetX, OffsetY);
218 | Location = pos;
219 | }
220 |
221 | ///
222 | /// Refresh shadow.
223 | ///
224 | /// (optional) redraw the background bitmap.
225 | public void RefreshShadow(bool redraw = true)
226 | {
227 | if (redraw)
228 | {
229 | //ShadowBitmap = DrawShadow();
230 | ShadowBitmap = DrawShadowBitmap(Owner.Width, Owner.Height, 0, ShadowBlur, ShadowSpread, ShadowColor);
231 | }
232 |
233 | //SetBitmap(ShadowBitmap, ShadowOpacity);
234 | UpdateLocation();
235 |
236 | //Region r = Region.FromHrgn(Win32.CreateRoundRectRgn(0, 0, Width, Height, BorderRadius, BorderRadius));
237 | var r = new Region(new Rectangle(0, 0, Width, Height));
238 | Region or;
239 | if (Owner.Region == null)
240 | or = new Region(Owner.ClientRectangle);
241 | else
242 | or = Owner.Region.Clone();
243 |
244 | or.Translate(-OffsetX, -OffsetY);
245 | r.Exclude(or);
246 | Region = r;
247 |
248 | Owner.Refresh();
249 | }
250 |
251 | /// Changes the current bitmap with a custom opacity level. Here is where all happens!
252 | public void SetBitmap(Bitmap bitmap, byte opacity = 255)
253 | {
254 | if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
255 | throw new ApplicationException("The bitmap must be 32ppp with alpha-channel.");
256 |
257 | // The ideia of this is very simple,
258 | // 1. Create a compatible DC with screen;
259 | // 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC;
260 | // 3. Call the UpdateLayeredWindow.
261 |
262 | IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
263 | IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
264 | IntPtr hBitmap = IntPtr.Zero;
265 | IntPtr oldBitmap = IntPtr.Zero;
266 |
267 | try
268 | {
269 | hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap
270 | oldBitmap = Win32.SelectObject(memDc, hBitmap);
271 |
272 | var size = new Win32.Size(bitmap.Width, bitmap.Height);
273 | var pointSource = new Win32.Point(0, 0);
274 | var topPos = new Win32.Point(Left, Top);
275 | var blend = new Win32.BLENDFUNCTION();
276 | blend.BlendOp = Win32.AC_SRC_OVER;
277 | blend.BlendFlags = 0;
278 | blend.SourceConstantAlpha = opacity;
279 | blend.AlphaFormat = Win32.AC_SRC_ALPHA;
280 |
281 | Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend,
282 | Win32.ULW_ALPHA);
283 | }
284 | finally
285 | {
286 | Win32.ReleaseDC(IntPtr.Zero, screenDc);
287 | if (hBitmap != IntPtr.Zero)
288 | {
289 | Win32.SelectObject(memDc, oldBitmap);
290 | //Windows.DeleteObject(hBitmap); // The documentation says that we have to use the Windows.DeleteObject... but since there is no such method I use the normal DeleteObject from Win32 GDI and it's working fine without any resource leak.
291 | Win32.DeleteObject(hBitmap);
292 | }
293 |
294 | Win32.DeleteDC(memDc);
295 | }
296 | }
297 | }
298 |
299 |
300 | // class that exposes needed win32 gdi functions.
301 | internal static class Win32
302 | {
303 | public enum Bool
304 | {
305 | False = 0,
306 | True
307 | };
308 |
309 | public const Int32 ULW_COLORKEY = 0x00000001;
310 | public const Int32 ULW_ALPHA = 0x00000002;
311 | public const Int32 ULW_OPAQUE = 0x00000004;
312 |
313 | public const byte AC_SRC_OVER = 0x00;
314 | public const byte AC_SRC_ALPHA = 0x01;
315 |
316 | [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
317 | public static extern IntPtr CreateRoundRectRgn
318 | (
319 | int nLeftRect, // x-coordinate of upper-left corner
320 | int nTopRect, // y-coordinate of upper-left corner
321 | int nRightRect, // x-coordinate of lower-right corner
322 | int nBottomRect, // y-coordinate of lower-right corner
323 | int nWidthEllipse, // height of ellipse
324 | int nHeightEllipse // width of ellipse
325 | );
326 |
327 | [DllImport("user32.dll", SetLastError = true)]
328 | public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
329 |
330 | ///
331 | /// Changes an attribute of the specified window. The function also sets the 32-bit (long) value at the specified
332 | /// offset into the extra window memory.
333 | ///
334 | /// A handle to the window and, indirectly, the class to which the window belongs..
335 | ///
336 | /// The zero-based offset to the value to be set. Valid values are in the range zero through the
337 | /// number of bytes of extra window memory, minus the size of an integer. To set any other value, specify one of the
338 | /// following values: GWL_EXSTYLE, GWL_HINSTANCE, GWL_ID, GWL_STYLE, GWL_USERDATA, GWL_WNDPROC
339 | ///
340 | /// The replacement value.
341 | ///
342 | /// If the function succeeds, the return value is the previous value of the specified 32-bit integer.
343 | /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
344 | ///
345 | [DllImport("user32.dll")]
346 | public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
347 |
348 |
349 | [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
350 | public static extern Bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize,
351 | IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);
352 |
353 | [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
354 | public static extern IntPtr GetDC(IntPtr hWnd);
355 |
356 | [DllImport("user32.dll", ExactSpelling = true)]
357 | public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
358 |
359 | [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
360 | public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
361 |
362 | [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
363 | public static extern Bool DeleteDC(IntPtr hdc);
364 |
365 | [DllImport("gdi32.dll", ExactSpelling = true)]
366 | public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
367 |
368 | [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
369 | public static extern Bool DeleteObject(IntPtr hObject);
370 |
371 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
372 | private struct ARGB
373 | {
374 | public readonly byte Blue;
375 | public readonly byte Green;
376 | public readonly byte Red;
377 | public readonly byte Alpha;
378 | }
379 |
380 |
381 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
382 | public struct BLENDFUNCTION
383 | {
384 | public byte BlendOp;
385 | public byte BlendFlags;
386 | public byte SourceConstantAlpha;
387 | public byte AlphaFormat;
388 | }
389 |
390 | [StructLayout(LayoutKind.Sequential)]
391 | public struct Point
392 | {
393 | public Int32 x;
394 | public Int32 y;
395 |
396 | public Point(Int32 x, Int32 y)
397 | {
398 | this.x = x;
399 | this.y = y;
400 | }
401 | }
402 |
403 |
404 | [StructLayout(LayoutKind.Sequential)]
405 | public struct Size
406 | {
407 | public Int32 cx;
408 | public Int32 cy;
409 |
410 | public Size(Int32 cx, Int32 cy)
411 | {
412 | this.cx = cx;
413 | this.cy = cy;
414 | }
415 | }
416 | }
417 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/Forms/ModernForm.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Controls;
2 | using NickAc.ModernUIDoneRight.Native;
3 | using NickAc.ModernUIDoneRight.Objects;
4 | using NickAc.ModernUIDoneRight.Objects.Interaction;
5 | using NickAc.ModernUIDoneRight.Utils;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.ComponentModel;
9 | using System.Diagnostics;
10 | using System.Drawing;
11 | using System.Linq;
12 | using System.Windows.Forms;
13 |
14 | namespace NickAc.ModernUIDoneRight.Forms
15 | {
16 | public class ModernForm : Form
17 | {
18 | #region Fields
19 |
20 | ///
21 | /// The default height of the titlebar
22 | ///
23 | public const int DefaultTitlebarHeight = 32;
24 |
25 | ///
26 | /// The size of the border
27 | ///
28 | public const int SizingBorder = 7;
29 |
30 | private readonly List _titlebarButtons, _nativeTitlebarButtons;
31 | private ColorScheme _colorScheme;
32 | private Size _minimumSize = Size.Empty;
33 | private bool _mouseChanged;
34 | private WindowHitTestResult _windowHit = WindowHitTestResult.None;
35 |
36 | #endregion
37 |
38 | #region Constructors
39 |
40 | public ModernForm()
41 | {
42 | Font = SystemFonts.MessageBoxFont;
43 | ColorScheme = DefaultColorSchemes.Blue;
44 |
45 | DoubleBuffered = true;
46 | AutoScaleMode = AutoScaleMode.None;
47 |
48 | SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
49 | SetStyle(ControlStyles.AllPaintingInWmPaint, true);
50 | SetStyle(ControlStyles.ContainerControl, true);
51 | SetStyle(ControlStyles.ResizeRedraw, true);
52 |
53 | _titlebarButtons = new List();
54 | _nativeTitlebarButtons = GenerateNativeButtons(DefaultTitlebarHeight, this);
55 |
56 | BackColor = Color.White;
57 | FormBorderStyle = FormBorderStyle.None;
58 | }
59 |
60 | #endregion
61 |
62 | #region Properties
63 |
64 | public int HamburgerButtonSize { get; set; } = 32;
65 |
66 | [Browsable(false)]
67 | [EditorBrowsable(EditorBrowsableState.Never)]
68 | public bool IsSideBarAvailable => !IsAppBarAvailable && Controls.OfType().Any();
69 |
70 |
71 | public Rectangle HamburgerRectangle => IsSideBarAvailable
72 | ? Rectangle.FromLTRB(TextBarRectangle.Left - HamburgerButtonSize - 1, 0, TextBarRectangle.Left,
73 | TextBarRectangle.Bottom)
74 | : Rectangle.Empty;
75 |
76 | [Browsable(false)]
77 | [EditorBrowsable(EditorBrowsableState.Never)]
78 | public Rectangle BottomSide => Rectangle.FromLTRB(SizingBorder, FormBounds.Bottom - SizingBorder,
79 | FormBounds.Right - SizingBorder, FormBounds.Bottom);
80 |
81 | ///
82 | /// The color scheme on this window
83 | ///
84 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
85 | public ColorScheme ColorScheme
86 | {
87 | get => _colorScheme;
88 | set
89 | {
90 | _colorScheme = value;
91 | Refresh();
92 | }
93 | }
94 |
95 | public override Rectangle DisplayRectangle => Rectangle.FromLTRB(TitlebarRectangle.Left,
96 | TitlebarRectangle.Bottom, TitlebarRectangle.Right, FormBounds.Bottom - 1);
97 |
98 | ///
99 | /// The form bounds rectangle relative to 0,0
100 | ///
101 | [Browsable(false)]
102 | [EditorBrowsable(EditorBrowsableState.Never)]
103 | public Rectangle FormBounds => new Rectangle(Point.Empty, Size);
104 |
105 | [Browsable(false)]
106 | [EditorBrowsable(EditorBrowsableState.Never)]
107 | public bool IsAppBarAvailable => Controls.OfType().Any();
108 |
109 | [Browsable(false)]
110 | [EditorBrowsable(EditorBrowsableState.Never)]
111 | public Rectangle LeftBottom =>
112 | Rectangle.FromLTRB(0, FormBounds.Bottom - SizingBorder, SizingBorder, FormBounds.Bottom);
113 |
114 | [Browsable(false)]
115 | [EditorBrowsable(EditorBrowsableState.Never)]
116 | public Rectangle LeftSide =>
117 | Rectangle.FromLTRB(0, TitlebarRectangle.Bottom, SizingBorder, FormBounds.Bottom - SizingBorder);
118 |
119 | public override Size MaximumSize
120 | {
121 | get => Screen.GetWorkingArea(this).Size;
122 | set
123 | {
124 | value = Screen.GetWorkingArea(this).Size;
125 | base.MaximumSize = value;
126 | }
127 | }
128 |
129 | public override Size MinimumSize
130 | {
131 | get
132 | {
133 | if (_minimumSize.IsEmpty)
134 | {
135 | var v = GetTitleBarButtonsWidth();
136 | return new Size(v, TitlebarHeight + SizingBorder);
137 | }
138 |
139 | return _minimumSize;
140 | }
141 | set => _minimumSize = value;
142 | }
143 |
144 | [Browsable(false)]
145 | [EditorBrowsable(EditorBrowsableState.Never)]
146 | public Rectangle RightBottom => Rectangle.FromLTRB(FormBounds.Right - SizingBorder,
147 | FormBounds.Bottom - SizingBorder, FormBounds.Right, FormBounds.Bottom);
148 |
149 | [Browsable(false)]
150 | [EditorBrowsable(EditorBrowsableState.Never)]
151 | public Rectangle RightSide => Rectangle.FromLTRB(FormBounds.Right - SizingBorder, TitlebarRectangle.Bottom,
152 | FormBounds.Right, FormBounds.Bottom - SizingBorder);
153 |
154 | public ShadowType ShadowType { get; set; } = ShadowType.Default;
155 |
156 | public bool Sizable { get; set; } = true;
157 |
158 | public override string Text
159 | {
160 | get => base.Text;
161 | set
162 | {
163 | base.Text = value;
164 | Invalidate();
165 | }
166 | }
167 |
168 | ///
169 | /// Rectangle that represents the titlebar text
170 | ///
171 | [Browsable(false)]
172 | [EditorBrowsable(EditorBrowsableState.Never)]
173 | public Rectangle TextBarRectangle => Rectangle.FromLTRB(
174 | (IsSideBarAvailable ? HamburgerButtonSize : 0) + TitlebarRectangle.Left, TitlebarRectangle.Top,
175 | TitlebarRectangle.Right - GetTitleBarButtonsWidth(), TitlebarRectangle.Bottom);
176 |
177 | public List TitlebarButtons => _titlebarButtons;
178 |
179 | ///
180 | /// Rectangle that represents all caption/titlebar buttons
181 | ///
182 | [Browsable(false)]
183 | [EditorBrowsable(EditorBrowsableState.Never)]
184 | public virtual Rectangle TitlebarButtonsRectangle
185 | {
186 | get
187 | {
188 | var btnWidth = GetTitleBarButtonsWidth();
189 | var titlebarRect = TitlebarRectangle;
190 | return Rectangle.FromLTRB(titlebarRect.Right - btnWidth, titlebarRect.Top, titlebarRect.Right,
191 | titlebarRect.Bottom);
192 | }
193 | }
194 |
195 | ///
196 | /// The font used in the titlebar
197 | ///
198 | public Font TitleBarFont { get; set; } = SystemFonts.CaptionFont;
199 |
200 | ///
201 | /// The actual height of the titlebar
202 | ///
203 | public int TitlebarHeight { get; set; } = DefaultTitlebarHeight;
204 |
205 | [Browsable(false)]
206 | [EditorBrowsable(EditorBrowsableState.Never)]
207 | protected virtual int BorderOffset => WindowState == FormWindowState.Maximized ? 0 : 1;
208 |
209 | ///
210 | /// Rectangle that represents the complete titlebar
211 | ///
212 | [Browsable(false)]
213 | [EditorBrowsable(EditorBrowsableState.Never)]
214 | public virtual Rectangle TitlebarRectangle => Rectangle.FromLTRB(BorderOffset, BorderOffset,
215 | FormBounds.Right - BorderOffset, TitlebarVisible ? TitlebarHeight + BorderOffset : BorderOffset);
216 |
217 | public bool TitlebarVisible { get; set; } = true;
218 |
219 | private List NativeTitlebarButtons => _nativeTitlebarButtons;
220 |
221 | #endregion
222 |
223 | #region Methods
224 |
225 | public void HandleMouseMoveAndChild(Control c)
226 | {
227 | //Listen to mouse events
228 | c.MouseDown += HandleMouseEventHandler;
229 | c.MouseMove += MouseMoveEvent;
230 | foreach (Control c2 in c.Controls)
231 | {
232 | //Do the same for child controls
233 | //(Recursive method call)
234 | HandleMouseMoveAndChild(c2);
235 | }
236 | }
237 |
238 | public WindowHitTestResult HitTest(Point loc)
239 | {
240 | return HitTest(loc, Point.Empty);
241 | }
242 |
243 | public WindowHitTestResult HitTest(Point loc, Point offset)
244 | {
245 | var negativeOffset = new Point(-offset.X, -offset.Y);
246 | if (TitlebarButtonsRectangle.OffsetAndReturn(negativeOffset).Contains(loc))
247 | return WindowHitTestResult.TitleBarButtons;
248 |
249 | if (TextBarRectangle.OffsetAndReturn(negativeOffset).Contains(loc))
250 | return WindowHitTestResult.TitleBar;
251 |
252 | if (!Sizable)
253 | return WindowHitTestResult.None;
254 |
255 | if (LeftBottom.OffsetAndReturn(negativeOffset).Contains(loc))
256 | return WindowHitTestResult.BottomLeft;
257 |
258 | if (LeftSide.OffsetAndReturn(negativeOffset).Contains(loc))
259 | return WindowHitTestResult.Left;
260 |
261 | if (BottomSide.OffsetAndReturn(negativeOffset).Contains(loc))
262 | return WindowHitTestResult.Bottom;
263 |
264 | if (RightBottom.OffsetAndReturn(negativeOffset).Contains(loc))
265 | return WindowHitTestResult.BottomRight;
266 |
267 | if (RightSide.OffsetAndReturn(negativeOffset).Contains(loc))
268 | return WindowHitTestResult.Right;
269 |
270 | return WindowHitTestResult.None;
271 | }
272 |
273 | public void UnhandleMouseMoveAndChild(Control c)
274 | {
275 | //Remove mouse events listeners
276 | c.MouseDown -= HandleMouseEventHandler;
277 | c.MouseMove -= MouseMoveEvent;
278 | foreach (Control c2 in c.Controls)
279 | {
280 | //Do the same for child controls
281 | //(Recursive method call)
282 | UnhandleMouseMoveAndChild(c2);
283 | }
284 | }
285 |
286 | protected override void OnControlAdded(ControlEventArgs e)
287 | {
288 | base.OnControlAdded(e);
289 | //Detect when control is added and handle form resizing
290 | HandleMouseMoveAndChild(e.Control);
291 | }
292 |
293 | protected override void OnControlRemoved(ControlEventArgs e)
294 | {
295 | base.OnControlRemoved(e);
296 | //Detect when control is removed and remove all mouse listeners
297 | UnhandleMouseMoveAndChild(e.Control);
298 | }
299 |
300 | protected override void OnLoad(EventArgs e)
301 | {
302 | if (!DesignMode)
303 | {
304 | if (Location.IsEmpty) CenterToScreen();
305 |
306 | //Check if we can use the aero shadow
307 | if ((ShadowType.Equals(ShadowType.AeroShadow) || ShadowType.Equals(ShadowType.Default)) &&
308 | DwmNative.ExtendFrameIntoClientArea(this, 0, 0, 0, 1))
309 | {
310 | //We can! Tell windows to allow the rendering to happen on our borderless form
311 | DwmNative.AllowRenderInBorderless(this);
312 | }
313 | else if (ShadowType.Equals(ShadowType.Default) || ShadowType.Equals(ShadowType.FlatShadow))
314 | {
315 | //No aero for us! We must create the typical flat shadow.
316 | new ShadowForm().Show(this);
317 | }
318 | //else if (ShadowType.Equals(ShadowType.GlowShadow))
319 | //{
320 | // var glowShadowForm = new PerPixelAlphaForm()
321 | // {/*
322 | // ShadowBlur = 5,
323 | // ShadowSpread = 5,
324 | // ShadowColor = ColorScheme.PrimaryColor*/
325 | // };
326 | // using (var bmp = new Bitmap(Width + 10, Height + 10))
327 | // {
328 | // using (var g = Graphics.FromImage(bmp))
329 | // {
330 | // g.FillRectangle(Brushes.Black, 0, 0, bmp.Width, bmp.Height);
331 | // }
332 | // glowShadowForm.SetBitmap(bmp);
333 | // }
334 |
335 | // glowShadowForm.Location = new Point(Location.X - 5, Location.Y - 5);
336 | // glowShadowForm.Show();
337 | // //SizeChanged += (s, ee) => glowShadowForm.RefreshShadow();
338 | // //glowShadowForm.RefreshShadow();
339 | //}
340 | }
341 |
342 | base.OnLoad(e);
343 | }
344 |
345 | protected override void OnMouseClick(MouseEventArgs e)
346 | {
347 | base.OnMouseClick(e);
348 | if (_windowHit != WindowHitTestResult.None && _windowHit != WindowHitTestResult.TitleBar &&
349 | _windowHit != WindowHitTestResult.TitleBarButtons && Sizable)
350 | {
351 | _windowHit = WindowHitTestResult.None;
352 | return;
353 | }
354 |
355 | var titlebarButtonOffset = 0;
356 | switch (HitTest(e.Location))
357 | {
358 | case WindowHitTestResult.TitleBarButtons:
359 | titlebarButtonOffset = 0;
360 | HandleTitlebarButtonClick(e, ref titlebarButtonOffset, NativeTitlebarButtons);
361 | HandleTitlebarButtonClick(e, ref titlebarButtonOffset, TitlebarButtons);
362 | break;
363 | }
364 |
365 | if (IsSideBarAvailable && HamburgerRectangle.Contains(e.Location))
366 | Controls.OfType().All(ToggleSidebar);
367 | }
368 |
369 | private static bool ToggleSidebar(SidebarControl c)
370 | {
371 | if (c.IsClosed)
372 | {
373 | c.ShowSidebar();
374 | }
375 | else
376 | c.HideSidebar();
377 |
378 | return true;
379 | }
380 |
381 | private bool _isMouseDown;
382 |
383 | protected override void OnMouseDown(MouseEventArgs e)
384 | {
385 | base.OnMouseDown(e);
386 | _isMouseDown = true;
387 | var hitResult = HitTest(e.Location);
388 |
389 | _windowHit = hitResult;
390 |
391 | if (hitResult == WindowHitTestResult.TitleBar)
392 | {
393 | if (e.Button == MouseButtons.Left && e.Clicks == 2 && MaximizeBox)
394 | {
395 | WindowState = (WindowState == FormWindowState.Normal
396 | ? FormWindowState.Maximized
397 | : FormWindowState.Normal);
398 | return;
399 | }
400 |
401 | FormUtils.StartFormDragFromTitlebar(this);
402 | }
403 | else if (hitResult != WindowHitTestResult.TitleBarButtons && hitResult != WindowHitTestResult.None &&
404 | Sizable)
405 | {
406 | if (!Sizable) return;
407 | FormUtils.StartFormResizeFromEdge(this, FormUtils.ConvertToResizeResult(hitResult));
408 | }
409 |
410 | Invalidate(TitlebarButtonsRectangle);
411 | if (IsSideBarAvailable)
412 | Invalidate(HamburgerRectangle);
413 | }
414 |
415 | protected override void OnMouseEnter(EventArgs e)
416 | {
417 | base.OnMouseEnter(e);
418 | if (DesignMode) return;
419 | if (_mouseChanged)
420 | {
421 | Cursor = Cursors.Default;
422 | _mouseChanged = false;
423 | }
424 |
425 | Invalidate(TitlebarButtonsRectangle);
426 | }
427 |
428 | protected override void OnMouseLeave(EventArgs e)
429 | {
430 | base.OnMouseLeave(e);
431 | if (DesignMode) return;
432 | if (_mouseChanged)
433 | {
434 | Cursor = Cursors.Default;
435 | _mouseChanged = false;
436 | }
437 |
438 | Invalidate(TitlebarButtonsRectangle);
439 | if (IsSideBarAvailable)
440 | Invalidate(HamburgerRectangle);
441 | }
442 |
443 | protected override void OnMouseMove(MouseEventArgs e)
444 | {
445 | base.OnMouseMove(e);
446 | if (DesignMode) return;
447 | var hitResult = HitTest(e.Location);
448 | var resizeResult = FormUtils.ConvertToResizeResult(hitResult);
449 | var cursor = FormUtils.HitTestToCursor(resizeResult);
450 | if (WindowState != FormWindowState.Maximized)
451 | {
452 | if (_mouseChanged)
453 | {
454 | base.Cursor = cursor;
455 | }
456 |
457 | _mouseChanged = true /*!cursor.Equals(Cursors.Default)*/;
458 | }
459 |
460 | Invalidate(TitlebarButtonsRectangle);
461 | }
462 |
463 | protected override void OnMouseUp(MouseEventArgs e)
464 | {
465 | base.OnMouseUp(e);
466 | _isMouseDown = false;
467 | if (_mouseChanged)
468 | {
469 | Cursor = Cursors.Default;
470 | _mouseChanged = false;
471 | }
472 |
473 | Invalidate(TitlebarButtonsRectangle);
474 | if (IsSideBarAvailable)
475 | Invalidate(HamburgerRectangle);
476 | }
477 |
478 | protected override void OnPaintBackground(PaintEventArgs e)
479 | {
480 | base.OnPaintBackground(e);
481 | var curLoc = PointToClient(Cursor.Position);
482 |
483 | using (var primary = new SolidBrush(ColorScheme.PrimaryColor))
484 | {
485 | using (var secondary = new SolidBrush(ColorScheme.SecondaryColor))
486 | {
487 | using (var mouseDownColor = new SolidBrush(ColorScheme.MouseDownColor))
488 | {
489 | using (var mouseHoverColor = new SolidBrush(ColorScheme.MouseHoverColor))
490 | {
491 | //Draw titlebar
492 | if (TitlebarVisible)
493 | e.Graphics.FillRectangle(IsAppBarAvailable ? secondary : primary, TitlebarRectangle);
494 | //Draw form border
495 | if (BorderOffset != 0)
496 | GraphicUtils.DrawRectangleBorder(FormBounds, e.Graphics, ColorScheme.SecondaryColor);
497 |
498 | if (!TitlebarVisible)
499 | return;
500 | //Start rendering the titlebar buttons
501 | var titlebarButtonOffset = 0;
502 | titlebarButtonOffset = RenderTitlebarButtons(e, curLoc, mouseDownColor, mouseHoverColor,
503 | NativeTitlebarButtons, ref titlebarButtonOffset);
504 | titlebarButtonOffset = RenderTitlebarButtons(e, curLoc, mouseDownColor, mouseHoverColor,
505 | TitlebarButtons,
506 | ref titlebarButtonOffset);
507 | //Dectect if an app bar is available.
508 | //If it is, draw the window title.
509 | if (!IsAppBarAvailable ||
510 | (Controls.OfType().FirstOrDefault()?.OverrideParentText ?? false))
511 | {
512 | GraphicUtils.DrawCenteredText(e.Graphics, Text, TitleBarFont,
513 | Rectangle.FromLTRB(TextBarRectangle.Left + SizingBorder, TextBarRectangle.Top,
514 | TextBarRectangle.Right - SizingBorder, TextBarRectangle.Bottom),
515 | ColorScheme.ForegroundColor, false, true);
516 | }
517 |
518 | if (IsSideBarAvailable)
519 | GraphicUtils.DrawHamburgerButton(e.Graphics, secondary, HamburgerRectangle,
520 | ColorScheme.ForegroundColor, this, true);
521 | }
522 | }
523 | }
524 | }
525 | }
526 |
527 | protected override void OnPaint(PaintEventArgs e)
528 | {
529 | var oldClip = e.Graphics.Clip;
530 | e.Graphics.SetClip(DisplayRectangle);
531 | base.OnPaint(e);
532 | e.Graphics.SetClip(oldClip.GetBounds(e.Graphics));
533 | oldClip.Dispose();
534 | }
535 |
536 | ///
537 | /// This method adds the default titlebar buttons.
538 | ///
539 | /// Button width
540 | /// Form containing the buttons
541 | ///
542 | private static List GenerateNativeButtons(int width, Form parent)
543 | {
544 | //Create a temporary list
545 | var list = new List
546 | {
547 | new NativeTitlebarButton(parent, width, NativeTitlebarButton.TitlebarAction.Close),
548 | new NativeTitlebarButton(parent, width, NativeTitlebarButton.TitlebarAction.Maximize),
549 | new NativeTitlebarButton(parent, width, NativeTitlebarButton.TitlebarAction.Minimize)
550 | };
551 |
552 | return list;
553 | }
554 |
555 | ///
556 | /// Get rectangle of a button
557 | ///
558 | /// Offset
559 | /// The button
560 | ///
561 | private Rectangle GetTitlebarButtonRectangle(int offset, ModernTitlebarButton btn)
562 | {
563 | return Rectangle.FromLTRB(TitlebarRectangle.Right - btn.Width - offset, 0, TitlebarRectangle.Right - offset,
564 | TitlebarRectangle.Bottom);
565 | }
566 |
567 | ///
568 | /// Get total width of all the caption buttons
569 | ///
570 | ///
571 | private int GetTitleBarButtonsWidth()
572 | {
573 | var titlebarButtonOffset = 0;
574 | for (var i = 0; i < NativeTitlebarButtons.Count; i++)
575 | {
576 | var btn = NativeTitlebarButtons[i];
577 | if (!btn.Visible) continue;
578 | var rect = GetTitlebarButtonRectangle(titlebarButtonOffset, btn);
579 | titlebarButtonOffset += btn.Width;
580 | }
581 |
582 | for (var i = 0; i < TitlebarButtons.Count; i++)
583 | {
584 | var btn = TitlebarButtons[i];
585 | if (!btn.Visible) continue;
586 | var rect = GetTitlebarButtonRectangle(titlebarButtonOffset, btn);
587 | titlebarButtonOffset += btn.Width;
588 | }
589 |
590 | return titlebarButtonOffset;
591 | }
592 |
593 | private void HandleMouseEventHandler(object sender, MouseEventArgs e)
594 | {
595 | //Get the control
596 | var c = (Control) sender;
597 | //Check if the window isn't and there isn't more than one click
598 | if ((WindowState != FormWindowState.Maximized) && e.Clicks != 1) return;
599 | //Check where clicked
600 | var result = HitTest(e.Location, c.Location);
601 | //Invoke method that will start firm resizing
602 | if (Sizable)
603 | FormUtils.StartFormResizeFromEdge(this, FormUtils.ConvertToResizeResult(result), c);
604 | }
605 |
606 | private int HandleTitlebarButtonClick(MouseEventArgs e, ref int titlebarButtonOffset,
607 | List buttons)
608 | {
609 | for (var i = 0; i < buttons.Count; i++)
610 | {
611 | var btn = buttons[i];
612 | if (!btn.Visible) continue;
613 | var rect = GetTitlebarButtonRectangle(titlebarButtonOffset, btn);
614 | titlebarButtonOffset += btn.Width;
615 | if (rect.Contains(e.Location))
616 | {
617 | btn.OnClick(e);
618 | }
619 | }
620 |
621 | return titlebarButtonOffset;
622 | }
623 |
624 | private void MouseMoveEvent(object sender, MouseEventArgs e)
625 | {
626 | //Get the control
627 | var c = ((Control) sender);
628 |
629 | //Check if window is maximized, if it is, stop!
630 | if (WindowState == FormWindowState.Maximized) return;
631 | //Try to see where the mouse was
632 | var result = HitTest(e.Location, c.Location);
633 | var cur = FormUtils.HitTestToCursor(FormUtils.ConvertToResizeResult(result));
634 | //Change the mouse accordingly
635 | if (!c.Cursor.Equals(cur) && _mouseChanged)
636 | {
637 | c.Cursor = cur;
638 | _mouseChanged = !cur.Equals(Cursors.Default);
639 | }
640 | }
641 |
642 | private int RenderTitlebarButtons(PaintEventArgs e, Point curLoc, SolidBrush secondaryDown,
643 | SolidBrush secondaryHover, IEnumerable buttons, ref int titlebarButtonOffset)
644 | {
645 | foreach (var btn in buttons)
646 | {
647 | if (!btn.Visible) continue;
648 | var rect = GetTitlebarButtonRectangle(titlebarButtonOffset, btn);
649 | if (rect.Contains(curLoc) && !DesignMode)
650 | e.Graphics.FillRectangle(_isMouseDown ? secondaryDown : secondaryHover, rect);
651 | GraphicUtils.DrawCenteredText(e.Graphics, btn.Text, btn.Font, rect, ColorScheme.ForegroundColor);
652 | titlebarButtonOffset += btn.Width;
653 | }
654 |
655 | return titlebarButtonOffset;
656 | }
657 |
658 | private new void ResetBackColor()
659 | {
660 | BackColor = Color.White;
661 | }
662 |
663 | private void ResetColorScheme()
664 | {
665 | ColorScheme = DefaultColorSchemes.Blue;
666 | }
667 |
668 | #endregion
669 | }
670 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/Forms/PerPixelAlphaForm.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2002 Rui Godinho Lopes
3 | // All rights reserved.
4 | //
5 | // This source file(s) may be redistributed unmodified by any means
6 | // PROVIDING they are not sold for profit without the authors expressed
7 | // written consent, and providing that this notice and the authors name
8 | // and all copyright notices remain intact.
9 | //
10 | // Any use of the software in source or binary forms, with or without
11 | // modification, must include, in the user documentation ("About" box and
12 | // printed documentation) and internal comments to the code, notices to
13 | // the end user as follows:
14 | //
15 | // "Portions Copyright © 2002 Rui Godinho Lopes"
16 | //
17 | // An email letting me know that you are using it would be nice as well.
18 | // That's not much to ask considering the amount of work that went into
19 | // this.
20 | //
21 | // THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED. USE IT AT YOUT OWN RISK. THE AUTHOR ACCEPTS NO
23 | // LIABILITY FOR ANY DATA DAMAGE/LOSS THAT THIS PRODUCT MAY CAUSE.
24 | //
25 |
26 | using System;
27 | using System.Drawing;
28 | using System.Drawing.Imaging;
29 | using System.Windows.Forms;
30 | using System.Runtime.InteropServices;
31 |
32 |
33 | // a static class to expose needed win32 gdi functions.
34 | class Win32 {
35 |
36 | public enum Bool {
37 | False= 0,
38 | True
39 | };
40 |
41 | [StructLayout(LayoutKind.Sequential)]
42 | public struct Point {
43 | public Int32 x;
44 | public Int32 y;
45 |
46 | public Point(Int32 x, Int32 y) { this.x= x; this.y= y; }
47 | }
48 |
49 | [StructLayout(LayoutKind.Sequential)]
50 | public struct Size {
51 | public Int32 cx;
52 | public Int32 cy;
53 |
54 | public Size(Int32 cx, Int32 cy) { this.cx= cx; this.cy= cy; }
55 | }
56 |
57 | [StructLayout(LayoutKind.Sequential, Pack=1)]
58 | struct ARGB {
59 | public byte Blue;
60 | public byte Green;
61 | public byte Red;
62 | public byte Alpha;
63 | }
64 |
65 | [StructLayout(LayoutKind.Sequential, Pack=1)]
66 | public struct BLENDFUNCTION {
67 | public byte BlendOp;
68 | public byte BlendFlags;
69 | public byte SourceConstantAlpha;
70 | public byte AlphaFormat;
71 | }
72 |
73 |
74 | public const Int32 ULW_COLORKEY = 0x00000001;
75 | public const Int32 ULW_ALPHA = 0x00000002;
76 | public const Int32 ULW_OPAQUE = 0x00000004;
77 |
78 | public const byte AC_SRC_OVER = 0x00;
79 | public const byte AC_SRC_ALPHA = 0x01;
80 |
81 |
82 | [DllImport("user32.dll", ExactSpelling=true, SetLastError=true)]
83 | public static extern Bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);
84 |
85 | [DllImport("user32.dll", ExactSpelling=true, SetLastError=true)]
86 | public static extern IntPtr GetDC(IntPtr hWnd);
87 |
88 | [DllImport("user32.dll", ExactSpelling=true)]
89 | public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
90 |
91 | [DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
92 | public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
93 |
94 | [DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
95 | public static extern Bool DeleteDC(IntPtr hdc);
96 |
97 | [DllImport("gdi32.dll", ExactSpelling=true)]
98 | public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
99 |
100 | [DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]
101 | public static extern Bool DeleteObject(IntPtr hObject);
102 | }
103 |
104 |
105 | /// PerPixel forms should derive from this base class
106 | /// Rui Godinho Lopesrui@ruilopes.com
107 | public class PerPixelAlphaForm : Form {
108 |
109 | /// Changes the current bitmap.
110 | public void SetBitmap(Bitmap bitmap) {
111 | SetBitmap(bitmap, 255);
112 | }
113 |
114 | /// Changes the current bitmap with a custom opacity level. Here is where all happens!
115 | public void SetBitmap(Bitmap bitmap, byte opacity) {
116 | if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
117 | throw new ApplicationException("The bitmap must be 32ppp with alpha-channel.");
118 |
119 | // The ideia of this is very simple,
120 | // 1. Create a compatible DC with screen;
121 | // 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC;
122 | // 3. Call the UpdateLayeredWindow.
123 |
124 | IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
125 | IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
126 | IntPtr hBitmap = IntPtr.Zero;
127 | IntPtr oldBitmap = IntPtr.Zero;
128 |
129 | try {
130 | hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap
131 | oldBitmap = Win32.SelectObject(memDc, hBitmap);
132 |
133 | Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height);
134 | Win32.Point pointSource = new Win32.Point(0, 0);
135 | Win32.Point topPos = new Win32.Point(Left, Top);
136 | Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
137 | blend.BlendOp = Win32.AC_SRC_OVER;
138 | blend.BlendFlags = 0;
139 | blend.SourceConstantAlpha = opacity;
140 | blend.AlphaFormat = Win32.AC_SRC_ALPHA;
141 |
142 | Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA);
143 | }
144 | finally {
145 | Win32.ReleaseDC(IntPtr.Zero, screenDc);
146 | if (hBitmap != IntPtr.Zero) {
147 | Win32.SelectObject(memDc, oldBitmap);
148 | //Windows.DeleteObject(hBitmap); // The documentation says that we have to use the Windows.DeleteObject... but since there is no such method I use the normal DeleteObject from Win32 GDI and it's working fine without any resource leak.
149 | Win32.DeleteObject(hBitmap);
150 | }
151 | Win32.DeleteDC(memDc);
152 | }
153 | }
154 |
155 | public PerPixelAlphaForm()
156 | {
157 | FormBorderStyle = FormBorderStyle.None;
158 | }
159 |
160 | protected override CreateParams CreateParams {
161 | get {
162 | CreateParams cp = base.CreateParams;
163 | cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style
164 | return cp;
165 | }
166 | }
167 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/Forms/ShadowForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows.Forms;
7 |
8 | namespace NickAc.ModernUIDoneRight.Forms
9 | {
10 | public class ShadowForm : Form
11 | {
12 | #region Constructor
13 |
14 | #endregion
15 |
16 | #region Methods
17 | static Size ComputeMySize(Form f, int borderTimes2)
18 | {
19 | return new Size(f.Width + borderTimes2, f.Height + borderTimes2);
20 | }
21 | #endregion
22 |
23 | #region Properties
24 | public int BorderSize { get; set; } = 5;
25 | public float WindowOpacity { get; set; } = 0.30F;
26 | public Form ShadowOwner { get; set; }
27 | public Color ShadowColor { get; set; } = Color.Black;
28 | #endregion
29 |
30 | #region Other
31 | public void Show(Form f)
32 | {
33 | BackColor = ShadowColor;
34 | this.FormBorderStyle = FormBorderStyle.None;
35 | this.MaximizeBox = false;
36 | this.MinimizeBox = false;
37 | DoubleBuffered = true;
38 | if (f != null) {
39 | this.ShowInTaskbar = false;
40 | f.FormClosing += (sender, e) => this.Dispose();
41 | MaximizeBox = f.MaximizeBox;
42 | MinimizeBox = f.MinimizeBox;
43 | f.Load += (sender, e) => {
44 | Left = f.Left - BorderSize;
45 | Top = f.Top - BorderSize;
46 | this.Opacity = WindowOpacity;
47 | };
48 |
49 | base.Show();
50 | this.Left = f.Left - BorderSize;
51 | this.Top = f.Top - BorderSize;
52 | switch (f.WindowState) {
53 | case FormWindowState.Maximized:
54 | this.Opacity = 0;
55 | break;
56 | default:
57 | this.Opacity = WindowOpacity;
58 | break;
59 | }
60 |
61 | var borderTimes2 = BorderSize * 2;
62 | this.Size = new Size(f.Width + borderTimes2, f.Height + borderTimes2);
63 | f.Move += (sender, e) => {
64 | Refresh();
65 | this.Left = f.Left - BorderSize;
66 | this.Top = f.Top - BorderSize;
67 | };
68 | f.Owner = this;
69 | DoubleBuffered = true;
70 | ShadowOwner = f;
71 | f.VisibleChanged += (sender, e) => {
72 | switch (f.WindowState) {
73 | case FormWindowState.Maximized:
74 | this.Opacity = 0;
75 | break;
76 | default:
77 | this.Opacity = f.Visible ? WindowOpacity : 0;
78 | break;
79 | }
80 | };
81 | f.SizeChanged += (sender, e) => {
82 | switch (f.WindowState) {
83 | case FormWindowState.Maximized:
84 | this.Opacity = 0;
85 | break;
86 | default:
87 | this.Opacity = WindowOpacity;
88 | break;
89 | }
90 | Refresh();
91 | this.Size = ComputeMySize(f, borderTimes2);
92 | };
93 | }
94 | }
95 | protected override bool ShowWithoutActivation {
96 | get {
97 | return true;
98 | }
99 | }
100 | #endregion
101 | }
102 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/ModernUIDoneRight.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {2B12BD1B-9601-4B60-9515-F9A756D10753}
8 | Library
9 | NickAc.ModernUIDoneRight
10 | ModernUIDoneRight
11 | v4.0
12 | 512
13 |
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | Component
47 |
48 |
49 | Component
50 |
51 |
52 | Component
53 |
54 |
55 | Component
56 |
57 |
58 | Component
59 |
60 |
61 | Form
62 |
63 |
64 | Form
65 |
66 |
67 | Form
68 |
69 |
70 |
71 | Form
72 |
73 |
74 |
75 |
76 | Form
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Native/DwmNative.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Windows.Forms;
7 |
8 | namespace NickAc.ModernUIDoneRight.Native
9 | {
10 | class DwmNative
11 | {
12 |
13 | [DllImport("dwmapi.dll", PreserveSig = true)]
14 | private static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attr, ref int attrValue, int attrSize);
15 |
16 | private enum DWMWINDOWATTRIBUTE : uint
17 | {
18 | NCRenderingEnabled = 1,
19 | NCRenderingPolicy,
20 | TransitionsForceDisabled,
21 | AllowNCPaint,
22 | CaptionButtonBounds,
23 | NonClientRtlLayout,
24 | ForceIconicRepresentation,
25 | Flip3DPolicy,
26 | ExtendedFrameBounds,
27 | HasIconicBitmap,
28 | DisallowPeek,
29 | ExcludedFromPeek,
30 | Cloak,
31 | Cloaked,
32 | FreezeRepresentation
33 | }
34 |
35 | public static void AllowRenderInBorderless(Form f)
36 | {
37 | int val = 2;
38 | DwmSetWindowAttribute(f.Handle, DWMWINDOWATTRIBUTE.NCRenderingPolicy, ref val, 4);
39 | }
40 |
41 |
42 | [DllImport("dwmapi.dll", PreserveSig = true)]
43 | static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);
44 |
45 | [StructLayout(LayoutKind.Sequential)]
46 | private struct MARGINS
47 | {
48 | public int leftWidth;
49 | public int rightWidth;
50 | public int topHeight;
51 | public int bottomHeight;
52 |
53 | public MARGINS(int leftWidth, int rightWidth, int topHeight, int bottomHeight)
54 | {
55 | this.leftWidth = leftWidth;
56 | this.rightWidth = rightWidth;
57 | this.topHeight = topHeight;
58 | this.bottomHeight = bottomHeight;
59 | }
60 | }
61 |
62 | [DllImport("dwmapi.dll")]
63 | private static extern int DwmIsCompositionEnabled(out bool enabled);
64 |
65 | public static bool IsCompositionEnabled()
66 | {
67 | if (Environment.OSVersion.Version.Major < 6) return false;
68 | bool enabled;
69 | DwmIsCompositionEnabled(out enabled);
70 | return enabled;
71 | }
72 |
73 | public static bool ExtendFrameIntoClientArea(Form f, int left, int top, int right, int bottom)
74 | {
75 | if (IsCompositionEnabled()) {
76 | MARGINS margins = new MARGINS(left, right, top, bottom);
77 | DwmExtendFrameIntoClientArea(f.Handle, ref margins);
78 | return true;
79 | }
80 | return false;
81 | }
82 |
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/Action.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Controls;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Drawing;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Windows.Forms;
8 |
9 | namespace NickAc.ModernUIDoneRight.Objects
10 | {
11 | [Serializable]
12 | public class AppAction
13 | {
14 |
15 | public Image Image { get; set; }
16 | public Cursor Cursor { get; set; }
17 | public string ToolTip { get; set; }
18 |
19 |
20 |
21 |
22 | ///
23 | /// Called to signal to subscribers that it was clicked.
24 | ///
25 | public event EventHandler Click;
26 | public virtual void OnClick(EventArgs e)
27 | {
28 | EventHandler eh = Click;
29 |
30 | eh?.Invoke(this, e);
31 | }
32 |
33 |
34 | public Rectangle GetRectangle(AppBar bar, List containerList)
35 | {
36 | if (bar != null && containerList != null && containerList.Contains(this))
37 | {
38 | int index = containerList.IndexOf(this) + (bar.MenuItems != null && bar.MenuItems.Count > 0 ? 1 : 0);
39 | int xTextOffset = bar.XTextOffset;
40 | int size = bar.Height - xTextOffset;
41 | int xTextOffsetHalf = bar.XTextOffset / 2;
42 | int right = bar.Width - xTextOffsetHalf - (index * size + xTextOffsetHalf * index);
43 | return Rectangle.FromLTRB(right - size, xTextOffsetHalf, right, bar.Height - xTextOffsetHalf);
44 | }
45 | return Rectangle.Empty;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/Colors/ColorScheme.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Utils;
2 | using System.ComponentModel;
3 | using System.Drawing;
4 | using System.Windows.Forms;
5 | using static NickAc.ModernUIDoneRight.Utils.GraphicUtils;
6 |
7 | namespace NickAc.ModernUIDoneRight.Objects
8 | {
9 | [TypeConverter(typeof(ColorSchemeConverter))]
10 | public class ColorScheme
11 | {
12 | #region Constructor
13 | public ColorScheme(Color primaryColor, Color secondaryColor)
14 | {
15 | PrimaryColor = primaryColor;
16 | SecondaryColor = secondaryColor;
17 | MouseDownColor = DarkenColor(primaryColor, 0.2f);
18 | MouseHoverColor = LightenColor(secondaryColor, 0.2F);
19 | if (primaryColor.IsDarker())
20 | {
21 | MouseDownColor = LightenColor(MouseDownColor, 0.2f);
22 | MouseHoverColor = LightenColor(MouseDownColor, 0.25f);
23 | }
24 | }
25 | #endregion
26 |
27 | #region Properties
28 | public Color PrimaryColor { get; set; }
29 | public Color SecondaryColor { get; set; }
30 | public Color MouseDownColor { get; set; }
31 | public Color MouseHoverColor { get; set; }
32 | public Color ForegroundColor => ForegroundColorForBackground(PrimaryColor);
33 | #endregion
34 |
35 | #region Static Methods
36 | public static Color DarkenColor(Color original, float value = 0.05f)
37 | {
38 | return ControlPaint.Dark(original, value);
39 | }
40 |
41 | public static Color LightenColor(Color original, float value = 0.05f)
42 | {
43 | return ControlPaint.Light(original, value);
44 | }
45 |
46 | public static ColorScheme CreateSimpleColorScheme(Color original)
47 | {
48 | return new ColorScheme(original, DarkenColor(original));
49 | }
50 | #endregion
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/Colors/DefaultColorSchemes.cs:
--------------------------------------------------------------------------------
1 | namespace NickAc.ModernUIDoneRight.Objects
2 | {
3 |
4 | public static class DefaultColorSchemes
5 | {
6 | public static ColorScheme Red => ColorScheme.CreateSimpleColorScheme(DefaultColors.Red);
7 | public static ColorScheme Blue => ColorScheme.CreateSimpleColorScheme(DefaultColors.Blue);
8 | public static ColorScheme Green => ColorScheme.CreateSimpleColorScheme(DefaultColors.Green);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/Colors/DefaultColors.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 |
3 | namespace NickAc.ModernUIDoneRight.Objects
4 | {
5 | public static class DefaultColors
6 | {
7 | public static Color Red => Color.FromArgb(213, 0, 0);
8 | public static Color Blue => Color.FromArgb(2, 119, 189);
9 | public static Color Green => Color.FromArgb(0, 150, 36);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/Interaction/ModernTitlebarButton.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Forms;
2 | using System;
3 | using System.Drawing;
4 | using System.Windows.Forms;
5 |
6 | namespace NickAc.ModernUIDoneRight.Objects.Interaction
7 | {
8 | public class ModernTitlebarButton
9 | {
10 | #region Events
11 | ///
12 | /// Called to signal to subscribers that this button was clicked
13 | ///
14 | public event EventHandler Click;
15 | public void OnClick(MouseEventArgs e)
16 | {
17 | var eh = Click;
18 | eh?.Invoke(this, e);
19 | }
20 | #endregion
21 |
22 | #region Properties
23 | public virtual Font Font { get; set; } = SystemFonts.CaptionFont;
24 | public virtual String Text { get; set; }
25 | public virtual int Width { get; set; } = ModernForm.DefaultTitlebarHeight;
26 | public virtual Boolean Visible { get; set; } = true;
27 |
28 | #endregion
29 |
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/Interaction/NativeTitlebarButton.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using System.Windows.Forms;
3 |
4 | namespace NickAc.ModernUIDoneRight.Objects.Interaction
5 | {
6 | public class NativeTitlebarButton : ModernTitlebarButton
7 | {
8 | Form parent;
9 | readonly TitlebarAction action;
10 | //Make use of the Marlett font.
11 | //This font provides characters that can be used to display a caption button
12 | static Font fMarlett = new Font("Marlett", 10f);
13 |
14 | public NativeTitlebarButton(Form parent, int width, TitlebarAction action)
15 | {
16 | this.action = action;
17 | this.parent = parent;
18 | this.Width = width;
19 | this.Font = fMarlett;
20 | Click += TitlebarButton_Click;
21 | }
22 |
23 | private void TitlebarButton_Click(object sender, MouseEventArgs e)
24 | {
25 | switch (action) {
26 | case TitlebarAction.Minimize:
27 | parent.WindowState = FormWindowState.Minimized;
28 | break;
29 | case TitlebarAction.Maximize:
30 | FormWindowState finalWindowState = FormWindowState.Normal;
31 | if (parent.WindowState == FormWindowState.Normal)
32 | finalWindowState = FormWindowState.Maximized;
33 | parent.WindowState = finalWindowState;
34 | break;
35 | case TitlebarAction.Close:
36 | parent.Close();
37 | break;
38 | }
39 | }
40 |
41 | private string GetButtonText()
42 | {
43 | switch (action) {
44 | case TitlebarAction.Minimize:
45 | return "0"; //In Marlett, "0" represents minimize button
46 | case TitlebarAction.Maximize:
47 | return parent.WindowState == FormWindowState.Maximized ? "2" : "1"; //In Marlett, "1" represents maximize and "2" represents restore button
48 | case TitlebarAction.Close:
49 | return "r"; //In Marlett, "r" represents close button
50 | }
51 | return "";
52 | }
53 |
54 | public override string Text {
55 | get {
56 | return GetButtonText();
57 | }
58 | set => base.Text = value;
59 | }
60 |
61 | public override bool Visible {
62 | get {
63 | switch (action) {
64 | case TitlebarAction.Minimize:
65 | return parent.MinimizeBox;
66 | case TitlebarAction.Maximize:
67 | return parent.MaximizeBox;
68 | }
69 | return true;
70 | }
71 | set => base.Visible = value;
72 | }
73 |
74 | public enum TitlebarAction
75 | {
76 | Minimize, //Minimize
77 | Maximize, //Maximize/Restore
78 | Close //Close
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/Interaction/WindowHitTestResult.cs:
--------------------------------------------------------------------------------
1 | namespace NickAc.ModernUIDoneRight.Objects.Interaction
2 | {
3 | public enum WindowHitTestResult
4 | {
5 | TitleBarButtons,
6 | TitleBar,
7 | Up,
8 | UpLeft,
9 | Left,
10 | BottomLeft,
11 | Bottom,
12 | BottomRight,
13 | Right,
14 | UpRight,
15 | None
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/MenuItems/AppBarMenuForm.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Forms;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace NickAc.ModernUIDoneRight.Objects.MenuItems
8 | {
9 | class AppBarMenuForm : ModernForm
10 | {
11 | protected override bool ShowWithoutActivation => true;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/MenuItems/AppBarMenuItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace NickAc.ModernUIDoneRight.Objects.MenuItems
8 | {
9 | [Serializable]
10 | public abstract class AppBarMenuItem
11 | {
12 | ///
13 | /// Called to signal to subscribers that this action was clicked
14 | ///
15 | public event EventHandler Click;
16 | protected virtual void OnClick(EventArgs e)
17 | {
18 | EventHandler eh = Click;
19 |
20 | eh?.Invoke(this, e);
21 | }
22 |
23 | ///
24 | /// Called to signal to subscribers that the item needs to be measured
25 | ///
26 | public event EventHandler MeasureItem;
27 | protected virtual void OnMeasureItem(MeasureMenuItemEventArgs e)
28 | {
29 | EventHandler eh = MeasureItem;
30 |
31 | eh?.Invoke(this, e);
32 | }
33 |
34 | ///
35 | /// Called to signal to subscribers that the item needs to be rendered
36 | ///
37 | public event EventHandler RenderItem;
38 | protected virtual void OnRenderItem(RenderMenuItemEventArgs e)
39 | {
40 | EventHandler eh = RenderItem;
41 |
42 | eh?.Invoke(this, e);
43 | }
44 |
45 | public Size GetSize(Font font, Graphics g)
46 | {
47 | MeasureMenuItemEventArgs args = new MeasureMenuItemEventArgs(font, g, Size.Empty);
48 | OnMeasureItem(args);
49 | return args.ItemSize;
50 | }
51 |
52 |
53 | public void DrawItem(Graphics g, Rectangle rect, Font font)
54 | {
55 | var args = new RenderMenuItemEventArgs(g, rect, font);
56 | OnRenderItem(args);
57 | }
58 |
59 |
60 |
61 | public void PerformClick()
62 | {
63 | OnClick(EventArgs.Empty);
64 | }
65 |
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/MenuItems/AppBarMenuTextItem.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Utils;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Drawing;
5 | using System.Linq;
6 | using System.Text;
7 |
8 | namespace NickAc.ModernUIDoneRight.Objects.MenuItems
9 | {
10 | public class AppBarMenuTextItem : AppBarMenuItem
11 | {
12 | private const int minimumWidth = 150;
13 | private const int minimumHeight = 40;
14 | private const int textOffsetLeft = 10;
15 | public Color ForeColor { get; set; } = Color.Black;
16 |
17 | public AppBarMenuTextItem() : this("")
18 | { }
19 |
20 | public AppBarMenuTextItem(string text)
21 | {
22 | Text = text;
23 | }
24 |
25 | public string Text { get; set; }
26 |
27 | protected override void OnRenderItem(RenderMenuItemEventArgs e)
28 | {
29 | using (var brush = new SolidBrush(ForeColor)) {
30 | GraphicUtils.DrawCenteredText(
31 | e.Graphics,
32 | Text,
33 | e.Font,
34 | Rectangle.FromLTRB(e.Rectangle.Left + textOffsetLeft, e.Rectangle.Top, e.Rectangle.Right, e.Rectangle.Bottom),
35 | ForeColor, horizontal: false);
36 | }
37 | }
38 |
39 | protected override void OnMeasureItem(MeasureMenuItemEventArgs e)
40 | {
41 | Size textSize = e.Graphics.MeasureString(Text, e.Font).ToSize();
42 | e.ItemSize = new Size(Math.Max(minimumWidth, textSize.Width), Math.Max(minimumHeight, textSize.Height));
43 | }
44 |
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/MenuItems/MeasureMenuItemEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace NickAc.ModernUIDoneRight.Objects.MenuItems
8 | {
9 | public class MeasureMenuItemEventArgs : EventArgs
10 | {
11 | public MeasureMenuItemEventArgs(Font font, Graphics graphics, Size itemSize)
12 | {
13 | Font = font;
14 | Graphics = graphics;
15 | ItemSize = itemSize;
16 | }
17 |
18 | public Font Font { get; set; }
19 | public Graphics Graphics { get; set; }
20 | public Size ItemSize { get; set; } = Size.Empty;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/MenuItems/RenderMenuItemEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace NickAc.ModernUIDoneRight.Objects.MenuItems
8 | {
9 | public class RenderMenuItemEventArgs : EventArgs
10 | {
11 | public RenderMenuItemEventArgs(Graphics graphics, Rectangle rectangle, Font font)
12 | {
13 | Graphics = graphics;
14 | Rectangle = rectangle;
15 | Font = font;
16 | }
17 |
18 | public Font Font { get; set; }
19 | public Graphics Graphics { get; set; }
20 | public Rectangle Rectangle { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/ShadowType.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace NickAc.ModernUIDoneRight.Objects
7 | {
8 | public enum ShadowType
9 | {
10 | Default,
11 | AeroShadow,
12 | FlatShadow,
13 | //GlowShadow,
14 | None
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Objects/TileText.cs:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Software Criado por NickAc
4 | * Ficheiro Criado em 16/11/2016 às 06:58 PM
5 | *
6 | */
7 | using System;
8 | using System.ComponentModel;
9 | using System.ComponentModel.Design.Serialization;
10 | using System.Drawing;
11 | using System.Globalization;
12 | using System.Reflection;
13 | using System.Runtime.Serialization;
14 |
15 | namespace NickAc.ModernUIDoneRight.Objects
16 | {
17 | public class TileText
18 | {
19 | public TileText()
20 | {
21 | }
22 | public TileText(string text, Font font, Point location)
23 | {
24 | this.text = text;
25 | this.font = font;
26 | this.location = location;
27 | }
28 | Point location = Point.Empty;
29 | public virtual Point Location {
30 | get {
31 | return location;
32 | }
33 | set {
34 | location = value;
35 | }
36 | }
37 |
38 | String text = "TileText";
39 | public virtual String Text {
40 | get {
41 | return text;
42 | }
43 | set {
44 | text = value;
45 | }
46 | }
47 |
48 | Font font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point);
49 | public virtual Font Font {
50 | get {
51 | return font;
52 | }
53 | set {
54 | font = value;
55 | }
56 | }
57 | public override string ToString()
58 | {
59 | return "TileText";
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("ModernUIDoneRight")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("ModernUIDoneRight")]
12 | [assembly: AssemblyCopyright("Copyright © 2017")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("2b12bd1b-9601-4b60-9515-f9a756d10753")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/SidebarTextItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows.Forms;
7 | using NickAc.ModernUIDoneRight.Controls;
8 | using NickAc.ModernUIDoneRight.Utils;
9 | using static NickAc.ModernUIDoneRight.Controls.SidebarControl;
10 |
11 | namespace NickAc.ModernUIDoneRight
12 | {
13 | public class SidebarTextItem : SideBarItem
14 | {
15 | public String Text { get; set; } = "";
16 | private const int DEFAULT_TEXT_HEIGHT = 32;
17 | private const int SIDE_OFFSET = 8;
18 |
19 | public SidebarTextItem(string text)
20 | {
21 | Text = text;
22 | }
23 |
24 | public Color ForeColor { get; set; } = Color.Black;
25 |
26 | public override void DrawItem(SidebarControl c, Graphics g, Size itemSize, bool isSelected)
27 | {
28 | using (var sb = new SolidBrush(isSelected ? GraphicUtils.ForegroundColorForBackground(c.ColorScheme.SecondaryColor) : ForeColor)) {
29 | using (var format = new StringFormat
30 | {
31 | LineAlignment = StringAlignment.Center,
32 | }) {
33 | g.DrawString(Text, c.Font, sb, new Rectangle(SIDE_OFFSET, 0, itemSize.Width, itemSize.Height), format);
34 | }
35 | }
36 | }
37 |
38 | public override void MeasureItem(SidebarControl c, Graphics g, out int itemHeight)
39 | {
40 | itemHeight = Math.Max(DEFAULT_TEXT_HEIGHT, (int)g.MeasureString(Text, c.Font).Height + SIDE_OFFSET * 2);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Utils/Animation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows.Forms;
5 |
6 | namespace NickAc.ModernUIDoneRight.Utils
7 | {
8 | public class Animation
9 | {
10 | readonly Timer baseTimer;
11 | static List globalCancel = new List();
12 | Action endAnim;
13 | bool hasBeenCanceled;
14 | string identifier = "unknown";
15 |
16 | public class AnimationBuilder
17 | {
18 | int count = 0;
19 | int countLimit = -1;
20 | int multiplier = 1;
21 | int interval = 1;
22 | String identifier = "unknown";
23 | Action action;
24 |
25 | public AnimationBuilder WithAction(Action a)
26 | {
27 | action = a;
28 | return this;
29 | }
30 |
31 | public AnimationBuilder WithCountLimit(int a)
32 | {
33 | var clone = (Action)action.Clone();
34 | countLimit = a;
35 | action = new Action((aa) => {
36 | if (count < countLimit) {
37 | clone.Invoke(aa);
38 | count++;
39 | } else
40 | aa.Cancel();
41 | });
42 | return this;
43 | }
44 |
45 | public AnimationBuilder WithIdentifier(String a)
46 | {
47 | identifier = a;
48 | return this;
49 | }
50 | public AnimationBuilder WithInterval(int a)
51 | {
52 | interval = a;
53 | return this;
54 | }
55 |
56 | public AnimationBuilder WithMultiplier(int a)
57 | {
58 | multiplier = a;
59 | return this;
60 | }
61 |
62 | public Animation Build()
63 | {
64 | return new Animation(action, identifier, interval, multiplier);
65 | }
66 | }
67 |
68 | Animation(Action action, String globalIdentifier = "unknown", int interval = 1, int multiplier = 1)
69 | {
70 | identifier = globalIdentifier;
71 | baseTimer = new Timer
72 | {
73 | Interval = interval
74 | };
75 | for (int i = 0; i < multiplier; i++) {
76 | baseTimer.Tick += (sender, e) => action?.Invoke(this);
77 | }
78 | }
79 |
80 |
81 |
82 | public Animation Start()
83 | {
84 | if (!globalCancel.Contains(identifier)) {
85 | baseTimer.Start();
86 | if (identifier != "unknown")
87 | globalCancel.Add(identifier);
88 | }
89 | return this;
90 | }
91 |
92 | public Animation Cancel()
93 | {
94 | baseTimer.Stop();
95 | if (identifier != "unknown" && globalCancel.Contains(identifier))
96 | globalCancel.Remove(identifier);
97 | if (endAnim != null && (!hasBeenCanceled))
98 | endAnim(this);
99 | hasBeenCanceled = true;
100 | return this;
101 | }
102 |
103 | public Animation End(Action end)
104 | {
105 | endAnim = end;
106 | return this;
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Utils/ColorSchemeConverter.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Objects;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Drawing;
6 | using System.Globalization;
7 | using System.Linq;
8 | using System.Text;
9 |
10 | namespace NickAc.ModernUIDoneRight.Utils
11 | {
12 | class ColorSchemeConverter : TypeConverter
13 | {
14 | public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
15 | {
16 | return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
17 | }
18 |
19 | private static readonly ColorConverter ColorConverter = new ColorConverter();
20 | public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
21 | {
22 | if (value is string stringVal && ColorConverter != null)
23 | {
24 | var color = (Color) ColorConverter.ConvertFrom(stringVal);
25 | return ColorScheme.CreateSimpleColorScheme(color);
26 | }
27 | return base.ConvertFrom(context, culture, value);
28 | }
29 |
30 | public override bool GetPropertiesSupported(ITypeDescriptorContext context)
31 | {
32 | return true;
33 | }
34 |
35 | public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
36 | {
37 | return TypeDescriptor.GetProperties(typeof(ColorScheme));
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/ModernUIDoneRight/Utils/ControlPaintWrapper.cs:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Software Criado por NickAc
4 | * Ficheiro Criado em 13/05/2016 às 05:53 PM
5 | *
6 | */
7 |
8 | using System;
9 | using System.Drawing;
10 | using System.Drawing.Drawing2D;
11 | using System.Drawing.Imaging;
12 | using System.Windows.Forms;
13 |
14 | namespace NickAc.ModernUIDoneRight.Utils
15 | {
16 | ///
17 | /// ControlPaintWrapper - Copied code from decompiled ControlPaint class.
18 | /// All credits to the .NET developers
19 | ///
20 | public static class ControlPaintWrapper
21 | {
22 | #region Fields
23 |
24 | private static readonly System.Drawing.ContentAlignment anyBottom = (System.Drawing.ContentAlignment)1792;
25 |
26 | private static readonly System.Drawing.ContentAlignment anyCenter = (System.Drawing.ContentAlignment)546;
27 |
28 | private static readonly System.Drawing.ContentAlignment anyMiddle = (System.Drawing.ContentAlignment)112;
29 |
30 | private static readonly System.Drawing.ContentAlignment anyRight = (System.Drawing.ContentAlignment)1092;
31 |
32 | #endregion
33 |
34 | #region Methods
35 |
36 | public static Rectangle CalculateBackgroundImageRectangle(Rectangle bounds, Image backgroundImage, ImageLayout imageLayout)
37 | {
38 | Rectangle result = bounds;
39 | if (backgroundImage != null) {
40 | switch (imageLayout) {
41 | case ImageLayout.None:
42 | result.Size = backgroundImage.Size;
43 | break;
44 |
45 | case ImageLayout.Center: {
46 | result.Size = backgroundImage.Size;
47 | Size size = bounds.Size;
48 | if (size.Width > result.Width) {
49 | result.X = (size.Width - result.Width) / 2;
50 | }
51 | if (size.Height > result.Height) {
52 | result.Y = (size.Height - result.Height) / 2;
53 | }
54 | break;
55 | }
56 | case ImageLayout.Stretch:
57 | result.Size = bounds.Size;
58 | break;
59 |
60 | case ImageLayout.Zoom: {
61 | Size size2 = backgroundImage.Size;
62 | float num = (float)bounds.Width / (float)size2.Width;
63 | float num2 = (float)bounds.Height / (float)size2.Height;
64 | if (num < num2) {
65 | result.Width = bounds.Width;
66 | result.Height = (int)((double)((float)size2.Height * num) + 0.5);
67 | if (bounds.Y >= 0) {
68 | result.Y = (bounds.Height - result.Height) / 2;
69 | }
70 | }
71 | else {
72 | result.Height = bounds.Height;
73 | result.Width = (int)((double)((float)size2.Width * num2) + 0.5);
74 | if (bounds.X >= 0) {
75 | result.X = (bounds.Width - result.Width) / 2;
76 | }
77 | }
78 | break;
79 | }
80 | }
81 | }
82 | return result;
83 | }
84 |
85 | public static Rectangle Center(this Rectangle rect, Rectangle parentRect)
86 | {
87 | Point center = parentRect.Center();
88 |
89 | var w = rect.Width;
90 | var h = rect.Height;
91 |
92 | return Rectangle.FromLTRB(center.X - (w / 2), center.Y - (h / 2), center.X + (w / 2), center.Y + (h / 2));
93 | }
94 |
95 | public static Point Center(this Rectangle rect)
96 | {
97 | var center = new Point
98 | {
99 | X = rect.X + rect.Size.Width / 2,
100 | Y = rect.Y + rect.Size.Height / 2
101 | };
102 | return center;
103 | }
104 |
105 | //Code adapted from https://stackoverflow.com/a/41781248
106 | //All credits go to Lamar (https://stackoverflow.com/users/1260500/lamar) and TaW (https://stackoverflow.com/users/3152130/taw)
107 | public static Bitmap ChangeToColor(this Image bmp, Color c)
108 | {
109 | Bitmap bmp2 = new Bitmap(bmp.Width, bmp.Height);
110 | using (Graphics g = Graphics.FromImage(bmp2)) {
111 | float tr = c.R / 255f;
112 | float tg = c.G / 255f;
113 | float tb = c.B / 255f;
114 |
115 | ColorMatrix colorMatrix = new ColorMatrix(new float[][]
116 | {
117 | new float[] {0, 0, 0, 0, 0},
118 | new float[] {0, 0, 0, 0, 0},
119 | new float[] {0, 0, 0, 0, 0},
120 | new float[] {0, 0, 0, 1, 0},
121 | new float[] {tr, tg, tb, 0, 1}
122 | });
123 |
124 | ImageAttributes attributes = new ImageAttributes();
125 | attributes.SetColorMatrix(colorMatrix);
126 |
127 | g.DrawImage(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height),
128 | 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes);
129 | }
130 | return bmp2;
131 | }
132 | public static StringFormat CreateStringFormat(Control ctl, ContentAlignment textAlign, bool showEllipsis)
133 | {
134 | StringFormat stringFormat = ControlPaintWrapper.StringFormatForAlignment(textAlign);
135 | if (ctl.RightToLeft == RightToLeft.Yes) {
136 | stringFormat.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
137 | }
138 | if (showEllipsis) {
139 | stringFormat.Trimming = StringTrimming.EllipsisCharacter;
140 | stringFormat.FormatFlags |= StringFormatFlags.LineLimit;
141 | }
142 | if (ctl.AutoSize) {
143 | stringFormat.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
144 | }
145 | return stringFormat;
146 | }
147 |
148 | public static void DrawBackgroundImage(Graphics g, Image backgroundImage, Color backColor, ImageLayout backgroundImageLayout, Rectangle bounds, Rectangle clipRect, Point scrollOffset, RightToLeft rightToLeft)
149 | {
150 | if (g == null) {
151 | throw new ArgumentNullException(nameof(g));
152 | }
153 | if (backgroundImageLayout == ImageLayout.Tile) {
154 | using (TextureBrush textureBrush = new TextureBrush(backgroundImage, WrapMode.Tile)) {
155 | if (scrollOffset != Point.Empty) {
156 | Matrix transform = textureBrush.Transform;
157 | transform.Translate((float)scrollOffset.X, (float)scrollOffset.Y);
158 | textureBrush.Transform = transform;
159 | }
160 | g.FillRectangle(textureBrush, clipRect);
161 | return;
162 | }
163 | }
164 | Rectangle rectangle = ControlPaintWrapper.CalculateBackgroundImageRectangle(bounds, backgroundImage, backgroundImageLayout);
165 | if (rightToLeft == RightToLeft.Yes && backgroundImageLayout == ImageLayout.None) {
166 | rectangle.X += clipRect.Width - rectangle.Width;
167 | }
168 | using (SolidBrush solidBrush = new SolidBrush(backColor)) {
169 | g.FillRectangle(solidBrush, clipRect);
170 | }
171 | if (!clipRect.Contains(rectangle)) {
172 | if (backgroundImageLayout == ImageLayout.Stretch || backgroundImageLayout == ImageLayout.Zoom) {
173 | rectangle.Intersect(clipRect);
174 | g.DrawImage(backgroundImage, rectangle);
175 | return;
176 | }
177 | if (backgroundImageLayout == ImageLayout.None) {
178 | rectangle.Offset(clipRect.Location);
179 | Rectangle destRect = rectangle;
180 | destRect.Intersect(clipRect);
181 | Rectangle rectangle2 = new Rectangle(Point.Empty, destRect.Size);
182 | g.DrawImage(backgroundImage, destRect, rectangle2.X, rectangle2.Y, rectangle2.Width, rectangle2.Height, GraphicsUnit.Pixel);
183 | return;
184 | }
185 | Rectangle destRect2 = rectangle;
186 | destRect2.Intersect(clipRect);
187 | Rectangle rectangle3 = new Rectangle(new Point(destRect2.X - rectangle.X, destRect2.Y - rectangle.Y), destRect2.Size);
188 | g.DrawImage(backgroundImage, destRect2, rectangle3.X, rectangle3.Y, rectangle3.Width, rectangle3.Height, GraphicsUnit.Pixel);
189 | return;
190 | }
191 | else {
192 | ImageAttributes imageAttributes = new ImageAttributes();
193 | imageAttributes.SetWrapMode(WrapMode.TileFlipXY);
194 | g.DrawImage(backgroundImage, rectangle, 0, 0, backgroundImage.Width, backgroundImage.Height, GraphicsUnit.Pixel, imageAttributes);
195 | imageAttributes.Dispose();
196 | }
197 | }
198 |
199 | public static Rectangle ImageRectangleFromZoom(Image img, Rectangle originalRect)
200 | {
201 | var result = new Rectangle();
202 | Size size = img.Size;
203 | float num = Math.Min((float)originalRect.Width / (float)size.Width, (float)originalRect.Height / (float)size.Height);
204 | result.Width = (int)((float)size.Width * num);
205 | result.Height = (int)((float)size.Height * num);
206 | result.X = (originalRect.Width - result.Width) / 2;
207 | result.X += result.Width / 7;
208 | result.Y = originalRect.Y + (originalRect.Height - result.Height) / 2;
209 | return result;
210 | }
211 |
212 | public static StringFormat StringFormatForAlignment(System.Drawing.ContentAlignment align)
213 | {
214 | return new StringFormat
215 | {
216 | Alignment = ControlPaintWrapper.TranslateAlignment(align),
217 | LineAlignment = ControlPaintWrapper.TranslateLineAlignment(align)
218 | };
219 | }
220 |
221 | public static TextFormatFlags TranslateLineAlignmentForGDI(System.Drawing.ContentAlignment align)
222 | {
223 | TextFormatFlags result;
224 | // disable once BitwiseOperatorOnEnumWithoutFlags
225 | if ((align & ControlPaintWrapper.anyRight) != (System.Drawing.ContentAlignment)0) {
226 | result = TextFormatFlags.Right;
227 | }
228 | else {
229 | // disable once BitwiseOperatorOnEnumWithoutFlags
230 | if ((align & ControlPaintWrapper.anyCenter) != (System.Drawing.ContentAlignment)0) {
231 | result = TextFormatFlags.HorizontalCenter;
232 | }
233 | else {
234 | result = TextFormatFlags.Default;
235 | }
236 | }
237 | return result;
238 | }
239 |
240 | //The Rectangle (corresponds to the PictureBox.ClientRectangle)
241 | //we use here is the Form.ClientRectangle
242 | //Here is the Paint event handler of your Form1
243 | //use this method to draw the image like as the zooming feature of PictureBox
244 | public static void ZoomDrawImage(Graphics g, Image img, Rectangle bounds)
245 | {
246 | decimal r1 = (decimal)img.Width / img.Height;
247 | decimal r2 = (decimal)bounds.Width / bounds.Height;
248 | int w = bounds.Width;
249 | int h = bounds.Height;
250 | if (r1 > r2) {
251 | w = bounds.Width;
252 | h = (int)(w / r1);
253 | }
254 | else if (r1 < r2) {
255 | h = bounds.Height;
256 | w = (int)(r1 * h);
257 | }
258 | int x = bounds.X + (bounds.Width - w) / 2;
259 | int y = bounds.Y + (bounds.Height - h) / 2;
260 | var oldMode = g.InterpolationMode;
261 | g.InterpolationMode = InterpolationMode.High;
262 | g.DrawImage(img, new Rectangle(x, y, w, h));
263 | g.InterpolationMode = oldMode;
264 | }
265 |
266 | internal static StringAlignment TranslateAlignment(System.Drawing.ContentAlignment align)
267 | {
268 | StringAlignment result;
269 | // disable once BitwiseOperatorOnEnumWithoutFlags
270 | if ((align & ControlPaintWrapper.anyRight) != (System.Drawing.ContentAlignment)0) {
271 | result = StringAlignment.Far;
272 | }
273 | else {
274 | // disable once BitwiseOperatorOnEnumWithoutFlags
275 | if ((align & ControlPaintWrapper.anyCenter) != (System.Drawing.ContentAlignment)0) {
276 | result = StringAlignment.Center;
277 | }
278 | else {
279 | result = StringAlignment.Near;
280 | }
281 | }
282 | return result;
283 | }
284 |
285 | internal static StringAlignment TranslateLineAlignment(System.Drawing.ContentAlignment align)
286 | {
287 | StringAlignment result;
288 | if ((align & ControlPaintWrapper.anyBottom) != (System.Drawing.ContentAlignment)0) {
289 | result = StringAlignment.Far;
290 | }
291 | else {
292 | if ((align & ControlPaintWrapper.anyMiddle) != (System.Drawing.ContentAlignment)0) {
293 | result = StringAlignment.Center;
294 | }
295 | else {
296 | result = StringAlignment.Near;
297 | }
298 | }
299 | return result;
300 | }
301 |
302 | #endregion
303 | }
304 | }
--------------------------------------------------------------------------------
/ModernUIDoneRight/Utils/FormUtils.cs:
--------------------------------------------------------------------------------
1 | using NickAc.ModernUIDoneRight.Forms;
2 | using NickAc.ModernUIDoneRight.Objects.Interaction;
3 | using System;
4 | using System.Drawing;
5 | using System.Windows.Forms;
6 |
7 | namespace NickAc.ModernUIDoneRight.Utils
8 | {
9 | class FormUtils
10 | {
11 | public static ResizeResult ConvertToResizeResult(WindowHitTestResult r)
12 | {
13 | switch (r) {
14 | case WindowHitTestResult.Up:
15 | return ResizeResult.Top;
16 | case WindowHitTestResult.UpLeft:
17 | return ResizeResult.TopLeft;
18 | case WindowHitTestResult.Left:
19 | return ResizeResult.Left;
20 | case WindowHitTestResult.BottomLeft:
21 | return ResizeResult.BottomLeft;
22 | case WindowHitTestResult.Bottom:
23 | return ResizeResult.Bottom;
24 | case WindowHitTestResult.BottomRight:
25 | return ResizeResult.BottomRight;
26 | case WindowHitTestResult.Right:
27 | return ResizeResult.Right;
28 | case WindowHitTestResult.UpRight:
29 | return ResizeResult.TopRight;
30 | default:
31 | return ResizeResult.Client;
32 | }
33 | }
34 |
35 | private static int ConvertRange(int originalStart, int originalEnd, int newStart, int newEnd, int value)
36 | {
37 | var scale = (double)(newEnd - newStart) / (originalEnd - originalStart);
38 | return (int)(newStart + ((value - originalStart) * scale));
39 | }
40 |
41 | public enum ResizeResult
42 | {
43 | Client = 1,
44 | TopLeft = 7,
45 | Top = 8,
46 | TopRight = 9,
47 | Left = 10,
48 | Right = 11,
49 | Bottom = 15,
50 | BottomLeft = 16,
51 | BottomRight = 17,
52 | }
53 |
54 |
55 | public static Cursor HitTestToCursor(ResizeResult result)
56 | {
57 | if ((result == ResizeResult.Left) || result == ResizeResult.Right)
58 | return Cursors.SizeWE;
59 | if (result == ResizeResult.Bottom || result == ResizeResult.Top)
60 | return Cursors.SizeNS;
61 | if (result == ResizeResult.BottomLeft || result == ResizeResult.TopRight)
62 | return Cursors.SizeNESW;
63 | if (result == ResizeResult.BottomRight || result == ResizeResult.TopLeft)
64 | return Cursors.SizeNWSE;
65 | return Cursors.Default;
66 | }
67 |
68 | public static void StartFormResizeFromEdge(Form f, ResizeResult result, Control c = null)
69 | {
70 | var minimum = f is ModernForm modernForm ? modernForm.MinimumSize : f.MinimumSize;
71 | var maximum = f is ModernForm form ? form.MaximumSize : f.MaximumSize;
72 | //Cursor.Clip = Screen.GetWorkingArea(f);
73 | var curLoc = f.PointToClient(Cursor.Position);
74 | var fLoc = new Point(f.Left, f.Top);
75 | var w = f.Width;
76 | var h = f.Height;
77 | var resultEnum = ((ResizeResult)result);
78 |
79 | Action