├── .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 mouseMove = (s, e) => { 80 | 81 | 82 | if (f.WindowState != FormWindowState.Maximized) { 83 | var changedSize = (new Size(curLoc) - new Size(e.Location)).Width; 84 | var changedSizeH = (new Size(curLoc) - new Size(e.Location)).Height; 85 | f.Cursor = HitTestToCursor(result); 86 | switch (resultEnum) { 87 | case ResizeResult.Left: 88 | if (curLoc.X <= ModernForm.SizingBorder && ((f.Width + changedSize) >= minimum.Width)) { 89 | f.Left -= changedSize; 90 | fLoc = new Point(f.Left, f.Top); 91 | f.Width += changedSize; 92 | f.Update(); 93 | } 94 | break; 95 | case ResizeResult.Right: 96 | if (curLoc.X >= minimum.Width - ModernForm.SizingBorder) { 97 | f.Left = fLoc.X; 98 | curLoc = f.PointToClient(Cursor.Position); 99 | f.Width = w - changedSize; 100 | f.Update(); 101 | w = f.Width; 102 | } 103 | break; 104 | case ResizeResult.Bottom: 105 | if (curLoc.Y >= minimum.Height - ModernForm.SizingBorder) { 106 | f.Top = fLoc.Y; 107 | curLoc = f.PointToClient(Cursor.Position); 108 | f.Height = h - changedSizeH; 109 | f.Update(); 110 | h = f.Height; 111 | } 112 | break; 113 | case ResizeResult.BottomLeft: 114 | if (curLoc.X <= ModernForm.SizingBorder && curLoc.Y >= minimum.Height - ModernForm.SizingBorder && ((f.Width + changedSize) >= minimum.Width)) { 115 | var ww = e.Location.X - f.Left; 116 | var hh = e.Location.Y - f.Bottom; 117 | 118 | f.Height = f.Bottom + hh; 119 | f.Left -= changedSize; 120 | fLoc = new Point(f.Left, f.Top); 121 | f.Width += changedSize; 122 | 123 | f.Update(); 124 | 125 | } 126 | break; 127 | 128 | case ResizeResult.BottomRight: 129 | var ww2 = e.Location.X - f.Right; 130 | var hh2 = e.Location.Y - f.Bottom; 131 | 132 | f.Height = f.Bottom + hh2; 133 | 134 | fLoc = new Point(f.Left, f.Top); 135 | f.Width += f.Left + ww2; 136 | 137 | f.Update(); 138 | 139 | break; 140 | } 141 | } 142 | }; 143 | MouseEventHandler invoke = mouseMove.Invoke; 144 | f.MouseMove += invoke; 145 | MouseEventHandler invokeCMove = (s, e) => { 146 | var pt = f.PointToClient(((Control)s).PointToScreen(e.Location)); 147 | var x = pt.X; 148 | var y = pt.Y; 149 | 150 | 151 | invoke(f, new MouseEventArgs(e.Button, e.Clicks, x, y, e.Delta)); 152 | }; 153 | if (c != null) c.MouseMove += invokeCMove; 154 | 155 | 156 | 157 | MouseEventHandler invoke2 = null; 158 | 159 | invoke2 = (s, e) => { 160 | if (c != null) c.MouseMove -= invokeCMove; 161 | if (c != null) c.MouseUp -= invoke2; 162 | f.MouseUp -= invoke2; 163 | f.MouseMove -= invoke; 164 | f.Update(); 165 | //Cursor.Clip = new Rectangle(); 166 | }; 167 | 168 | f.MouseUp += invoke2; 169 | if (c != null) c.MouseUp += invoke2; 170 | 171 | 172 | } 173 | 174 | public static void StartFormDragFromTitlebar(Form f, Control c = null) 175 | { 176 | //Cursor.Clip = Screen.GetWorkingArea(f); 177 | var startCursorPosition = (c ?? f).PointToClient(Cursor.Position); 178 | Action mouseMove = (Object s, MouseEventArgs e) => { 179 | if (f.WindowState == FormWindowState.Maximized) { 180 | var beforeW = (f is ModernForm ? (((ModernForm)f).TextBarRectangle.Width) : f.Width); 181 | f.WindowState = FormWindowState.Normal; 182 | var afterW = (f is ModernForm ? (((ModernForm)f).TextBarRectangle.Width) : f.Width); 183 | startCursorPosition = new Point(ConvertRange(0, beforeW, 0, afterW, startCursorPosition.X), startCursorPosition.Y); 184 | } 185 | f.Location += (new Size(e.Location) - new Size(startCursorPosition)); 186 | }; 187 | MouseEventHandler invoke = mouseMove.Invoke; 188 | (c ?? f).MouseMove += invoke; 189 | (c ?? f).MouseUp += (s, e) => { 190 | (c ?? f).MouseMove -= invoke; 191 | 192 | //Cursor.Clip = new Rectangle(); 193 | }; 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /ModernUIDoneRight/Utils/GaussianBlur.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Drawing.Imaging; 5 | using System.Runtime.InteropServices; 6 | using System.Threading.Tasks; 7 | 8 | namespace NickAc.ModernUIDoneRight.Utils 9 | { 10 | //Code taken from https://github.com/mdymel/superfastblur 11 | public class GaussianBlur 12 | { 13 | private readonly int[] _alpha; 14 | private readonly int[] _red; 15 | private readonly int[] _green; 16 | private readonly int[] _blue; 17 | 18 | private readonly int _width; 19 | private readonly int _height; 20 | 21 | private readonly ParallelOptions _pOptions = new ParallelOptions { MaxDegreeOfParallelism = 16 }; 22 | 23 | public GaussianBlur(Bitmap image) 24 | { 25 | var rct = new Rectangle(0, 0, image.Width, image.Height); 26 | var source = new int[rct.Width * rct.Height]; 27 | var bits = image.LockBits(rct, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 28 | Marshal.Copy(bits.Scan0, source, 0, source.Length); 29 | image.UnlockBits(bits); 30 | 31 | _width = image.Width; 32 | _height = image.Height; 33 | 34 | _alpha = new int[_width * _height]; 35 | _red = new int[_width * _height]; 36 | _green = new int[_width * _height]; 37 | _blue = new int[_width * _height]; 38 | 39 | Parallel.For(0, source.Length, _pOptions, i => { 40 | _alpha[i] = (int)((source[i] & 0xff000000) >> 24); 41 | _red[i] = (source[i] & 0xff0000) >> 16; 42 | _green[i] = (source[i] & 0x00ff00) >> 8; 43 | _blue[i] = (source[i] & 0x0000ff); 44 | }); 45 | } 46 | 47 | public Bitmap Process(int radial) 48 | { 49 | var newAlpha = new int[_width * _height]; 50 | var newRed = new int[_width * _height]; 51 | var newGreen = new int[_width * _height]; 52 | var newBlue = new int[_width * _height]; 53 | var dest = new int[_width * _height]; 54 | 55 | Parallel.Invoke( 56 | () => gaussBlur_4(_alpha, newAlpha, radial), 57 | () => gaussBlur_4(_red, newRed, radial), 58 | () => gaussBlur_4(_green, newGreen, radial), 59 | () => gaussBlur_4(_blue, newBlue, radial)); 60 | 61 | Parallel.For(0, dest.Length, _pOptions, i => { 62 | if (newAlpha[i] > 255) newAlpha[i] = 255; 63 | if (newRed[i] > 255) newRed[i] = 255; 64 | if (newGreen[i] > 255) newGreen[i] = 255; 65 | if (newBlue[i] > 255) newBlue[i] = 255; 66 | 67 | if (newAlpha[i] < 0) newAlpha[i] = 0; 68 | if (newRed[i] < 0) newRed[i] = 0; 69 | if (newGreen[i] < 0) newGreen[i] = 0; 70 | if (newBlue[i] < 0) newBlue[i] = 0; 71 | 72 | dest[i] = (int)((uint)(newAlpha[i] << 24) | (uint)(newRed[i] << 16) | (uint)(newGreen[i] << 8) | (uint)newBlue[i]); 73 | }); 74 | 75 | var image = new Bitmap(_width, _height); 76 | var rct = new Rectangle(0, 0, image.Width, image.Height); 77 | var bits2 = image.LockBits(rct, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 78 | Marshal.Copy(dest, 0, bits2.Scan0, dest.Length); 79 | image.UnlockBits(bits2); 80 | return image; 81 | } 82 | 83 | private void gaussBlur_4(int[] source, int[] dest, int r) 84 | { 85 | var bxs = boxesForGauss(r, 3); 86 | boxBlur_4(source, dest, _width, _height, (bxs[0] - 1) / 2); 87 | boxBlur_4(dest, source, _width, _height, (bxs[1] - 1) / 2); 88 | boxBlur_4(source, dest, _width, _height, (bxs[2] - 1) / 2); 89 | } 90 | 91 | private int[] boxesForGauss(int sigma, int n) 92 | { 93 | var wIdeal = Math.Sqrt((12 * sigma * sigma / n) + 1); 94 | var wl = (int)Math.Floor(wIdeal); 95 | if (wl % 2 == 0) wl--; 96 | var wu = wl + 2; 97 | 98 | var mIdeal = (double)(12 * sigma * sigma - n * wl * wl - 4 * n * wl - 3 * n) / (-4 * wl - 4); 99 | var m = Math.Round(mIdeal); 100 | 101 | var sizes = new List(); 102 | for (var i = 0; i < n; i++) sizes.Add(i < m ? wl : wu); 103 | return sizes.ToArray(); 104 | } 105 | 106 | private void boxBlur_4(int[] source, int[] dest, int w, int h, int r) 107 | { 108 | for (var i = 0; i < source.Length; i++) dest[i] = source[i]; 109 | boxBlurH_4(dest, source, w, h, r); 110 | boxBlurT_4(source, dest, w, h, r); 111 | } 112 | 113 | private void boxBlurH_4(int[] source, int[] dest, int w, int h, int r) 114 | { 115 | var iar = (double)1 / (r + r + 1); 116 | Parallel.For(0, h, _pOptions, i => { 117 | var ti = i * w; 118 | var li = ti; 119 | var ri = ti + r; 120 | var fv = source[ti]; 121 | var lv = source[ti + w - 1]; 122 | var val = (r + 1) * fv; 123 | for (var j = 0; j < r; j++) val += source[ti + j]; 124 | for (var j = 0; j <= r; j++) { 125 | val += source[ri++] - fv; 126 | dest[ti++] = (int)Math.Round(val * iar); 127 | } 128 | for (var j = r + 1; j < w - r; j++) { 129 | val += source[ri++] - dest[li++]; 130 | dest[ti++] = (int)Math.Round(val * iar); 131 | } 132 | for (var j = w - r; j < w; j++) { 133 | val += lv - source[li++]; 134 | dest[ti++] = (int)Math.Round(val * iar); 135 | } 136 | }); 137 | } 138 | 139 | private void boxBlurT_4(int[] source, int[] dest, int w, int h, int r) 140 | { 141 | var iar = (double)1 / (r + r + 1); 142 | Parallel.For(0, w, _pOptions, i => { 143 | var ti = i; 144 | var li = ti; 145 | var ri = ti + r * w; 146 | var fv = source[ti]; 147 | var lv = source[ti + w * (h - 1)]; 148 | var val = (r + 1) * fv; 149 | for (var j = 0; j < r; j++) val += source[ti + j * w]; 150 | for (var j = 0; j <= r; j++) { 151 | val += source[ri] - fv; 152 | dest[ti] = (int)Math.Round(val * iar); 153 | ri += w; 154 | ti += w; 155 | } 156 | for (var j = r + 1; j < h - r; j++) { 157 | val += source[ri] - source[li]; 158 | dest[ti] = (int)Math.Round(val * iar); 159 | li += w; 160 | ri += w; 161 | ti += w; 162 | } 163 | for (var j = h - r; j < h; j++) { 164 | val += lv - source[li]; 165 | dest[ti] = (int)Math.Round(val * iar); 166 | li += w; 167 | ti += w; 168 | } 169 | }); 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /ModernUIDoneRight/Utils/GraphicUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | namespace NickAc.ModernUIDoneRight.Utils 6 | { 7 | public static class GraphicUtils 8 | { 9 | 10 | public static void DrawHamburgerButton(Graphics g, SolidBrush secondary, Rectangle hamburgerRectangle, Color foreColor, Control c, bool smallButton = false) 11 | { 12 | if (Control.MouseButtons != MouseButtons.None && hamburgerRectangle.Contains(c.PointToClient(Cursor.Position))) 13 | { 14 | g.FillRectangle(secondary, hamburgerRectangle); 15 | } 16 | 17 | using (var forePen = new Pen(foreColor, 3)) 18 | { 19 | //Draw hamburger icon 20 | var rect = hamburgerRectangle; 21 | const int barSize = 2; 22 | var spacingSides = smallButton ? 6 : 4; 23 | const int interval = 3; 24 | var centerX = rect.Right - (rect.Width / 2); 25 | var centerY = rect.Bottom - (rect.Height / 2); 26 | var topLine = centerY - (barSize * 2) - interval; 27 | var bottomLine = centerY + (barSize * 2) + interval; 28 | 29 | var oldMode = g.SmoothingMode; 30 | g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 31 | 32 | //Top 33 | g.DrawLine(forePen, rect.Left + spacingSides, topLine, rect.Right - spacingSides, 34 | topLine); 35 | 36 | //Middle 37 | g.DrawLine(forePen, rect.Left + spacingSides, centerY, rect.Right - spacingSides, 38 | centerY); 39 | 40 | //Bottom 41 | g.DrawLine(forePen, rect.Left + spacingSides, bottomLine, rect.Right - spacingSides, 42 | bottomLine); 43 | 44 | g.SmoothingMode = oldMode; 45 | } 46 | } 47 | 48 | public static Rectangle OffsetAndReturn(this Rectangle rect, Point offset) 49 | { 50 | if (offset.Equals(Point.Empty)) 51 | return rect; 52 | var newR = new Rectangle(rect.Location, rect.Size); 53 | newR.Offset(offset); 54 | return newR; 55 | } 56 | 57 | public static Rectangle OffsetAndReturn(this Rectangle rect, int x, int y) 58 | { 59 | if (x.Equals(Point.Empty.X) && y.Equals(Point.Empty.Y)) 60 | return rect; 61 | var newR = new Rectangle(rect.Location, rect.Size); 62 | newR.Offset(x, y); 63 | return newR; 64 | } 65 | 66 | //Method taken from https://stackoverflow.com/a/2241471 67 | //All credits go to the author: JYelton(https://stackoverflow.com/users/161052/jyelton) 68 | public static int PerceivedBrightness(Color c) 69 | { 70 | return (int)Math.Sqrt( 71 | c.R * c.R * .299 + 72 | c.G * c.G * .587 + 73 | c.B * c.B * .114); 74 | } 75 | 76 | public static Color ForegroundColorForBackground(Color back) 77 | { 78 | return !IsDark(back) ? Color.Black : Color.White; 79 | } 80 | 81 | public static bool IsDark(this Color c) 82 | { 83 | return PerceivedBrightness(c) < 130; 84 | } 85 | public static bool IsDarker(this Color c) 86 | { 87 | return PerceivedBrightness(c) < 100; 88 | } 89 | 90 | 91 | public static void DrawRectangleBorder(Rectangle rect, Graphics g, Color borderColor) 92 | { 93 | using (var p = new Pen(borderColor)) 94 | { 95 | //Top 96 | g.DrawLine(p, rect.Left + 1, rect.Top, rect.Right - 1, rect.Top); 97 | //Bottom 98 | g.DrawLine(p, rect.Left + 1, rect.Bottom - 1, rect.Right - 1, rect.Bottom - 1); 99 | //Left 100 | g.DrawLine(p, rect.Left, rect.Top, rect.Left, rect.Bottom); 101 | //Right 102 | g.DrawLine(p, rect.Right - 1, rect.Top, rect.Right - 1, rect.Bottom); 103 | } 104 | } 105 | 106 | public static void DrawCenteredText(Graphics g, string text, Font f, Rectangle rect, Color textColor, bool horizontal = true, bool vertical = true) 107 | { 108 | var sb = new SolidBrush(textColor); 109 | var stringFormat = new StringFormat(); 110 | if (horizontal) stringFormat.Alignment = StringAlignment.Center; // -- Horizontal Alignment 111 | if (vertical) stringFormat.LineAlignment = StringAlignment.Center; // || Vertical Alignment 112 | 113 | g.DrawString(text, f, sb, rect, stringFormat); 114 | stringFormat.Dispose(); 115 | sb.Dispose(); 116 | } 117 | 118 | 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /ModernUIDoneRight/Utils/ShadowUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Drawing.Drawing2D; 5 | using System.Linq; 6 | using System.Windows.Forms; 7 | using static System.Math; 8 | 9 | namespace NickAc.ModernUIDoneRight.Utils 10 | { 11 | public static class ShadowUtils 12 | { 13 | public interface IShadowController 14 | { 15 | bool ShouldShowShadow(); 16 | } 17 | enum RenderSide 18 | { 19 | Top, 20 | Bottom, 21 | Left, 22 | Right 23 | } 24 | 25 | static RenderSide[] VisibleTop = { RenderSide.Bottom/*, RenderSide.Top*/ }; 26 | static RenderSide[] VisibleBottom = { RenderSide.Top/*, RenderSide.Bottom*/ }; 27 | static RenderSide[] VisibleLeft = { RenderSide.Right }; 28 | static RenderSide[] VisibleRight = { RenderSide.Left }; 29 | 30 | static bool IsVisible(RenderSide side, DockStyle st) 31 | { 32 | switch (st) { 33 | case DockStyle.Top: 34 | return VisibleTop.Contains(side); 35 | case DockStyle.Bottom: 36 | return VisibleBottom.Contains(side); 37 | case DockStyle.Left: 38 | return VisibleLeft.Contains(side); 39 | case DockStyle.Right: 40 | return VisibleRight.Contains(side); 41 | case DockStyle.Fill: 42 | return false; 43 | } 44 | return true; 45 | } 46 | 47 | 48 | public static void DrawShadow(Graphics G, Color c, Rectangle r, int d, DockStyle st = DockStyle.None) 49 | { 50 | Color[] colors = GetColorVector(c, d).ToArray(); 51 | 52 | if (IsVisible(RenderSide.Top, st)) 53 | for (int i = 1; i < d; i++) { 54 | //TOP 55 | using (Pen pen = new Pen(colors[i], 1f)) 56 | G.DrawLine(pen, new Point(r.Left - Max(i - 1, 0), r.Top - i), new Point(r.Right + Max(i - 1, 0), r.Top - i)); 57 | } 58 | 59 | if (IsVisible(RenderSide.Bottom, st)) 60 | for (int i = 0; i < d; i++) { 61 | //BOTTOM 62 | using (Pen pen = new Pen(colors[i], 1f)) 63 | G.DrawLine(pen, new Point(r.Left - Max(i - 1, 0), r.Bottom + i), new Point(r.Right + i, r.Bottom + i)); 64 | } 65 | if (IsVisible(RenderSide.Left, st)) 66 | for (int i = 1; i < d; i++) { 67 | //LEFT 68 | using (Pen pen = new Pen(colors[i], 1f)) 69 | G.DrawLine(pen, new Point(r.Left - i, r.Top - i), new Point(r.Left - i, r.Bottom + i)); 70 | } 71 | if (IsVisible(RenderSide.Right, st)) 72 | for (int i = 0; i < d; i++) { 73 | //RIGHT 74 | using (Pen pen = new Pen(colors[i], 1f)) 75 | G.DrawLine(pen, new Point(r.Right + i, r.Top - i), new Point(r.Right + i, r.Bottom + Max(i - 1, 0))); 76 | } 77 | } 78 | 79 | //Code taken and adapted from StackOverflow (https://stackoverflow.com/a/13653167). 80 | //All credits go to Marino Šimić (https://stackoverflow.com/users/610204/marino-%c5%a0imi%c4%87). 81 | public static void DrawRoundedRectangle(this Graphics gfx, Rectangle bounds, int cornerRadius, Pen drawPen, Color fillColor) 82 | { 83 | int strokeOffset = Convert.ToInt32(Ceiling(drawPen.Width)); 84 | bounds = Rectangle.Inflate(bounds, -strokeOffset, -strokeOffset); 85 | 86 | var gfxPath = new GraphicsPath(); 87 | if (cornerRadius > 0) { 88 | gfxPath.AddArc(bounds.X, bounds.Y, cornerRadius, cornerRadius, 180, 90); 89 | gfxPath.AddArc(bounds.X + bounds.Width - cornerRadius, bounds.Y, cornerRadius, cornerRadius, 270, 90); 90 | gfxPath.AddArc(bounds.X + bounds.Width - cornerRadius, bounds.Y + bounds.Height - cornerRadius, cornerRadius, 91 | cornerRadius, 0, 90); 92 | gfxPath.AddArc(bounds.X, bounds.Y + bounds.Height - cornerRadius, cornerRadius, cornerRadius, 90, 90); 93 | } else { 94 | gfxPath.AddRectangle(bounds); 95 | } 96 | gfxPath.CloseAllFigures(); 97 | using (SolidBrush brush = new SolidBrush(fillColor)) { 98 | gfx.FillPath(brush, gfxPath); 99 | if (drawPen != Pens.Transparent) { 100 | var pen = new Pen(drawPen.Color); 101 | pen.EndCap = pen.StartCap = LineCap.Round; 102 | gfx.DrawPath(pen, gfxPath); 103 | pen.Dispose(); 104 | } 105 | } 106 | gfxPath.Dispose(); 107 | } 108 | 109 | //Code taken and adapted from StackOverflow (https://stackoverflow.com/a/13653167). 110 | //All credits go to Marino Šimić (https://stackoverflow.com/users/610204/marino-%c5%a0imi%c4%87). 111 | public static void DrawOutsetShadow(Graphics g, Color shadowColor, int hShadow, int vShadow, int blur, int spread, Control control) 112 | { 113 | var rOuter = Rectangle.Inflate(control.Bounds, blur / 2, blur / 2); 114 | var rInner = Rectangle.Inflate(control.Bounds, blur / 2, blur / 2); 115 | //rInner.Offset(hShadow, vShadow); 116 | rInner.Inflate(-blur, -blur); 117 | rOuter.Inflate(spread, spread); 118 | //rOuter.Offset(hShadow, vShadow); 119 | var originalOuter = rOuter; 120 | 121 | var img = new Bitmap(originalOuter.Width, originalOuter.Height, g); 122 | var g2 = Graphics.FromImage(img); 123 | 124 | var currentBlur = 0; 125 | 126 | do { 127 | var transparency = (rOuter.Height - rInner.Height) / (double)(blur * 2 + spread * 2); 128 | var color = Color.FromArgb(((int)(200 * (transparency * transparency))), shadowColor); 129 | var rOutput = rInner; 130 | rOutput.Offset(-originalOuter.Left, -originalOuter.Top); 131 | g2.DrawRoundedRectangle(rOutput, 5, Pens.Transparent, color); 132 | rInner.Inflate(1, 1); 133 | currentBlur = (int)((double)blur * (1 - (transparency * transparency))); 134 | } while (rOuter.Contains(rInner)); 135 | 136 | g2.Flush(); 137 | g2.Dispose(); 138 | 139 | g.DrawImage(img, originalOuter); 140 | 141 | img.Dispose(); 142 | } 143 | 144 | //Code taken and adapted from https://stackoverflow.com/a/25741405 145 | //All credits go to TaW (https://stackoverflow.com/users/3152130/taw) 146 | static List GetColorVector(Color fc, int depth) 147 | { 148 | List cv = new List(); 149 | int baseC = 65; 150 | float div = baseC / depth; 151 | for (int d = 1; d <= depth; d++) { 152 | cv.Add(Color.FromArgb(Max(0, baseC), fc)); 153 | baseC -= (int)div; 154 | } 155 | return cv; 156 | } 157 | 158 | 159 | //Code taken and adapted from https://stackoverflow.com/a/25741405 160 | //All credits go to TaW (https://stackoverflow.com/users/3152130/taw) 161 | static GraphicsPath GetRectPath(Rectangle R) 162 | { 163 | byte[] fm = new byte[3]; 164 | for (int b = 0; b < 3; b++) fm[b] = 1; 165 | List points = new List 166 | { 167 | new Point(R.Left, R.Bottom), 168 | new Point(R.Right, R.Bottom), 169 | new Point(R.Right, R.Top) 170 | }; 171 | return new GraphicsPath(points.ToArray(), fm); 172 | } 173 | 174 | public static void CreateDropShadow(this Control ctrl) 175 | { 176 | if (ctrl.Parent != null) { 177 | ctrl.Parent.Paint += (s, e) => { 178 | if (ctrl.Parent != null && ctrl.Visible && (!(ctrl is IShadowController) || ((IShadowController)ctrl).ShouldShowShadow())) 179 | DrawShadow(e.Graphics, Color.Black, ctrl.Bounds, 7, ctrl.Dock); 180 | }; 181 | } 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /ModernUITest/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ModernUITest/Form1.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace ModernUITest 2 | { 3 | partial class Form1 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.appBar1 = new NickAc.ModernUIDoneRight.Controls.AppBar(); 32 | this.modernButton1 = new NickAc.ModernUIDoneRight.Controls.ModernButton(); 33 | this.modernButton2 = new NickAc.ModernUIDoneRight.Controls.ModernButton(); 34 | this.sidebarControl1 = new NickAc.ModernUIDoneRight.Controls.SidebarControl(); 35 | this.tilePanelReborn1 = new NickAc.ModernUIDoneRight.Controls.TilePanelReborn(); 36 | this.SuspendLayout(); 37 | // 38 | // appBar1 39 | // 40 | this.appBar1.CastShadow = true; 41 | this.appBar1.Dock = System.Windows.Forms.DockStyle.Top; 42 | this.appBar1.HamburgerButtonSize = 32; 43 | this.appBar1.IconVisible = false; 44 | this.appBar1.Location = new System.Drawing.Point(1, 33); 45 | this.appBar1.Name = "appBar1"; 46 | this.appBar1.OverrideParentText = false; 47 | this.appBar1.Size = new System.Drawing.Size(795, 50); 48 | this.appBar1.TabIndex = 8; 49 | this.appBar1.Text = "Form1"; 50 | this.appBar1.TextFont = new System.Drawing.Font("Segoe UI", 14F); 51 | // 52 | // modernButton1 53 | // 54 | this.modernButton1.CustomColorScheme = false; 55 | this.modernButton1.Location = new System.Drawing.Point(303, 146); 56 | this.modernButton1.Name = "modernButton1"; 57 | this.modernButton1.Size = new System.Drawing.Size(138, 48); 58 | this.modernButton1.TabIndex = 9; 59 | this.modernButton1.Text = "modernButton1"; 60 | this.modernButton1.UseVisualStyleBackColor = true; 61 | // 62 | // modernButton2 63 | // 64 | this.modernButton2.CustomColorScheme = false; 65 | this.modernButton2.Location = new System.Drawing.Point(533, 146); 66 | this.modernButton2.Name = "modernButton2"; 67 | this.modernButton2.Size = new System.Drawing.Size(138, 48); 68 | this.modernButton2.TabIndex = 9; 69 | this.modernButton2.Text = "modernButton1"; 70 | this.modernButton2.UseVisualStyleBackColor = true; 71 | // 72 | // sidebarControl1 73 | // 74 | this.sidebarControl1.Dock = System.Windows.Forms.DockStyle.Left; 75 | this.sidebarControl1.IsClosed = false; 76 | this.sidebarControl1.Location = new System.Drawing.Point(1, 83); 77 | this.sidebarControl1.Name = "sidebarControl1"; 78 | this.sidebarControl1.Size = new System.Drawing.Size(210, 334); 79 | this.sidebarControl1.TabIndex = 10; 80 | this.sidebarControl1.Text = "sidebarControl1"; 81 | this.sidebarControl1.TopBarColor = System.Drawing.Color.FromArgb(((int)(((byte)(189)))), ((int)(((byte)(189)))), ((int)(((byte)(189))))); 82 | this.sidebarControl1.TopBarSize = 100; 83 | this.sidebarControl1.TopBarSpacing = 32; 84 | // 85 | // tilePanelReborn1 86 | // 87 | this.tilePanelReborn1.BrandedTile = false; 88 | this.tilePanelReborn1.CanBeHovered = false; 89 | this.tilePanelReborn1.Checkable = false; 90 | this.tilePanelReborn1.Flat = false; 91 | this.tilePanelReborn1.Image = null; 92 | this.tilePanelReborn1.Location = new System.Drawing.Point(262, 232); 93 | this.tilePanelReborn1.Name = "tilePanelReborn1"; 94 | this.tilePanelReborn1.Size = new System.Drawing.Size(217, 101); 95 | this.tilePanelReborn1.TabIndex = 11; 96 | this.tilePanelReborn1.Text = "tilePanelReborn1"; 97 | // 98 | // Form1 99 | // 100 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 101 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 102 | this.BackColor = System.Drawing.Color.White; 103 | this.ClientSize = new System.Drawing.Size(797, 418); 104 | this.ColorScheme.MouseDownColor = System.Drawing.Color.FromArgb(((int)(((byte)(1)))), ((int)(((byte)(64)))), ((int)(((byte)(101))))); 105 | this.ColorScheme.MouseHoverColor = System.Drawing.Color.FromArgb(((int)(((byte)(1)))), ((int)(((byte)(100)))), ((int)(((byte)(158))))); 106 | this.ColorScheme.PrimaryColor = System.Drawing.Color.FromArgb(((int)(((byte)(2)))), ((int)(((byte)(119)))), ((int)(((byte)(189))))); 107 | this.ColorScheme.SecondaryColor = System.Drawing.Color.FromArgb(((int)(((byte)(1)))), ((int)(((byte)(75)))), ((int)(((byte)(120))))); 108 | this.Controls.Add(this.tilePanelReborn1); 109 | this.Controls.Add(this.sidebarControl1); 110 | this.Controls.Add(this.modernButton2); 111 | this.Controls.Add(this.modernButton1); 112 | this.Controls.Add(this.appBar1); 113 | this.Location = new System.Drawing.Point(0, 0); 114 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 115 | this.Name = "Form1"; 116 | this.Text = "Form1"; 117 | this.ResumeLayout(false); 118 | 119 | } 120 | 121 | #endregion 122 | private NickAc.ModernUIDoneRight.Controls.AppBar appBar1; 123 | private NickAc.ModernUIDoneRight.Controls.ModernButton modernButton1; 124 | private NickAc.ModernUIDoneRight.Controls.ModernButton modernButton2; 125 | private NickAc.ModernUIDoneRight.Controls.SidebarControl sidebarControl1; 126 | private NickAc.ModernUIDoneRight.Controls.TilePanelReborn tilePanelReborn1; 127 | } 128 | } 129 | 130 | -------------------------------------------------------------------------------- /ModernUITest/Form1.cs: -------------------------------------------------------------------------------- 1 | using ModernUITest.Properties; 2 | using NickAc.ModernUIDoneRight; 3 | using NickAc.ModernUIDoneRight.Controls; 4 | using NickAc.ModernUIDoneRight.Forms; 5 | using NickAc.ModernUIDoneRight.Objects; 6 | using NickAc.ModernUIDoneRight.Objects.Interaction; 7 | using System.Drawing; 8 | using System.Windows.Forms; 9 | 10 | namespace ModernUITest 11 | { 12 | public partial class Form1 : ModernForm 13 | { 14 | 15 | public Form1() 16 | { 17 | InitializeComponent(); 18 | 19 | // this.ColorScheme = ColorScheme.CreateSimpleColorScheme(ColorTranslator.FromHtml("#2D2D30")); 20 | var btn2 = new ModernTitlebarButton 21 | { 22 | Text = "2" 23 | 24 | }; 25 | btn2.Click += (s, e) => MessageBox.Show("2"); 26 | TitlebarButtons.Add(btn2); 27 | var btn1 = new ModernTitlebarButton 28 | { 29 | Text = "1" 30 | }; 31 | btn1.Click += (s, e) => MessageBox.Show("1"); 32 | TitlebarButtons.Add(btn1); 33 | 34 | var item11 = new SidebarTextItem("Text 1"); 35 | item11.Click += (s, e) => { MessageBox.Show(this, "3"); }; 36 | 37 | appBar1.ToolTip = new ModernToolTip(); 38 | AppAction action1 = new AppAction(); 39 | action1.Cursor = Cursors.Hand; 40 | action1.Image = Resources.Speaker; 41 | action1.Click+=Action1_Click; 42 | action1.ToolTip = "click me!"; 43 | this.appBar1.Actions.Add(action1); 44 | 45 | AppAction action2 = new AppAction(); 46 | action2.Cursor = Cursors.Help; 47 | action2.Click += Action1_Click; 48 | action2.Image = Resources.Speaker; 49 | action2.ToolTip = "ALICE was beginning to get very tired of sitting by her sister on the bank and of having nothing to do: \n" + 50 | "once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, \n" + 51 | "\"and what is the use of a book,\" thought Alice, \"without pictures or conversations?'\n\n"; 52 | this.appBar1.Actions.Add(action2); 53 | } 54 | 55 | 56 | void Action1_Click(object sender, System.EventArgs e) 57 | { 58 | if (appBar1.ToolTip != null) 59 | { 60 | appBar1.ToolTip.Dispose(); 61 | } 62 | MessageBox.Show(sender.ToString() + " clicked"); 63 | if (appBar1.ToolTip is ModernToolTip) 64 | { 65 | appBar1.ToolTip = new ToolTip(); 66 | } 67 | else 68 | { 69 | appBar1.ToolTip = new ModernToolTip(); 70 | } 71 | } 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /ModernUITest/Form1.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 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 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /ModernUITest/ModernUITest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E874F220-2A5A-4038-BD42-302ED1EA6A48} 8 | WinExe 9 | ModernUITest 10 | ModernUITest 11 | v4.0 12 | 512 13 | true 14 | 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | Form 50 | 51 | 52 | Form1.cs 53 | 54 | 55 | 56 | 57 | Form1.cs 58 | 59 | 60 | ResXFileCodeGenerator 61 | Resources.Designer.cs 62 | Designer 63 | 64 | 65 | True 66 | Resources.resx 67 | True 68 | 69 | 70 | SettingsSingleFileGenerator 71 | Settings.Designer.cs 72 | 73 | 74 | True 75 | Settings.settings 76 | True 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | {2b12bd1b-9601-4b60-9515-f9a756d10753} 85 | ModernUIDoneRight 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ModernUITest/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | 6 | namespace ModernUITest 7 | { 8 | static class Program 9 | { 10 | /// 11 | /// The main entry point for the application. 12 | /// 13 | [STAThread] 14 | static void Main() 15 | { 16 | Application.EnableVisualStyles(); 17 | Application.SetCompatibleTextRenderingDefault(false); 18 | Application.Run(new Form1()); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ModernUITest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ModernUITest")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ModernUITest")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e874f220-2a5a-4038-bd42-302ed1ea6a48")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ModernUITest/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ModernUITest.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModernUITest.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap Speaker { 67 | get { 68 | object obj = ResourceManager.GetObject("Speaker", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ModernUITest/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 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 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\64px-Speaker_Icon.svg.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | -------------------------------------------------------------------------------- /ModernUITest/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ModernUITest.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ModernUITest/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ModernUITest/Resources/64px-Speaker_Icon.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickAcPT/ModernUIDoneRight/b6f99c37eeeaf0f61f6d1891ddebe5a7325c8c73/ModernUITest/Resources/64px-Speaker_Icon.svg.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ModernUIDoneRight 2 | I always felt that there is no free and good looking modern-ish theme for WinForms. 3 | 4 | So, I did what everyone does! Reinvent the wheel and create my own! 5 | This is a rewrite of my old theme library for WinForms. 6 | 7 | 8 | ## Current State 9 | ![Current State](https://i.imgur.com/EAcilGP.png "Image") 10 | --------------------------------------------------------------------------------