├── .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 | Light Blue Theme
35 | Dark Blue Theme
36 | Generic Light Theme
37 | Generic Dark Theme
38 | Blend Theme
39 |
40 |
41 |
42 |
46 |
47 |
48 | Blue Accent
49 | Orange Accent
50 | Purple Accent
51 | Green Accent
52 |
53 |
54 |
55 |
59 |
60 |
61 | Show Dialog
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 | Performing really important stuff...
19 |
20 |
21 |
23 | Close Window
24 |
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 |
174 |
176 |
177 |
179 |
180 |
191 |
192 |
194 |
195 |
206 |
207 |
208 |
209 |
212 |
215 |
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 | 
3 |
4 | #
5 |
6 |
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 | 
23 | 
24 | 
25 | 
26 | 
27 |
28 | ## Accents
29 |
30 | The following screenshot displays the predefined accent colors which can be customized:
31 |
32 | 
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 | 
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 |
--------------------------------------------------------------------------------