├── .gitattributes ├── .gitignore ├── Images ├── Blend-Dialog.png ├── Blend-Theme.png ├── Dark-Dialog.png ├── Dark-Theme.png ├── DarkBlue-Accents.png ├── DarkBlue-Dialog.png ├── DarkBlue-Theme.png ├── Light-Dialog.png ├── Light-Theme.png ├── LightBlue-Dialog.png └── LightBlue-Theme.png ├── LICENSE ├── ModernChrome.Sample ├── App.xaml ├── App.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── ModernChrome.Sample.NET45.csproj ├── ModernChrome.Sample.NET47.csproj ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── SampleDialog.xaml └── SampleDialog.xaml.cs ├── ModernChrome.sln ├── ModernChrome ├── Behaviors │ └── GlowWindowBehavior.cs ├── BindingProxy.cs ├── Converters │ ├── BooleanToVisibilityConverter.cs │ ├── FirstNotNullMultiConverter.cs │ ├── ResizeModeToEnabledConverter.cs │ ├── WindowStateToThicknessConverter.cs │ └── WindowStateToVisibilityConverter.cs ├── DesignTimeModernWindow.cs ├── DesignTimeResourceDictionary.cs ├── ModernChrome.NET45.csproj ├── ModernChrome.NET47.csproj ├── ModernChrome.nuspec ├── ModernWindow.cs ├── ModernWindowChrome.xaml ├── ModernWindowChrome.xaml.cs ├── Properties │ └── AssemblyInfo.cs ├── ThemeChangedEventArgs.cs ├── ThemeManager.cs └── Themes │ ├── Blend.xaml │ ├── Dark.xaml │ ├── DarkBlue.xaml │ ├── Generic.xaml │ ├── Light.xaml │ ├── LightBlue.xaml │ └── Themes.xaml ├── ModernChromeLogo.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 -------------------------------------------------------------------------------- /Images/Blend-Dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/Images/Blend-Dialog.png -------------------------------------------------------------------------------- /Images/Blend-Theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/Images/Blend-Theme.png -------------------------------------------------------------------------------- /Images/Dark-Dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/Images/Dark-Dialog.png -------------------------------------------------------------------------------- /Images/Dark-Theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/Images/Dark-Theme.png -------------------------------------------------------------------------------- /Images/DarkBlue-Accents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/Images/DarkBlue-Accents.png -------------------------------------------------------------------------------- /Images/DarkBlue-Dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/Images/DarkBlue-Dialog.png -------------------------------------------------------------------------------- /Images/DarkBlue-Theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/Images/DarkBlue-Theme.png -------------------------------------------------------------------------------- /Images/Light-Dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/Images/Light-Dialog.png -------------------------------------------------------------------------------- /Images/Light-Theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/Images/Light-Theme.png -------------------------------------------------------------------------------- /Images/LightBlue-Dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/Images/LightBlue-Dialog.png -------------------------------------------------------------------------------- /Images/LightBlue-Theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/Images/LightBlue-Theme.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Christian Ivicevic 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 | -------------------------------------------------------------------------------- /ModernChrome.Sample/App.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ModernChrome.Sample/App.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ModernChrome.Sample 2 | { 3 | /// 4 | /// Interaction logic for App.xaml 5 | /// 6 | public partial class App 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /ModernChrome.Sample/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 14 | 15 | 16 | Ready 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /ModernChrome.Sample/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Media; 4 | 5 | namespace ModernChrome.Sample 6 | { 7 | public partial class MainWindow 8 | { 9 | public MainWindow() 10 | { 11 | InitializeComponent(); 12 | 13 | ThemeManager.ThemeChanged += (sender, args) => 14 | { 15 | if (args.Theme != "Light") 16 | { 17 | ThemeText.Foreground = Brushes.White; 18 | AccentText.Foreground = Brushes.White; 19 | ActionText.Foreground = Brushes.White; 20 | } 21 | else 22 | { 23 | ThemeText.Foreground = Brushes.Black; 24 | AccentText.Foreground = Brushes.Black; 25 | ActionText.Foreground = Brushes.Black; 26 | } 27 | }; 28 | } 29 | 30 | private void ChangeAccent(object sender, RoutedEventArgs e) 31 | { 32 | var color = (sender as Button)?.Tag.ToString(); 33 | if (!string.IsNullOrEmpty(color)) 34 | BorderBrush = Application.Current.FindResource($"StatusBar{color}BrushKey") as SolidColorBrush; 35 | } 36 | 37 | private void ChangeTheme(object sender, RoutedEventArgs e) 38 | { 39 | var theme = (sender as Button)?.Tag.ToString(); 40 | if (!string.IsNullOrEmpty(theme)) 41 | ThemeManager.ChangeTheme(Application.Current, theme); 42 | } 43 | 44 | private void ShowDialog(object sender, RoutedEventArgs e) 45 | { 46 | new SampleDialog {Owner = this}.ShowDialog(); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /ModernChrome.Sample/ModernChrome.Sample.NET45.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {CAD144BB-2D6C-4B81-8893-91459F98F73A} 8 | WinExe 9 | ModernChrome.Sample 10 | ModernChrome.Sample 11 | v4.5 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | obj\net45\ 17 | 18 | 19 | 20 | AnyCPU 21 | true 22 | full 23 | false 24 | bin\Debug\net45\ 25 | DEBUG;TRACE;NET45 26 | prompt 27 | 4 28 | NU1602 29 | 30 | 31 | AnyCPU 32 | pdbonly 33 | true 34 | bin\Release\net45\ 35 | TRACE;NET47 36 | prompt 37 | 4 38 | NU1602 39 | 40 | 41 | 42 | 43 | 44 | 4.0 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | MSBuild:Compile 53 | Designer 54 | 55 | 56 | SampleDialog.xaml 57 | 58 | 59 | MSBuild:Compile 60 | Designer 61 | 62 | 63 | App.xaml 64 | Code 65 | 66 | 67 | MainWindow.xaml 68 | Code 69 | 70 | 71 | Designer 72 | MSBuild:Compile 73 | 74 | 75 | 76 | 77 | Code 78 | 79 | 80 | True 81 | True 82 | Resources.resx 83 | 84 | 85 | True 86 | Settings.settings 87 | True 88 | 89 | 90 | ResXFileCodeGenerator 91 | Resources.Designer.cs 92 | 93 | 94 | SettingsSingleFileGenerator 95 | Settings.Designer.cs 96 | 97 | 98 | 99 | 100 | {ef9abd47-f09c-4dfd-8933-32196a90629e} 101 | ModernChrome.NET45 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /ModernChrome.Sample/ModernChrome.Sample.NET47.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {BE29AD44-E6E7-456D-9586-C8CED83C8EB8} 8 | WinExe 9 | ModernChrome.Sample 10 | ModernChrome.Sample 11 | v4.7 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | obj\net47\ 17 | 18 | 19 | AnyCPU 20 | true 21 | full 22 | false 23 | bin\Debug\net47\ 24 | DEBUG;TRACE;NET47 25 | prompt 26 | 4 27 | NU1602 28 | 29 | 30 | AnyCPU 31 | pdbonly 32 | true 33 | bin\Release\net47\ 34 | TRACE;NET47 35 | prompt 36 | 4 37 | NU1602 38 | 39 | 40 | 41 | 42 | 43 | 4.0 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | MSBuild:Compile 52 | Designer 53 | 54 | 55 | SampleDialog.xaml 56 | 57 | 58 | MSBuild:Compile 59 | Designer 60 | 61 | 62 | App.xaml 63 | Code 64 | 65 | 66 | MainWindow.xaml 67 | Code 68 | 69 | 70 | Designer 71 | MSBuild:Compile 72 | 73 | 74 | 75 | 76 | Code 77 | 78 | 79 | True 80 | True 81 | Resources.resx 82 | 83 | 84 | True 85 | Settings.settings 86 | True 87 | 88 | 89 | ResXFileCodeGenerator 90 | Resources.Designer.cs 91 | 92 | 93 | SettingsSingleFileGenerator 94 | Settings.Designer.cs 95 | 96 | 97 | 98 | 99 | {2dd68e07-20d5-4bde-94aa-3b7ecd844524} 100 | ModernChrome.NET47 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /ModernChrome.Sample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 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("ModernChrome.Sample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ModernChrome.Sample")] 13 | [assembly: AssemblyCopyright("Copyright © 2017 Christian Ivicevic")] 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 | //In order to begin building localizable applications, set 23 | //CultureYouAreCodingWith in your .csproj file 24 | //inside a . For example, if you are using US english 25 | //in your source files, set the to en-US. Then uncomment 26 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 27 | //the line below to match the UICulture setting in the project file. 28 | 29 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 30 | 31 | [assembly: ThemeInfo( 32 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 33 | //(used if a resource is not found in the page, 34 | // or application resource dictionaries) 35 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 36 | //(used if a resource is not found in the page, 37 | // app, or any theme specific resource dictionaries) 38 | )] 39 | 40 | // Version information for an assembly consists of the following four values: 41 | // 42 | // Major Version 43 | // Minor Version 44 | // Build Number 45 | // Revision 46 | // 47 | // You can specify all the values or you can default the Build and Revision Numbers 48 | // by using the '*' as shown below: 49 | // [assembly: AssemblyVersion("1.0.*")] 50 | [assembly: AssemblyVersion("1.0.*")] 51 | //[assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /ModernChrome.Sample/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 ModernChrome.Sample.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("ModernChrome.Sample.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 | -------------------------------------------------------------------------------- /ModernChrome.Sample/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 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /ModernChrome.Sample/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 ModernChrome.Sample.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.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 | -------------------------------------------------------------------------------- /ModernChrome.Sample/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ModernChrome.Sample/SampleDialog.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ModernChrome.Sample/SampleDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace ModernChrome.Sample 4 | { 5 | public partial class SampleDialog 6 | { 7 | public SampleDialog() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | private void CloseWindow(object sender, RoutedEventArgs e) 13 | { 14 | Close(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /ModernChrome.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernChrome.NET45", "ModernChrome\ModernChrome.NET45.csproj", "{EF9ABD47-F09C-4DFD-8933-32196A90629E}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernChrome.Sample.NET47", "ModernChrome.Sample\ModernChrome.Sample.NET47.csproj", "{BE29AD44-E6E7-456D-9586-C8CED83C8EB8}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ModernChrome", "ModernChrome", "{BCE3CCA9-6C07-4FCF-8CC8-AA6421E2D25C}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernChrome.NET47", "ModernChrome\ModernChrome.NET47.csproj", "{2DD68E07-20D5-4BDE-94AA-3B7ECD844524}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ModernChrome.Sample", "ModernChrome.Sample", "{CA5C20C6-F9EB-4779-87B7-E2F7B462BCC1}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernChrome.Sample.NET45", "ModernChrome.Sample\ModernChrome.Sample.NET45.csproj", "{CAD144BB-2D6C-4B81-8893-91459F98F73A}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | Release|Any CPU = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {EF9ABD47-F09C-4DFD-8933-32196A90629E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {EF9ABD47-F09C-4DFD-8933-32196A90629E}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {EF9ABD47-F09C-4DFD-8933-32196A90629E}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {EF9ABD47-F09C-4DFD-8933-32196A90629E}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {BE29AD44-E6E7-456D-9586-C8CED83C8EB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {BE29AD44-E6E7-456D-9586-C8CED83C8EB8}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {BE29AD44-E6E7-456D-9586-C8CED83C8EB8}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {BE29AD44-E6E7-456D-9586-C8CED83C8EB8}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {2DD68E07-20D5-4BDE-94AA-3B7ECD844524}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {2DD68E07-20D5-4BDE-94AA-3B7ECD844524}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {2DD68E07-20D5-4BDE-94AA-3B7ECD844524}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {2DD68E07-20D5-4BDE-94AA-3B7ECD844524}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {CAD144BB-2D6C-4B81-8893-91459F98F73A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {CAD144BB-2D6C-4B81-8893-91459F98F73A}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {CAD144BB-2D6C-4B81-8893-91459F98F73A}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {CAD144BB-2D6C-4B81-8893-91459F98F73A}.Release|Any CPU.Build.0 = Release|Any CPU 40 | EndGlobalSection 41 | GlobalSection(SolutionProperties) = preSolution 42 | HideSolutionNode = FALSE 43 | EndGlobalSection 44 | GlobalSection(NestedProjects) = preSolution 45 | {EF9ABD47-F09C-4DFD-8933-32196A90629E} = {BCE3CCA9-6C07-4FCF-8CC8-AA6421E2D25C} 46 | {BE29AD44-E6E7-456D-9586-C8CED83C8EB8} = {CA5C20C6-F9EB-4779-87B7-E2F7B462BCC1} 47 | {2DD68E07-20D5-4BDE-94AA-3B7ECD844524} = {BCE3CCA9-6C07-4FCF-8CC8-AA6421E2D25C} 48 | {CAD144BB-2D6C-4B81-8893-91459F98F73A} = {CA5C20C6-F9EB-4779-87B7-E2F7B462BCC1} 49 | EndGlobalSection 50 | GlobalSection(ExtensibilityGlobals) = postSolution 51 | SolutionGuid = {E087DAE5-41A7-4255-B2DD-8E9E524B1627} 52 | EndGlobalSection 53 | EndGlobal 54 | -------------------------------------------------------------------------------- /ModernChrome/Behaviors/GlowWindowBehavior.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 4 | using System.Windows.Interactivity; 5 | using System.Windows.Interop; 6 | using System.Windows.Threading; 7 | using MahApps.Metro.Controls; 8 | 9 | namespace ModernChrome.Behaviors 10 | { 11 | /// 12 | /// 13 | /// Extends a window with four glow windows that display a colored shadow. 14 | /// 15 | internal sealed class GlowWindowBehavior : Behavior 16 | { 17 | private static readonly TimeSpan GlowTimerDelay = TimeSpan.FromMilliseconds(200); 18 | 19 | private IntPtr _handle; 20 | 21 | private HwndSource _hWndSource; 22 | 23 | private GlowWindow _left, _right, _top, _bottom; 24 | 25 | private DispatcherTimer _makeGlowVisibleTimer; 26 | 27 | private bool IsGlowDisabled => 28 | AssociatedObject is ModernWindow borderlessWindow && borderlessWindow.GlowBrush == null; 29 | 30 | private void AssociatedObjectOnLoaded(object sender, RoutedEventArgs routedEventArgs) 31 | { 32 | if (IsGlowDisabled) 33 | return; 34 | 35 | AssociatedObject.StateChanged -= AssociatedObjectStateChanged; 36 | AssociatedObject.StateChanged += AssociatedObjectStateChanged; 37 | 38 | if (_makeGlowVisibleTimer == null) 39 | { 40 | _makeGlowVisibleTimer = new DispatcherTimer {Interval = GlowTimerDelay}; 41 | _makeGlowVisibleTimer.Tick += GlowVisibleTimerOnTick; 42 | } 43 | 44 | _left = new GlowWindow(AssociatedObject, GlowDirection.Left); 45 | _right = new GlowWindow(AssociatedObject, GlowDirection.Right); 46 | _top = new GlowWindow(AssociatedObject, GlowDirection.Top); 47 | _bottom = new GlowWindow(AssociatedObject, GlowDirection.Bottom); 48 | 49 | Show(); 50 | Update(); 51 | 52 | AssociatedObject.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => SetOpacityTo(1))); 53 | } 54 | 55 | private void AssociatedObjectStateChanged(object sender, EventArgs e) 56 | { 57 | _makeGlowVisibleTimer?.Stop(); 58 | if (AssociatedObject.WindowState == WindowState.Normal) 59 | if (_makeGlowVisibleTimer != null) 60 | _makeGlowVisibleTimer.Start(); 61 | else 62 | RestoreGlow(); 63 | else 64 | HideGlow(); 65 | } 66 | 67 | private void AssociatedObjectUnloaded(object sender, RoutedEventArgs e) 68 | { 69 | if (_makeGlowVisibleTimer == null) 70 | return; 71 | _makeGlowVisibleTimer.Stop(); 72 | _makeGlowVisibleTimer.Tick -= GlowVisibleTimerOnTick; 73 | _makeGlowVisibleTimer = null; 74 | } 75 | 76 | private void GlowVisibleTimerOnTick(object sender, EventArgs e) 77 | { 78 | _makeGlowVisibleTimer?.Stop(); 79 | RestoreGlow(); 80 | } 81 | 82 | private void HideGlow() 83 | { 84 | if (_left != null) _left.IsGlowing = false; 85 | if (_top != null) _top.IsGlowing = false; 86 | if (_right != null) _right.IsGlowing = false; 87 | if (_bottom != null) _bottom.IsGlowing = false; 88 | Update(); 89 | } 90 | 91 | protected override void OnAttached() 92 | { 93 | base.OnAttached(); 94 | 95 | AssociatedObject.SourceInitialized += (o, args) => 96 | { 97 | _handle = new WindowInteropHelper(AssociatedObject).Handle; 98 | _hWndSource = HwndSource.FromHwnd(_handle); 99 | _hWndSource?.AddHook(AssociatedObjectWindowProc); 100 | }; 101 | AssociatedObject.Loaded += AssociatedObjectOnLoaded; 102 | AssociatedObject.Unloaded += AssociatedObjectUnloaded; 103 | } 104 | 105 | private void RestoreGlow() 106 | { 107 | if (_left != null) _left.IsGlowing = true; 108 | if (_top != null) _top.IsGlowing = true; 109 | if (_right != null) _right.IsGlowing = true; 110 | if (_bottom != null) _bottom.IsGlowing = true; 111 | Update(); 112 | } 113 | 114 | private void SetOpacityTo(double newOpacity) 115 | { 116 | if (_left == null || _right == null || _top == null || _bottom == null) return; 117 | _left.Opacity = newOpacity; 118 | _right.Opacity = newOpacity; 119 | _top.Opacity = newOpacity; 120 | _bottom.Opacity = newOpacity; 121 | } 122 | 123 | private void Show() 124 | { 125 | _left?.Show(); 126 | _right?.Show(); 127 | _top?.Show(); 128 | _bottom?.Show(); 129 | } 130 | 131 | private void Update() 132 | { 133 | if (!(_left != null && _right != null && _top != null && _bottom != null)) return; 134 | _left.Update(); 135 | _right.Update(); 136 | _top.Update(); 137 | _bottom.Update(); 138 | } 139 | 140 | #pragma warning disable 618 141 | private void UpdateCore() 142 | { 143 | if (!(_left != null && _right != null && _top != null && _bottom != null) || _handle == IntPtr.Zero) return; 144 | _left.Update(); 145 | _right.Update(); 146 | _top.Update(); 147 | _bottom.Update(); 148 | } 149 | #pragma warning restore 618 150 | 151 | /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms632612(v=vs.85).aspx 152 | [StructLayout(LayoutKind.Sequential)] 153 | internal struct WindowPosition 154 | { 155 | public IntPtr hWnd; 156 | 157 | public IntPtr hWndInsertAfter; 158 | 159 | public int x; 160 | 161 | public int y; 162 | 163 | public int cx; 164 | 165 | public int cy; 166 | 167 | public int flags; 168 | } 169 | 170 | #pragma warning disable 618 171 | private WindowPosition _prevWindowPos; 172 | 173 | private IntPtr AssociatedObjectWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 174 | { 175 | if (_hWndSource?.RootVisual == null) 176 | return IntPtr.Zero; 177 | 178 | switch (msg) 179 | { 180 | case 0x0047: 181 | case 0x0046: 182 | var wp = (WindowPosition) Marshal.PtrToStructure(lParam, typeof(WindowPosition)); 183 | if (!wp.Equals(_prevWindowPos)) 184 | UpdateCore(); 185 | _prevWindowPos = wp; 186 | break; 187 | case 0x0005: 188 | case 0x0214: 189 | UpdateCore(); 190 | break; 191 | default: 192 | return IntPtr.Zero; 193 | } 194 | return IntPtr.Zero; 195 | } 196 | #pragma warning restore 618 197 | } 198 | } -------------------------------------------------------------------------------- /ModernChrome/BindingProxy.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace ModernChrome 4 | { 5 | /// 6 | /// 7 | /// Used to store DynamicResource objects which can be referenced in StaticResource contexts. 8 | /// 9 | internal sealed class BindingProxy : Freezable 10 | { 11 | /// 12 | /// Identifies the property. 13 | /// 14 | public static readonly DependencyProperty DataProperty = 15 | DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); 16 | 17 | /// 18 | /// Gets or sets the data stored in this . 19 | /// 20 | public object Data 21 | { 22 | get => GetValue(DataProperty); 23 | set => SetValue(DataProperty, value); 24 | } 25 | 26 | protected override Freezable CreateInstanceCore() => new BindingProxy(); 27 | } 28 | } -------------------------------------------------------------------------------- /ModernChrome/Converters/BooleanToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | namespace ModernChrome.Converters 2 | { 3 | /// 4 | /// Represents the converter that converts Boolean values to and from Visibility enumeration values. 5 | /// 6 | internal sealed class BooleanToVisibilityConverter 7 | { 8 | private static System.Windows.Controls.BooleanToVisibilityConverter _instance; 9 | 10 | /// 11 | /// Gets a singleton instance of this converter. 12 | /// 13 | public static System.Windows.Controls.BooleanToVisibilityConverter Instance => 14 | _instance ?? (_instance = new System.Windows.Controls.BooleanToVisibilityConverter()); 15 | } 16 | } -------------------------------------------------------------------------------- /ModernChrome/Converters/FirstNotNullMultiConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Linq; 4 | using System.Windows.Data; 5 | 6 | namespace ModernChrome.Converters 7 | { 8 | /// 9 | /// 10 | /// Represents the converter that converts multiple values to the first value that is not null. 11 | /// 12 | internal sealed class FirstNotNullMultiConverter : IMultiValueConverter 13 | { 14 | private static FirstNotNullMultiConverter _instance; 15 | 16 | /// 17 | /// Gets a singleton instance of this converter. 18 | /// 19 | public static FirstNotNullMultiConverter Instance => 20 | _instance ?? (_instance = new FirstNotNullMultiConverter()); 21 | 22 | /// 23 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) => 24 | values.FirstOrDefault(value => value != null); 25 | 26 | /// 27 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => 28 | throw new NotImplementedException(); 29 | } 30 | } -------------------------------------------------------------------------------- /ModernChrome/Converters/ResizeModeToEnabledConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace ModernChrome.Converters 7 | { 8 | /// 9 | /// 10 | /// Represents the converter that converts ResizeMode enumeration values to boolean Enabled values. 11 | /// 12 | internal sealed class ResizeModeToEnabledConverter : IValueConverter 13 | { 14 | private static ResizeModeToEnabledConverter _instance; 15 | 16 | /// 17 | /// Gets a singleton instance of this converter. 18 | /// 19 | public static ResizeModeToEnabledConverter Instance => 20 | _instance ?? (_instance = new ResizeModeToEnabledConverter()); 21 | 22 | /// 23 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 24 | { 25 | if (!(value is ResizeMode resizeMode) || !(parameter is string param)) return false; 26 | // ReSharper disable once ConvertIfStatementToSwitchStatement 27 | if (param == "MIN") 28 | return resizeMode != ResizeMode.NoResize; 29 | if (param == "MAX") 30 | return resizeMode == ResizeMode.CanResize || resizeMode == ResizeMode.CanResizeWithGrip; 31 | return false; 32 | } 33 | 34 | /// 35 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => 36 | throw new NotImplementedException(); 37 | } 38 | } -------------------------------------------------------------------------------- /ModernChrome/Converters/WindowStateToThicknessConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace ModernChrome.Converters 7 | { 8 | /// 9 | /// 10 | /// Represents the converter that converts WindowState enumeration values to Thickness structs. 11 | /// 12 | internal sealed class WindowStateToThicknessConverter : IValueConverter 13 | { 14 | private static WindowStateToThicknessConverter _instance; 15 | 16 | /// 17 | /// Gets a singleton instance of this converter. 18 | /// 19 | public static WindowStateToThicknessConverter Instance => 20 | _instance ?? (_instance = new WindowStateToThicknessConverter()); 21 | 22 | /// 23 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => 24 | value is WindowState state 25 | ? (state == WindowState.Maximized ? new Thickness(0) : new Thickness(1)) 26 | : new Thickness(0); 27 | 28 | /// 29 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => 30 | throw new NotImplementedException(); 31 | } 32 | } -------------------------------------------------------------------------------- /ModernChrome/Converters/WindowStateToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace ModernChrome.Converters 7 | { 8 | /// 9 | /// 10 | /// Represents the converter that converts WindowState enumeration values to Visibility enumeration values. 11 | /// 12 | internal sealed class WindowStateToVisibilityConverter : IValueConverter 13 | { 14 | private static WindowStateToVisibilityConverter _instance; 15 | 16 | /// 17 | /// Gets a singleton instance of this converter. 18 | /// 19 | public static WindowStateToVisibilityConverter Instance => 20 | _instance ?? (_instance = new WindowStateToVisibilityConverter()); 21 | 22 | /// 23 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => 24 | value is WindowState state 25 | ? (state == WindowState.Maximized ? Visibility.Collapsed : Visibility.Visible) 26 | : Visibility.Collapsed; 27 | 28 | /// 29 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => 30 | throw new NotImplementedException(); 31 | } 32 | } -------------------------------------------------------------------------------- /ModernChrome/DesignTimeModernWindow.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Data; 4 | using System.Windows.Media; 5 | using System.Windows.Shapes; 6 | 7 | namespace ModernChrome 8 | { 9 | /// 10 | internal sealed class DesignTimeModernWindow : ModernWindow 11 | { 12 | /// 13 | public DesignTimeModernWindow() 14 | { 15 | CaptionIcon = new Ellipse {Width = 20, Height = 20}; 16 | BindingOperations.SetBinding((Ellipse) CaptionIcon, Shape.FillProperty, 17 | new Binding 18 | { 19 | Path = new PropertyPath("(TextBlock.Foreground)"), 20 | RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ContentPresenter), 1), 21 | FallbackValue = Brushes.Black 22 | }); 23 | Title = "Modern Chrome Window"; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /ModernChrome/DesignTimeResourceDictionary.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using System.ComponentModel; 4 | using System.Reflection; 5 | using System.Windows; 6 | 7 | namespace ModernChrome 8 | { 9 | /// 10 | internal sealed class DesignTimeResourceDictionary : ResourceDictionary 11 | { 12 | private readonly ObservableCollection _noopMergedDictionaries = 13 | new NoopObservableCollection(); 14 | 15 | /// 16 | public DesignTimeResourceDictionary() 17 | { 18 | var fieldInfo = typeof(ResourceDictionary).GetField("_mergedDictionaries", 19 | BindingFlags.Instance | BindingFlags.NonPublic); 20 | if (fieldInfo != null) 21 | fieldInfo.SetValue(this, _noopMergedDictionaries); 22 | } 23 | 24 | private static Lazy IsInDesignMode { get; } = 25 | new Lazy(() => DesignerProperties.GetIsInDesignMode(new DependencyObject())); 26 | 27 | private sealed class NoopObservableCollection : ObservableCollection 28 | { 29 | protected override void InsertItem(int index, T item) 30 | { 31 | if (IsInDesignMode.Value) 32 | base.InsertItem(index, item); 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /ModernChrome/ModernChrome.NET45.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {EF9ABD47-F09C-4DFD-8933-32196A90629E} 8 | Library 9 | Properties 10 | ModernChrome 11 | ModernChrome 12 | v4.5 13 | 512 14 | 15 | obj\net45\ 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\net45\ 22 | TRACE;DEBUG;NET45 23 | prompt 24 | 4 25 | bin\Debug\net45\ModernChrome.xml 26 | NU1602 27 | 28 | 29 | pdbonly 30 | true 31 | bin\Release\net45\ 32 | TRACE;NET45 33 | prompt 34 | 4 35 | bin\Release\net45\ModernChrome.xml 36 | NU1602 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | ModernWindowChrome.xaml 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | MSBuild:Compile 67 | Designer 68 | 69 | 70 | MSBuild:Compile 71 | Designer 72 | 73 | 74 | MSBuild:Compile 75 | Designer 76 | 77 | 78 | MSBuild:Compile 79 | Designer 80 | 81 | 82 | MSBuild:Compile 83 | Designer 84 | 85 | 86 | MSBuild:Compile 87 | Designer 88 | 89 | 90 | Designer 91 | MSBuild:Compile 92 | 93 | 94 | 95 | 96 | Designer 97 | MSBuild:Compile 98 | 99 | 100 | 101 | 102 | 1.0.1 103 | 104 | 105 | 1.6.0-alpha0128 106 | 107 | 108 | 4.3.0 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | RMDIR "$(TargetDir)en/" /S /Q 117 | RMDIR "$(TargetDir)es/" /S /Q 118 | RMDIR "$(TargetDir)fr/" /S /Q 119 | RMDIR "$(TargetDir)it/" /S /Q 120 | RMDIR "$(TargetDir)ja/" /S /Q 121 | RMDIR "$(TargetDir)ko/" /S /Q 122 | RMDIR "$(TargetDir)ru/" /S /Q 123 | RMDIR "$(TargetDir)zh-Hans/" /S /Q 124 | RMDIR "$(TargetDir)zh-Hant/" /S /Q 125 | 126 | -------------------------------------------------------------------------------- /ModernChrome/ModernChrome.NET47.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2DD68E07-20D5-4BDE-94AA-3B7ECD844524} 8 | Library 9 | Properties 10 | ModernChrome 11 | ModernChrome 12 | v4.7 13 | 512 14 | 15 | obj\net47\ 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\net47\ 22 | TRACE;DEBUG;NET47 23 | prompt 24 | 4 25 | bin\Debug\net47\ModernChrome.xml 26 | NU1602 27 | 28 | 29 | pdbonly 30 | true 31 | bin\Release\net47\ 32 | TRACE;NET47 33 | prompt 34 | 4 35 | bin\Release\net47\ModernChrome.xml 36 | NU1602 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | ModernWindowChrome.xaml 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | MSBuild:Compile 67 | Designer 68 | 69 | 70 | MSBuild:Compile 71 | Designer 72 | 73 | 74 | MSBuild:Compile 75 | Designer 76 | 77 | 78 | MSBuild:Compile 79 | Designer 80 | 81 | 82 | MSBuild:Compile 83 | Designer 84 | 85 | 86 | MSBuild:Compile 87 | Designer 88 | 89 | 90 | Designer 91 | MSBuild:Compile 92 | 93 | 94 | 95 | 96 | Designer 97 | MSBuild:Compile 98 | 99 | 100 | 101 | 102 | 1.0.1 103 | 104 | 105 | 1.6.0-alpha0128 106 | 107 | 108 | 4.3.0 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | RMDIR "$(TargetDir)en/" /S /Q 117 | RMDIR "$(TargetDir)es/" /S /Q 118 | RMDIR "$(TargetDir)fr/" /S /Q 119 | RMDIR "$(TargetDir)it/" /S /Q 120 | RMDIR "$(TargetDir)ja/" /S /Q 121 | RMDIR "$(TargetDir)ko/" /S /Q 122 | RMDIR "$(TargetDir)ru/" /S /Q 123 | RMDIR "$(TargetDir)zh-Hans/" /S /Q 124 | RMDIR "$(TargetDir)zh-Hant/" /S /Q 125 | 126 | -------------------------------------------------------------------------------- /ModernChrome/ModernChrome.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ModernChrome 6 | Visual Studio Modern WPF Theme 7 | 1.0.0-alpha001 8 | Christian Ivicevic 9 | civicevic 10 | https://github.com/ChristianIvicevic/ModernChrome/blob/master/LICENSE 11 | https://github.com/ChristianIvicevic/ModernChrome 12 | false 13 | Modern Chrome is a library for .NET WPF applications that provides a custom ModernWindow base class for windows that mimics the look of Visual Studio 2017 with a custom chrome and glowing borders. The library does NOT (at least not yet...) provide styles and control templates for general controls and only styles the base window and its chrome. 14 | Visual Studio Modern WPF Theme 15 | 16 | Copyright (c) 2017 Christian Ivicevic 17 | WPF Theme Modern ModernUI Metro MetroUI VisualStudio XAML UI .NET Toolkit 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ModernChrome/ModernWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | using System.Windows.Input; 6 | using System.Windows.Interop; 7 | using System.Windows.Media; 8 | using MahApps.Metro.Behaviours; 9 | using GlowWindowBehavior = ModernChrome.Behaviors.GlowWindowBehavior; 10 | 11 | namespace ModernChrome 12 | { 13 | /// 14 | public class ModernWindow : Window 15 | { 16 | /// 17 | /// Identifies the property. 18 | /// 19 | public static readonly DependencyProperty CaptionIconProperty = 20 | DependencyProperty.Register("CaptionIcon", typeof(object), typeof(ModernWindow), 21 | new PropertyMetadata(null)); 22 | 23 | /// 24 | /// Identifies the property. 25 | /// 26 | public static readonly DependencyProperty GlowBrushProperty = DependencyProperty.Register("GlowBrush", 27 | typeof(Brush), typeof(ModernWindow), new PropertyMetadata(null)); 28 | 29 | /// 30 | /// Identifies the property. 31 | /// 32 | public static readonly DependencyProperty NonActiveGlowBrushProperty = 33 | DependencyProperty.Register("NonActiveGlowBrush", typeof(Brush), typeof(ModernWindow), 34 | new PropertyMetadata(new SolidColorBrush(Color.FromRgb(153, 153, 153)))); 35 | 36 | /// 37 | /// Identiefies the property. 38 | /// 39 | public static readonly DependencyProperty ShowCaptionIconProperty = 40 | DependencyProperty.Register("ShowCaptionIcon", typeof(bool), typeof(ModernWindow), 41 | new PropertyMetadata(true)); 42 | 43 | /// 44 | /// Identifies the property. 45 | /// 46 | public static readonly DependencyProperty ShowCloseButtonProperty = 47 | DependencyProperty.Register("ShowCloseButton", typeof(bool), typeof(ModernWindow), 48 | new PropertyMetadata(true)); 49 | 50 | /// 51 | /// Identifies the property. 52 | /// 53 | public static readonly DependencyProperty ShowStatusBarProperty = 54 | DependencyProperty.Register("ShowStatusBar", typeof(bool), typeof(ModernWindow), 55 | new PropertyMetadata(true)); 56 | 57 | /// 58 | /// Identifies the property. 59 | /// 60 | public static readonly DependencyProperty StatusBarProperty = 61 | DependencyProperty.Register("StatusBar", typeof(object), typeof(ModernWindow), 62 | new PropertyMetadata(null)); 63 | 64 | private bool _shouldRestoreForDragMove; 65 | 66 | /// 67 | static ModernWindow() 68 | { 69 | DefaultStyleKeyProperty.OverrideMetadata(typeof(ModernWindow), 70 | new FrameworkPropertyMetadata(typeof(ModernWindow))); 71 | } 72 | 73 | /// 74 | public ModernWindow() 75 | { 76 | BorderBrush = new SolidColorBrush(Color.FromRgb(0x00, 0x7a, 0xcc)); 77 | // Enforce the visibility of the title bar and status bar. 78 | MinHeight = 35 + (ShowStatusBar ? 23 : 0) + 2; 79 | // Enforce the visibility of the icon (if any) and the window command buttons. 80 | MinWidth = 148; 81 | 82 | StylizedBehaviors.SetBehaviors(this, new StylizedBehaviorCollection 83 | { 84 | new BorderlessWindowBehavior(), 85 | new GlowWindowBehavior() 86 | }); 87 | 88 | BindingOperations.SetBinding(this, GlowBrushProperty, new Binding 89 | { 90 | Source = this, 91 | Path = new PropertyPath("BorderBrush") 92 | }); 93 | SetCurrentValue(BorderThicknessProperty, new Thickness(0)); 94 | } 95 | 96 | /// 97 | /// Gets or sets the caption icon displayed in the title bar. 98 | /// 99 | public object CaptionIcon 100 | { 101 | get => GetValue(CaptionIconProperty); 102 | set => SetValue(CaptionIconProperty, value); 103 | } 104 | 105 | /// 106 | /// Gets or sets the brush used for the Window's glow. 107 | /// 108 | public Brush GlowBrush 109 | { 110 | get => (Brush) GetValue(GlowBrushProperty); 111 | set => SetValue(GlowBrushProperty, value); 112 | } 113 | 114 | /// 115 | /// Gets or sets the brush used for the Window's non-active glow. 116 | /// 117 | public Brush NonActiveGlowBrush 118 | { 119 | get => (Brush) GetValue(NonActiveGlowBrushProperty); 120 | set => SetValue(NonActiveGlowBrushProperty, value); 121 | } 122 | 123 | /// 124 | /// Gets or sets a boolean value indicating whether the icon should be displayed in the title. 125 | /// 126 | public bool ShowCaptionIcon 127 | { 128 | // ReSharper disable once PossibleNullReferenceException 129 | get => (bool) GetValue(ShowCaptionIconProperty); 130 | set => SetValue(ShowCaptionIconProperty, value); 131 | } 132 | 133 | /// 134 | /// Gets or sets a boolen value indicating whether the close button should be displayed in the window command button 135 | /// line. 136 | /// 137 | public bool ShowCloseButton 138 | { 139 | // ReSharper disable once PossibleNullReferenceException 140 | get => (bool) GetValue(ShowCloseButtonProperty); 141 | set => SetValue(ShowCloseButtonProperty, value); 142 | } 143 | 144 | /// 145 | /// Gets or sets a boolean value indicating whether the default status bar should be displayed. 146 | /// 147 | public bool ShowStatusBar 148 | { 149 | // ReSharper disable once PossibleNullReferenceException 150 | get => (bool) GetValue(ShowStatusBarProperty); 151 | set => SetValue(ShowStatusBarProperty, value); 152 | } 153 | 154 | /// 155 | /// Gets or sets the contents of the status bar. 156 | /// 157 | public object StatusBar 158 | { 159 | get => GetValue(StatusBarProperty); 160 | set => SetValue(StatusBarProperty, value); 161 | } 162 | 163 | /// 164 | public override void OnApplyTemplate() 165 | { 166 | if (GetTemplateChild("WindowChrome") is ModernWindowChrome windowChrome) 167 | { 168 | windowChrome.DataContext = this; 169 | 170 | windowChrome.WindowCaptionBar.MouseRightButtonDown += WindowCaptionBar_OnMouseRightButtonDown; 171 | 172 | windowChrome.WindowTitleBar.MouseLeftButtonDown += WindowTitleBar_OnMouseLeftButtonDown; 173 | windowChrome.WindowTitleBar.MouseLeftButtonUp += WindowTitleBar_OnMouseLeftButtonUp; 174 | windowChrome.WindowTitleBar.MouseMove += WindowTitleBar_OnMouseMove; 175 | 176 | windowChrome.CloseButton.Click += (sender, args) => Close(); 177 | windowChrome.RestoreButton.Click += (sender, args) => 178 | WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; 179 | windowChrome.MinimizeButton.Click += (sender, args) => WindowState = WindowState.Minimized; 180 | } 181 | 182 | base.OnApplyTemplate(); 183 | } 184 | 185 | #region Event Handlers 186 | 187 | private void WindowCaptionBar_OnMouseRightButtonDown(object sender, MouseButtonEventArgs e) 188 | { 189 | var hWnd = new WindowInteropHelper(this).Handle; 190 | var point = PointToScreen(e.MouseDevice.GetPosition(this)); 191 | var cmd = TrackPopupMenu(GetSystemMenu(hWnd, false), 0x100, (int) point.X, (int) point.Y, 0, hWnd, 192 | IntPtr.Zero); 193 | if (cmd > 0) SendMessage(hWnd, 0x112, (IntPtr) cmd, IntPtr.Zero); 194 | } 195 | 196 | private void WindowTitleBar_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 197 | { 198 | if (e.ClickCount == 2) 199 | { 200 | if (ResizeMode == ResizeMode.CanResize || ResizeMode == ResizeMode.CanResizeWithGrip) 201 | WindowState = WindowState == WindowState.Maximized 202 | ? WindowState.Normal 203 | : WindowState.Maximized; 204 | } 205 | else 206 | { 207 | _shouldRestoreForDragMove = WindowState == WindowState.Maximized; 208 | DragMove(); 209 | } 210 | } 211 | 212 | private void WindowTitleBar_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 213 | { 214 | _shouldRestoreForDragMove = false; 215 | } 216 | 217 | private void WindowTitleBar_OnMouseMove(object sender, MouseEventArgs e) 218 | { 219 | if (!_shouldRestoreForDragMove) return; 220 | _shouldRestoreForDragMove = false; 221 | var pointToWindow = e.MouseDevice.GetPosition(sender as IInputElement); 222 | var pointToScreen = PointToScreen(pointToWindow); 223 | Left = pointToScreen.X - RestoreBounds.Width * 0.5; 224 | Top = Math.Max(0, pointToScreen.Y - pointToWindow.Y); 225 | WindowState = WindowState.Normal; 226 | DragMove(); 227 | } 228 | 229 | #endregion 230 | 231 | #region Native Methods 232 | 233 | /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647985(v=vs.85).aspx 234 | [DllImport("user32.dll")] 235 | private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); 236 | 237 | /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx 238 | [DllImport("user32.dll")] 239 | private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); 240 | 241 | /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms648002(v=vs.85).aspx 242 | [DllImport("user32.dll")] 243 | private static extern int TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y, int nReserved, IntPtr hWnd, 244 | IntPtr prcRect); 245 | 246 | #endregion 247 | } 248 | } -------------------------------------------------------------------------------- /ModernChrome/ModernWindowChrome.xaml: -------------------------------------------------------------------------------- 1 |  14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 69 | 70 | 71 | 73 | 74 | 75 | 76 | 77 | 78 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 129 | 130 | 142 | 143 | 146 | 147 | 148 | 151 | 152 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 177 | 209 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 239 | 241 | 244 | 247 | 248 | 249 | 250 | 251 | -------------------------------------------------------------------------------- /ModernChrome/ModernWindowChrome.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | using System.Windows.Threading; 7 | 8 | namespace ModernChrome 9 | { 10 | /// 11 | internal sealed partial class ModernWindowChrome 12 | { 13 | /// 14 | /// Identifies the property. 15 | /// 16 | public static readonly DependencyProperty CloseProperty = 17 | DependencyProperty.Register("Close", typeof(string), typeof(ModernWindowChrome), 18 | new PropertyMetadata(string.Empty)); 19 | 20 | /// 21 | /// Identifies the property. 22 | /// 23 | public static readonly DependencyProperty MaximizeProperty = 24 | DependencyProperty.Register("Maximize", typeof(string), typeof(ModernWindowChrome), 25 | new PropertyMetadata(string.Empty)); 26 | 27 | /// 28 | /// Identifies the property. 29 | /// 30 | public static readonly DependencyProperty MinimizeProperty = 31 | DependencyProperty.Register("Minimize", typeof(string), typeof(ModernWindowChrome), 32 | new PropertyMetadata(string.Empty)); 33 | 34 | /// 35 | /// Identifies the property. 36 | /// 37 | public static readonly DependencyProperty RestoreDownProperty = 38 | DependencyProperty.Register("RestoreDown", typeof(string), typeof(ModernWindowChrome), 39 | new PropertyMetadata(string.Empty)); 40 | 41 | /// 42 | public ModernWindowChrome() 43 | { 44 | InitializeComponent(); 45 | Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => 46 | { 47 | if (string.IsNullOrWhiteSpace(Minimize)) 48 | Minimize = GetCaption(900); 49 | if (string.IsNullOrWhiteSpace(Maximize)) 50 | Maximize = GetCaption(901); 51 | if (string.IsNullOrWhiteSpace(Close)) 52 | Close = GetCaption(905); 53 | if (string.IsNullOrWhiteSpace(RestoreDown)) 54 | RestoreDown = GetCaption(903); 55 | })); 56 | } 57 | 58 | /// 59 | /// Gets or sets the tool-tip for the close button. 60 | /// 61 | public string Close 62 | { 63 | get => (string) GetValue(CloseProperty); 64 | set => SetValue(CloseProperty, value); 65 | } 66 | 67 | /// 68 | /// Gets or sets the tool-tip for the maximize button. 69 | /// 70 | public string Maximize 71 | { 72 | get => (string) GetValue(MaximizeProperty); 73 | set => SetValue(MaximizeProperty, value); 74 | } 75 | 76 | /// 77 | /// Gets or sets the tool-tip for the minimize button. 78 | /// 79 | public string Minimize 80 | { 81 | get => (string) GetValue(MinimizeProperty); 82 | set => SetValue(MinimizeProperty, value); 83 | } 84 | 85 | /// 86 | /// Gets or sets the tool-tip for the restore button. 87 | /// 88 | public string RestoreDown 89 | { 90 | get => (string) GetValue(RestoreDownProperty); 91 | set => SetValue(RestoreDownProperty, value); 92 | } 93 | 94 | private static string GetCaption(int uId) 95 | { 96 | var hInstance = LoadLibrary(Environment.SystemDirectory + @"\User32.dll"); 97 | var lpBuffer = new StringBuilder(256); 98 | LoadString(hInstance, uId, lpBuffer, lpBuffer.Capacity); 99 | FreeLibrary(hInstance); 100 | return lpBuffer.ToString().Replace("&", ""); 101 | } 102 | 103 | #region Native Methods 104 | 105 | /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx 106 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)] 107 | private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); 108 | 109 | /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647486(v=vs.85).aspx 110 | [DllImport("user32.dll", CharSet = CharSet.Auto)] 111 | private static extern int LoadString(IntPtr hInstance, int uId, StringBuilder lpBuffer, int nBufferMax); 112 | 113 | /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683152(v=vs.85).aspx 114 | [DllImport("kernel32.dll", SetLastError = true)] 115 | [return: MarshalAs(UnmanagedType.Bool)] 116 | private static extern bool FreeLibrary(IntPtr hModule); 117 | 118 | #endregion 119 | } 120 | } -------------------------------------------------------------------------------- /ModernChrome/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 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("Modern Chrome")] 9 | [assembly: AssemblyDescription("Visual Studio Modern WPF Theme")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Modern Chrome")] 13 | [assembly: AssemblyCopyright("Copyright (c) 2017 Christian Ivicevic")] 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 | [assembly: ThemeInfo( 23 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 24 | //(used if a resource is not found in the page, 25 | // or application resource dictionaries) 26 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 27 | //(used if a resource is not found in the page, 28 | // app, or any theme specific resource dictionaries) 29 | )] 30 | 31 | // Version information for an assembly consists of the following four values: 32 | // 33 | // Major Version 34 | // Minor Version 35 | // Build Number 36 | // Revision 37 | // 38 | // You can specify all the values or you can default the Build and Revision Numbers 39 | // by using the '*' as shown below: 40 | // [assembly: AssemblyVersion("1.0.*")] 41 | [assembly: AssemblyVersion("1.0.0.0")] 42 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /ModernChrome/ThemeChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ModernChrome 4 | { 5 | /// 6 | /// 7 | /// Class which is used as argument for an event to signal theme changes. 8 | /// 9 | public sealed class ThemeChangedEventArgs : EventArgs 10 | { 11 | /// 12 | /// Creates a new instance of this class with the specified theme argument. 13 | /// 14 | /// The new theme. 15 | // ReSharper disable once InheritdocConsiderUsage 16 | public ThemeChangedEventArgs(string theme) => Theme = theme; 17 | 18 | /// 19 | /// The new theme. 20 | /// 21 | public string Theme { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /ModernChrome/ThemeManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.RegularExpressions; 5 | using System.Windows; 6 | 7 | namespace ModernChrome 8 | { 9 | /// 10 | /// A class that allows for the detection and alteration of a theme. 11 | /// 12 | public static class ThemeManager 13 | { 14 | private static IList _themeList; 15 | 16 | private static string CurrentTheme { get; set; } 17 | 18 | /// 19 | /// Gets all available theme dictionaries. 20 | /// 21 | public static IEnumerable Themes 22 | { 23 | get 24 | { 25 | if (_themeList != null) 26 | return _themeList; 27 | try 28 | { 29 | // GetUriFromTheme(GetThemeFromUri(...)) ensures proper pack syntax. 30 | // Please don't judge me... 31 | _themeList = new ResourceDictionary {Source = GetUriFromTheme("Themes")}.MergedDictionaries 32 | .Select(d => GetUriFromTheme(GetThemeFromUri(d.Source))).ToList(); 33 | } 34 | catch 35 | { 36 | // ignored 37 | } 38 | return _themeList; 39 | } 40 | } 41 | 42 | /// 43 | /// Changes the theme of the specified application to the provided theme. 44 | /// 45 | /// Application to inject theme into. 46 | /// New theme to inject. 47 | public static void ChangeTheme(Application app, string newTheme) 48 | { 49 | ResourceDictionary detectedTheme = null; 50 | // Try to detect the user-loaded theme during the first call. 51 | if (string.IsNullOrEmpty(CurrentTheme)) 52 | foreach (var theme in Themes) 53 | { 54 | var currentTheme = app.Resources.MergedDictionaries.Reverse().Where(x => x.Source != null) 55 | .FirstOrDefault(d => string.Equals(d.Source.ToString(), theme.ToString(), 56 | StringComparison.CurrentCultureIgnoreCase)); 57 | if (currentTheme == null) continue; 58 | detectedTheme = currentTheme; 59 | CurrentTheme = GetThemeFromUri(currentTheme.Source); 60 | break; 61 | } 62 | if (CurrentTheme == newTheme) return; 63 | app.Resources.MergedDictionaries.Add(new ResourceDictionary 64 | { 65 | Source = GetUriFromTheme(newTheme) 66 | }); 67 | 68 | if (detectedTheme == null) 69 | detectedTheme = app.Resources.MergedDictionaries.Where(x => x.Source != null).FirstOrDefault(d => 70 | string.Equals(d.Source.ToString(), GetUriFromTheme(CurrentTheme).ToString(), 71 | StringComparison.CurrentCultureIgnoreCase)); 72 | app.Resources.MergedDictionaries.Remove(detectedTheme); 73 | CurrentTheme = newTheme; 74 | OnThemeChanged(newTheme); 75 | } 76 | 77 | private static string GetThemeFromUri(Uri uri) 78 | { 79 | var matches = Regex.Match(uri.ToString(), 80 | @"(?:pack://application:,,,/ModernChrome;component/Themes/)?(\w+)\.xaml"); 81 | return matches.Success ? matches.Groups[1].Value : string.Empty; 82 | } 83 | 84 | private static Uri GetUriFromTheme(string theme) => 85 | new Uri($"pack://application:,,,/ModernChrome;component/Themes/{theme}.xaml"); 86 | 87 | /// 88 | /// This event is fired when the theme has been changed. 89 | /// 90 | public static event EventHandler ThemeChanged; 91 | 92 | private static void OnThemeChanged(string newTheme) => 93 | ThemeChanged?.Invoke(Application.Current, new ThemeChangedEventArgs(newTheme)); 94 | } 95 | } -------------------------------------------------------------------------------- /ModernChrome/Themes/Blend.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | #000000 5 | #ffffff 6 | #929292 7 | #d5d5d5 8 | #000000 9 | #2e2e36 10 | #767677 11 | #929292 12 | #007acc 13 | #227447 14 | #ca5100 15 | #68217a 16 | #ffffff 17 | #1a1a1d 18 | #007acc 19 | #007acc 20 | #ffffff 21 | #343436 22 | #343436 23 | #ffffff 24 | #1a1a1d 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ModernChrome/Themes/Dark.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | #000000 5 | #ffffff 6 | #999999 7 | #f1f1f1 8 | #000000 9 | #424245 10 | #818183 11 | #6f6f70 12 | #007acc 13 | #227447 14 | #ca5100 15 | #68217a 16 | #ffffff 17 | #2d2d30 18 | #007acc 19 | #007acc 20 | #ffffff 21 | #3f3f41 22 | #3f3f41 23 | #ffffff 24 | #2d2d30 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ModernChrome/Themes/DarkBlue.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | #000000 5 | #ffffff 6 | #ffffff 7 | #ced4dd 8 | #000000 9 | #515151 10 | #7f8899 11 | #b4bac4 12 | #007acc 13 | #227447 14 | #ca5100 15 | #68217a 16 | #ffffff 17 | #293955 18 | #ffe8a6 19 | #e5c365 20 | #000000 21 | #e5c365 22 | #fffcf4 23 | #000000 24 | #293955 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ModernChrome/Themes/Generic.xaml: -------------------------------------------------------------------------------- 1 |  4 | 17 | -------------------------------------------------------------------------------- /ModernChrome/Themes/Light.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | #9a9eb8 5 | #007acc 6 | #525252 7 | #1e1e1e 8 | #000000 9 | #cbcdda 10 | #8f8f91 11 | #949496 12 | #007acc 13 | #227447 14 | #ca5100 15 | #68217a 16 | #ffffff 17 | #eeeef2 18 | #007acc 19 | #007acc 20 | #ffffff 21 | #fcfcfd 22 | #fcfcfd 23 | #007acc 24 | #eeeef2 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ModernChrome/Themes/LightBlue.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | #000000 5 | #007acc 6 | #000000 7 | #000000 8 | #000000 9 | #515151 10 | #80838c 11 | #62646b 12 | #007acc 13 | #227447 14 | #ca5100 15 | #68217a 16 | #ffffff 17 | #293955 18 | #ffe8a6 19 | #e5c365 20 | #000000 21 | #e5c365 22 | #fffcf4 23 | #000000 24 | #d6dbe9 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ModernChrome/Themes/Themes.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /ModernChromeLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QtLab/ModernChrome/6f75a2ed99d3cd44c30ef354e1b9e4e992d019b4/ModernChromeLogo.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![Modern Chrome Logo](ModernChromeLogo.png) 3 | 4 | # 5 | 6 |
7 | 8 | 9 | 10 |
11 | 12 | # Description 13 | 14 | Modern Chrome is a library for .NET WPF applications that provides a custom `ModernWindow` base class for windows that mimics the look of Visual Studio 2017 with a custom chrome and glowing borders. The library does **NOT** *(at least not yet...)* provide styles and control templates for general controls and only styles the base window and its chrome. 15 | 16 | # Screenshots 17 | 18 | ## Themes 19 | 20 | The library currently supports the five themes `LightBlue`, `DarkBlue`, `Light`, `Dark` and `Blend`. 21 | 22 | ![Light Blue Theme](Images/LightBlue-Theme.png) 23 | ![Dark Blue Theme](Images/DarkBlue-Theme.png) 24 | ![Light Theme](Images/Light-Theme.png) 25 | ![Dark Theme](Images/Dark-Theme.png) 26 | ![Blend Theme](Images/Blend-Theme.png) 27 | 28 | ## Accents 29 | 30 | The following screenshot displays the predefined accent colors which can be customized: 31 | 32 | ![Dark Blue Accents](Images/DarkBlue-Accents.png) 33 | 34 | ## Dialogs 35 | 36 | The following screenshot shows a sample dialog and how the main window in the background loses its colored border as well as having the icon and text appear in a disabled state: 37 | 38 | ![Light Blue Dialog](Images/LightBlue-Dialog.png) 39 | 40 | # Quick Start 41 | 42 | Follow this short guide on getting started quickly - **it is HIGHLY suggested to browse the sample application for further customization and usage**. 43 | 44 | ## Setting up the project 45 | 46 | 1. Download the source from the repository or download the [NuGet package](https://www.nuget.org/packages/ModernChrome/) via the package manager. 47 | 2. In your `App.xaml` of your main application you have to add one of the available theme `ResourceDictionaries` with the following snippet while picking one of the available themes (IntelliSense will provide support for selecting a theme and you can either select `LightBlue.xaml`, `DarkBlue.xaml`, `Light.xaml`, `Dark.xaml` or `Blend.xaml`): 48 | ```xaml 49 | 50 | 51 | 52 | 53 | 54 | ``` 55 | 3. In your `MainWindow.xaml` you have to reference the *ModernChrome* namespace and change the window class to `ModernWindow` in the XAML file (and your `MainWindow.xaml.cs` if you happen to redudantly explicitly inherit from the previous `Window`): 56 | ```xaml 57 | 62 | 63 | 64 | ``` 65 | ```csharp 66 | namespace ModernChrome.Sample 67 | { 68 | public partial class MainWindow : ModernWindow // this can be dropped anyways 69 | { 70 | public MainWindow() 71 | { 72 | InitializeComponent(); 73 | } 74 | } 75 | } 76 | ``` 77 | 78 | ## Optional Quality of Life tweaks 79 | 80 | 1. Since this library is dependendant on the *Microsoft.Expression.Interactions* library from the Expression Blend SDK you might get a bunch of localization folders in your project output. I suggest going into your project properties under **Build Events** and adding the following **post-build event command line** to be executed **On successful build** (adjust as necessary if you happen to have either more or less folders): 81 | ``` 82 | RMDIR "$(TargetDir)en/" /S /Q 83 | RMDIR "$(TargetDir)es/" /S /Q 84 | RMDIR "$(TargetDir)fr/" /S /Q 85 | RMDIR "$(TargetDir)it/" /S /Q 86 | RMDIR "$(TargetDir)ja/" /S /Q 87 | RMDIR "$(TargetDir)ko/" /S /Q 88 | RMDIR "$(TargetDir)ru/" /S /Q 89 | RMDIR "$(TargetDir)zh-Hans/" /S /Q 90 | RMDIR "$(TargetDir)zh-Hant/" /S /Q 91 | ``` 92 | 2. Currently the library is dependent on alpha builds of *MahApps.Metro* and you will most likely get the following NuGet warning: 93 | ``` 94 | NU1602 MahApps.Metro 1.6.0-alpha0XXX does not provide an inclusive lower bound for dependency ControlzEx (> 3.0.2 && < 4.0.0). An approximate best match of ControlzEx 3.X.X.X was resolved. 95 | ``` 96 | Until this gets fixed by the developer of *MahApps.Metro* you can supress this warning by going to your project properties and adding `NU1602` under **Build** and **Suppress warnings**. 97 | 98 | ## Customizations 99 | 100 | ### Themes 101 | 102 | The application theme can be selected via the `ResourceDictionary` imported in the `App.xaml` or during runtime by calling 103 | 104 | ```csharp 105 | ModernChrome.ThemeManager.ChangeTheme(Application.Current, theme); 106 | ``` 107 | 108 | where `theme` is a string to an available theme. Currently you can select `LightBlue`, `DarkBlue`, `Light`, `Dark` or `Blend`. Previously loaded themes are automatically removed from the `Application.Resources.MergedDictionaries` and the new theme is injected automatically. 109 | 110 | Furthermore you can track theme changes during runtime through the exposed `ModernChrome.ThemeManager.ThemeChanged` event which provides a `ThemeChangedEventArgs` holding the name of the newly loaded theme. Listening to the event is showed in the sample application: 111 | 112 | ```csharp 113 | ModernChrome.ThemeManager.ThemeChanged += (sender, args) => 114 | { 115 | if (args.Theme != "Light") 116 | { 117 | ThemeText.Foreground = Brushes.White; 118 | AccentText.Foreground = Brushes.White; 119 | ActionText.Foreground = Brushes.White; 120 | } 121 | else 122 | { 123 | ThemeText.Foreground = Brushes.Black; 124 | AccentText.Foreground = Brushes.Black; 125 | ActionText.Foreground = Brushes.Black; 126 | } 127 | }; 128 | ``` 129 | 130 | Although the themes do provide a `Background` color for `ModernWindow`s you can define your custom color if necessary, it won't be overwritten. 131 | 132 | ### Status bar and glowing border (Accent) 133 | 134 | `ModernWindow` provides a default status bar if you don't disable it manually via the `ModernWindow.ShowStatusBar` dependency property. Both the status bar color and the glowing border are bound to the `ModernWindow.BorderBrush` property. 135 | 136 | If you opt-in to use the default status bar that comes with the library you can add controls to it via the `ModernWindow.StatusBar` dependency property: 137 | 138 | ```csharp 139 | 140 | Ready 141 | 142 | ``` 143 | 144 | The `ContentPresenter` that displays your custom content stores the current suggested `Foreground` via `TextBlock.Foreground="{DynamicResource StatusBarTextBrushKey}"` and thus making sure that `TextBlock` controls always inherit a color that will be readable **IF** you use default `BorderBrush` colors. Otherwise you have to adjust the colors yourself. 145 | 146 | Once again the themes do provide a default `BorderBrush` color for `ModernWindow`s but you can define your custom color if necessary, it won't be overwritten. 147 | 148 | ### Window icon 149 | 150 | The window icon, internally refered to as caption icon, can be hidden using the `ModernWindow.ShowCaptionIcon` property which is useful for dialog windows. The window title bar will adjust accordingly depending on the value of the property. 151 | 152 | A custom caption icon is automatically displayed with the dimensions 20 x 20 and it is recommended to use a `Path` control for scalable icons. Similiar to the status bar you can define your icon as follows: 153 | 154 | ```csharp 155 | 156 | 159 | 160 | ``` 161 | 162 | You might wonder about the `Fill="{Binding Path=(TextBlock.Foreground), RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"`. The different themes used in the library have different colors depending on the `Window.IsActive` value. E.g. with the `LightBlue` theme my icon will generally appear in blue unless the window has lost focus which turns the icon gray. It is suggested to bind against this color in order to visually highlight when the window has lost focus. 163 | 164 | ### Window command buttons (Minimize, Maximize, Restore, Close) 165 | 166 | Usually a window enables or disables those buttons depending on the value of `Window.ResizeMode` however `ModernWindow` handles this slightly different, since it does not only disable those buttons, it removes them entirely. Furthermore it provides the `ModernWindow.ShowCloseButton` property to hide the close button as well for convenience which would usually need P/Invoke calls. Keep in mind though, that Alt + F4 will most likely still work and you have to intercept the `Closing` event and abort it if necessary. 167 | 168 | # Dependencies 169 | The library does not reinvent the wheel, it only combines and strips the functionality of the following available packages: 170 | * [ControlzEx](https://github.com/ControlzEx/ControlzEx) 171 | * [Expression.Blend.Sdk.WPF](https://www.nuget.org/packages/Expression.Blend.Sdk.WPF/) 172 | * [MahApps.Metro](https://github.com/MahApps/MahApps.Metro) 173 | 174 | It is highly recommended to switch the default package management format of NuGet to `PackageReference` in order to reduce clutter and collisions with other projects. 175 | 176 | *MetroChrome* reuses the `BorderlessWindowBehavior` and a customized `GlowWindowBehavior` from the *MahApps.Metro* library to provide a window that can be easily resized and handled using AeroSnap and has a glowing border. 177 | 178 | # Important Notice 179 | Neither I nor the *ModernChrome* library are affiliated with, sponsored by, endorsed or approved by Microsoft. This project only mimics the style of Visual Studio and provides resources for custom applications. 180 | 181 | **Visual Studio and its logo are registered trademarks of the Microsoft Corporation.** 182 | 183 | # License 184 | This project is licensed under the [MIT License](./LICENSE). 185 | --------------------------------------------------------------------------------