├── .gitattributes
├── .gitignore
├── Arthas.Demo
├── App.manifest
├── App.xaml
├── App.xaml.cs
├── Arthas.Demo.csproj
├── Properties
│ └── AssemblyInfo.cs
├── Resources
│ ├── editIcon.png
│ ├── icon.png
│ ├── iconMove.png
│ ├── pic.jpg
│ ├── tabIcon.png
│ └── titleMuenIcon.png
└── Views
│ ├── Caption.xaml
│ ├── Caption.xaml.cs
│ ├── Caption_Model.cs
│ ├── ControlGallery.xaml
│ ├── ControlGallery.xaml.cs
│ ├── ControlGallery_Model.cs
│ ├── ExpanderDemo.xaml
│ ├── ExpanderDemo.xaml.cs
│ ├── ExpanderDemo_Model.cs
│ ├── Main.xaml
│ ├── Main.xaml.cs
│ └── Main_Model.cs
├── Arthas.Shell
├── Arthas.Shell.csproj
├── Extensions.cs
├── Interop
│ ├── GWL.cs
│ ├── HT.cs
│ ├── POINT.cs
│ ├── RECT.cs
│ ├── SW.cs
│ ├── SWP.cs
│ ├── WINDOWPLACEMENT.cs
│ ├── WM.cs
│ ├── WS.cs
│ ├── WVR.cs
│ └── Win32.cs
├── MetroWindowBase.cs
├── MetroWindowChrome.cs
└── ScreenHelper.cs
├── Arthas.sln
├── Arthas
├── Arthas.csproj
├── Binder
│ ├── MetroDialogModel.cs
│ └── MetroWindowModel.cs
├── Controls
│ ├── MetroBorder.cs
│ ├── MetroBorder.xaml
│ ├── MetroButton.cs
│ ├── MetroButton.xaml
│ ├── MetroButtonState.cs
│ ├── MetroCaptionMenu.cs
│ ├── MetroCaptionMenu.xaml
│ ├── MetroCaptionMenuItem.cs
│ ├── MetroCaptionMenuItem.xaml
│ ├── MetroContextMenu.cs
│ ├── MetroContextMenu.xaml
│ ├── MetroExpander.cs
│ ├── MetroExpander.xaml
│ ├── MetroFocusButton.cs
│ ├── MetroFocusButton.xaml
│ ├── MetroGridTile.cs
│ ├── MetroGridTile.xaml
│ ├── MetroGroup.cs
│ ├── MetroGroup.xaml
│ ├── MetroMenuItem.cs
│ ├── MetroMenuItem.xaml
│ ├── MetroMenuSeparator.cs
│ ├── MetroMenuSeparator.xaml
│ ├── MetroProgressBar.cs
│ ├── MetroProgressBar.xaml
│ ├── MetroScrollViewer.cs
│ ├── MetroScrollViewer.xaml
│ ├── MetroSwitch.cs
│ ├── MetroSwitch.xaml
│ ├── MetroTabControl.cs
│ ├── MetroTabControl.xaml
│ ├── MetroTabItem.cs
│ ├── MetroTabItem.xaml
│ ├── MetroTextBlock.cs
│ ├── MetroTextBlock.xaml
│ ├── MetroTextBox.cs
│ ├── MetroTextBox.xaml
│ ├── MetroTextButton.cs
│ ├── MetroTextButton.xaml
│ ├── MetroTile.cs
│ ├── MetroTile.xaml
│ ├── MetroWaterfallFlow.cs
│ ├── MetroWindow.cs
│ ├── MetroWindow.xaml
│ └── ProgressBarState.cs
├── Converter
│ ├── CornerRadiusToDouble.cs
│ ├── DoubleToCornerRadius.cs
│ └── DoubleToThickness.cs
├── Properties
│ └── AssemblyInfo.cs
├── Resource.cs
├── ThemeBrush.cs
├── ThemeKey.cs
└── Themes
│ └── Generic.xaml
├── Build.bat
├── Directory.Build.props
├── LICENSE
├── README.md
└── Screenshots
└── 1.png
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.exe filter=lfs diff=lfs merge=lfs -text
2 | *.dll filter=lfs diff=lfs merge=lfs -text
3 | *.png filter=lfs diff=lfs merge=lfs -text
4 | *.jpg filter=lfs diff=lfs merge=lfs -text
5 | *.ico filter=lfs diff=lfs merge=lfs -text
6 | *.zip filter=lfs diff=lfs merge=lfs -text
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vs
3 | bin
4 | obj
5 |
6 | *.user
7 |
--------------------------------------------------------------------------------
/Arthas.Demo/App.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Arthas.Demo/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
--------------------------------------------------------------------------------
/Arthas.Demo/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using Arthas.Demo.Views;
3 |
4 | namespace Arthas.Demo;
5 |
6 | public partial class App
7 | {
8 | protected override void OnStartup(StartupEventArgs e)
9 | {
10 | base.OnStartup(e);
11 |
12 | var mainModel = new Main_Model();
13 | var window = mainModel.CreateWindow();
14 | MainWindow = window;
15 | MainWindow.Show();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Arthas.Demo/Arthas.Demo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | WinExe
4 | App.manifest
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Arthas.Demo/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | [assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
4 |
--------------------------------------------------------------------------------
/Arthas.Demo/Resources/editIcon.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:7e046688a6f9b00755ef306296470277accda111c9779e57e80a329619453068
3 | size 17869
4 |
--------------------------------------------------------------------------------
/Arthas.Demo/Resources/icon.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:ba3763f810ff8d6768b87f27c26fa3163ae21458a71c461248d404d0c868f964
3 | size 18153
4 |
--------------------------------------------------------------------------------
/Arthas.Demo/Resources/iconMove.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:f90643ff930631d47f6a6802f1d861e7183949707117b5db51ada2a80a9832a8
3 | size 18206
4 |
--------------------------------------------------------------------------------
/Arthas.Demo/Resources/pic.jpg:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:73c0f860410d171b35567575ae0c9b5eb7a65645837390f944f5758c7212e67c
3 | size 119761
4 |
--------------------------------------------------------------------------------
/Arthas.Demo/Resources/tabIcon.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:bdd5248ccbcb58948cc2e4d9c6ecfff66de7620e87e5865c7dbe75cf65808fea
3 | size 18307
4 |
--------------------------------------------------------------------------------
/Arthas.Demo/Resources/titleMuenIcon.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:6d747940e0141f989c13c37c7bcde0d1d70fac127b7afc9f9b9af917eca58cc5
3 | size 18299
4 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/Caption.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/Caption.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace Arthas.Demo.Views;
2 |
3 | public partial class Caption
4 | {
5 | public Caption()
6 | {
7 | InitializeComponent();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/Caption_Model.cs:
--------------------------------------------------------------------------------
1 | using OpenView;
2 |
3 | namespace Arthas.Demo.Views;
4 |
5 | public class Caption_Model : ViewModel
6 | {
7 | }
8 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/ControlGallery.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
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 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/ControlGallery.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace Arthas.Demo.Views;
2 |
3 | public partial class ControlGallery
4 | {
5 | public ControlGallery()
6 | {
7 | InitializeComponent();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/ControlGallery_Model.cs:
--------------------------------------------------------------------------------
1 | using OpenView;
2 |
3 | namespace Arthas.Demo.Views;
4 |
5 | public class ControlGallery_Model : ViewModel
6 | {
7 | }
8 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/ExpanderDemo.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/ExpanderDemo.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace Arthas.Demo.Views;
2 |
3 | public partial class ExpanderDemo
4 | {
5 | public ExpanderDemo()
6 | {
7 | InitializeComponent();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/ExpanderDemo_Model.cs:
--------------------------------------------------------------------------------
1 | using OpenView;
2 |
3 | namespace Arthas.Demo.Views;
4 |
5 | public class ExpanderDemo_Model : ViewModel
6 | {
7 | }
8 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/Main.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/Main.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace Arthas.Demo.Views;
2 |
3 | public partial class Main
4 | {
5 | public Main()
6 | {
7 | InitializeComponent();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Arthas.Demo/Views/Main_Model.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using Arthas.Binder;
3 | using Arthas.Controls;
4 |
5 | namespace Arthas.Demo.Views;
6 |
7 | public class Main_Model : MetroWindowModel
8 | {
9 | public override string Title => "Arthas.Demo";
10 |
11 | protected override void OnWindowInitialized(Window window)
12 | {
13 | base.OnWindowInitialized(window);
14 |
15 | window.Width = 1200;
16 | window.Height = 860;
17 |
18 | if (window is MetroWindow metroWindow)
19 | metroWindow.CaptionContent = new Caption_Model().CreateView();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Arthas.Shell/Arthas.Shell.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | disable
4 | true
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Arthas.Shell/Extensions.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | namespace Arthas.Shell;
4 |
5 | public static class Extensions
6 | {
7 | public static void BringToFront(this Window? window)
8 | {
9 | if (window is null)
10 | return;
11 |
12 | try
13 | {
14 | if (!window.IsVisible)
15 | return;
16 |
17 | window.Activate();
18 | window.Focus();
19 | }
20 | catch
21 | {
22 | // ignored
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Arthas.Shell/Interop/GWL.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 |
3 | namespace Arthas.Shell.Interop;
4 |
5 | ///
6 | /// GetWindowLongPtr values, GWL_*
7 | ///
8 | [SuppressMessage("ReSharper", "InconsistentNaming")]
9 | enum GWL
10 | {
11 | STYLE = -16
12 | }
13 |
--------------------------------------------------------------------------------
/Arthas.Shell/Interop/HT.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 |
3 | namespace Arthas.Shell.Interop;
4 |
5 | [SuppressMessage("ReSharper", "InconsistentNaming")]
6 | enum HT
7 | {
8 | CAPTION = 2
9 | }
10 |
--------------------------------------------------------------------------------
/Arthas.Shell/Interop/POINT.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace Arthas.Shell.Interop;
6 |
7 | [Serializable]
8 | [StructLayout(LayoutKind.Sequential)]
9 | [SuppressMessage("ReSharper", "InconsistentNaming")]
10 | struct POINT
11 | {
12 | public int X { get; set; }
13 | public int Y { get; set; }
14 | }
15 |
--------------------------------------------------------------------------------
/Arthas.Shell/Interop/RECT.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace Arthas.Shell.Interop;
6 |
7 | [StructLayout(LayoutKind.Sequential, Pack = 0)]
8 | [Serializable]
9 | [SuppressMessage("ReSharper", "InconsistentNaming")]
10 | struct RECT
11 | {
12 | public int Left { get; set; }
13 |
14 | public int Top { get; set; }
15 |
16 | public int Right { get; set; }
17 |
18 | public int Bottom { get; set; }
19 |
20 | public int Width => Right - Left;
21 |
22 | public int Height => Bottom - Top;
23 |
24 | public void Offset(int dx, int dy)
25 | {
26 | Left += dx;
27 | Top += dy;
28 | Right += dx;
29 | Bottom += dy;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Arthas.Shell/Interop/SW.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 |
3 | namespace Arthas.Shell.Interop;
4 |
5 | ///
6 | /// ShowWindow options
7 | ///
8 | [SuppressMessage("ReSharper", "InconsistentNaming")]
9 | enum SW
10 | {
11 | SHOWMINIMIZED = 2,
12 | SHOWMAXIMIZED = 3
13 | }
14 |
--------------------------------------------------------------------------------
/Arthas.Shell/Interop/SWP.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 |
4 | namespace Arthas.Shell.Interop;
5 |
6 | ///
7 | /// SetWindowPos options
8 | ///
9 | [Flags]
10 | [SuppressMessage("ReSharper", "InconsistentNaming")]
11 | enum SWP : uint
12 | {
13 | ///
14 | /// Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to the window, even if
15 | /// the
16 | /// window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window's
17 | /// size is
18 | /// being changed.
19 | ///
20 | FRAMECHANGED = 0x0020,
21 |
22 | ///
23 | /// Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the
24 | /// topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter).
25 | ///
26 | NOACTIVATE = 0x0010,
27 |
28 | ///
29 | /// Retains the current position (ignores X and Y parameters).
30 | ///
31 | NOMOVE = 0x0002,
32 |
33 | ///
34 | /// Does not change the owner window's position in the Z order.
35 | ///
36 | NOOWNERZORDER = 0x0200,
37 |
38 | ///
39 | /// Retains the current size (ignores the cx and cy parameters).
40 | ///
41 | NOSIZE = 0x0001,
42 |
43 | ///
44 | /// Retains the current Z order (ignores the hWndInsertAfter parameter).
45 | ///
46 | NOZORDER = 0x0004,
47 |
48 | ///
49 | /// Displays the window.
50 | ///
51 | SHOWWINDOW = 0x0040
52 | }
53 |
--------------------------------------------------------------------------------
/Arthas.Shell/Interop/WINDOWPLACEMENT.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace Arthas.Shell.Interop;
6 |
7 | [Serializable]
8 | [StructLayout(LayoutKind.Sequential)]
9 | [SuppressMessage("ReSharper", "InconsistentNaming")]
10 | class WINDOWPLACEMENT
11 | {
12 | public int length = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
13 | public int flags;
14 | public SW showCmd;
15 | public POINT minPosition;
16 | public POINT maxPosition;
17 | public RECT normalPosition;
18 | }
19 |
--------------------------------------------------------------------------------
/Arthas.Shell/Interop/WM.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 |
3 | namespace Arthas.Shell.Interop;
4 |
5 | ///
6 | /// Window message values, WM_*
7 | ///
8 | [SuppressMessage("ReSharper", "InconsistentNaming")]
9 | enum WM
10 | {
11 | NCCALCSIZE = 0x0083,
12 | NCPAINT = 0x0085,
13 | NCLBUTTONDOWN = 0x00A1,
14 | DPICHANGED = 0x02E0
15 | }
16 |
--------------------------------------------------------------------------------
/Arthas.Shell/Interop/WS.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 |
4 | namespace Arthas.Shell.Interop;
5 |
6 | ///
7 | /// WindowStyle values, WS_*
8 | ///
9 | [Flags]
10 | [SuppressMessage("ReSharper", "InconsistentNaming")]
11 | enum WS : uint
12 | {
13 | CHILD = 0x40000000,
14 | CLIPCHILDREN = 0x02000000,
15 | BORDER = 0x00800000,
16 | DLGFRAME = 0x00400000,
17 | CAPTION = BORDER | DLGFRAME
18 | }
19 |
--------------------------------------------------------------------------------
/Arthas.Shell/Interop/WVR.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 |
4 | namespace Arthas.Shell.Interop;
5 |
6 | [Flags]
7 | [SuppressMessage("ReSharper", "InconsistentNaming")]
8 | enum WVR
9 | {
10 | HREDRAW = 0x0100,
11 | VREDRAW = 0x0200,
12 | VALIDRECTS = 0x0400,
13 | REDRAW = HREDRAW | VREDRAW
14 | }
15 |
--------------------------------------------------------------------------------
/Arthas.Shell/Interop/Win32.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | namespace Arthas.Shell.Interop;
7 |
8 | static class Win32
9 | {
10 | [DllImport("dwmapi.dll", EntryPoint = "DwmIsCompositionEnabled", PreserveSig = false)]
11 | [return: MarshalAs(UnmanagedType.Bool)]
12 | static extern bool _DwmIsCompositionEnabled();
13 |
14 | static readonly bool _isOsVistaOrNewer = new Version(6, 0) <= Environment.OSVersion.Version;
15 |
16 | public static bool DwmIsCompositionEnabled()
17 | {
18 | return _isOsVistaOrNewer && _DwmIsCompositionEnabled();
19 | }
20 |
21 | public static WS GetWindowStyle(IntPtr hWnd)
22 | {
23 | return (WS)GetWindowLongPtr(hWnd, GWL.STYLE);
24 | }
25 |
26 | public static WS SetWindowStyle(IntPtr hWnd, WS dwNewLong)
27 | {
28 | return (WS)SetWindowLongPtr(hWnd, GWL.STYLE, (IntPtr)dwNewLong);
29 | }
30 |
31 | [MethodImpl(MethodImplOptions.NoInlining)]
32 | public static IntPtr GetWindowLongPtr(IntPtr hwnd, GWL nIndex)
33 | {
34 | var ret = IntPtr.Size == 8
35 | ? GetWindowLongPtr64(hwnd, nIndex)
36 | : GetWindowLongPtr32(hwnd, nIndex);
37 |
38 | if (ret == IntPtr.Zero)
39 | throw new Win32Exception();
40 |
41 | return ret;
42 | }
43 |
44 | [DllImport("user32.dll", EntryPoint = "GetWindowLong", SetLastError = true)]
45 | static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, GWL nIndex);
46 |
47 | [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", SetLastError = true)]
48 | static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, GWL nIndex);
49 |
50 | [DllImport("user32.dll", SetLastError = true)]
51 | [return: MarshalAs(UnmanagedType.Bool)]
52 | static extern bool GetWindowPlacement(IntPtr hwnd, [In] [Out] WINDOWPLACEMENT lpwndpl);
53 |
54 | [MethodImpl(MethodImplOptions.NoInlining)]
55 | public static WINDOWPLACEMENT GetWindowPlacement(IntPtr hwnd)
56 | {
57 | WINDOWPLACEMENT wndpl = new();
58 |
59 | if (GetWindowPlacement(hwnd, wndpl))
60 | return wndpl;
61 |
62 | throw new Win32Exception();
63 | }
64 |
65 | [MethodImpl(MethodImplOptions.NoInlining)]
66 | public static IntPtr SetWindowLongPtr(IntPtr hwnd, GWL nIndex, IntPtr dwNewLong)
67 | {
68 | if (IntPtr.Size == 8)
69 | return SetWindowLongPtr64(hwnd, nIndex, dwNewLong);
70 |
71 | return new(SetWindowLongPtr32(hwnd, nIndex, dwNewLong.ToInt32()));
72 | }
73 |
74 | [DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
75 | static extern int SetWindowLongPtr32(IntPtr hWnd, GWL nIndex, int dwNewLong);
76 |
77 | [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
78 | static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, GWL nIndex, IntPtr dwNewLong);
79 |
80 | [DllImport("user32.dll", EntryPoint = "SetWindowPos", SetLastError = true)]
81 | [return: MarshalAs(UnmanagedType.Bool)]
82 | static extern bool _SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SWP uFlags);
83 |
84 | [MethodImpl(MethodImplOptions.NoInlining)]
85 | public static void SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SWP uFlags)
86 | {
87 | if (!_SetWindowPos(hWnd, hWndInsertAfter, x, y, cx, cy, uFlags))
88 | throw new Win32Exception();
89 | }
90 |
91 | [DllImport("user32.dll", SetLastError = true)]
92 | public static extern IntPtr SendMessage(IntPtr hWnd, WM msg, IntPtr wParam, IntPtr lParam);
93 | }
94 |
--------------------------------------------------------------------------------
/Arthas.Shell/MetroWindowBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 | using System.Windows.Interop;
4 | using Arthas.Shell.Interop;
5 |
6 | namespace Arthas.Shell;
7 |
8 | public class MetroWindowBase : Window
9 | {
10 | readonly MetroWindowChrome _chrome;
11 |
12 | protected MetroWindowBase()
13 | {
14 | _chrome = new(this);
15 |
16 | WindowStartupLocation = WindowStartupLocation.CenterScreen;
17 |
18 | CommandBindings.Add(new(SystemCommands.MinimizeWindowCommand, delegate
19 | {
20 | SystemCommands.MinimizeWindow(this);
21 | }));
22 |
23 | CommandBindings.Add(new(SystemCommands.MaximizeWindowCommand, delegate
24 | {
25 | ChangWindowState();
26 | }));
27 |
28 | CommandBindings.Add(new(SystemCommands.RestoreWindowCommand, delegate
29 | {
30 | ChangWindowState();
31 | }));
32 |
33 | CommandBindings.Add(new(SystemCommands.CloseWindowCommand, delegate
34 | {
35 | SystemCommands.CloseWindow(this);
36 | }));
37 |
38 | ContentRendered += OnContentRendered;
39 | }
40 |
41 | void OnContentRendered(object? sender, EventArgs e)
42 | {
43 | ContentRendered -= OnContentRendered;
44 | Activate();
45 | }
46 |
47 | protected void ChangWindowState()
48 | {
49 | switch (ResizeMode)
50 | {
51 | case ResizeMode.CanResize:
52 | case ResizeMode.CanResizeWithGrip:
53 |
54 | break;
55 |
56 | default:
57 |
58 | return;
59 | }
60 |
61 | switch (WindowState)
62 | {
63 | case WindowState.Normal:
64 |
65 | SystemCommands.MaximizeWindow(this);
66 |
67 | break;
68 |
69 | case WindowState.Maximized:
70 |
71 | SystemCommands.RestoreWindow(this);
72 |
73 | break;
74 | }
75 | }
76 |
77 | public IntPtr Handle { get; private set; }
78 | public IntPtr OwnerHandle { get; private set; }
79 | public HwndSource? HwndSource { get; private set; }
80 |
81 | protected override void OnSourceInitialized(EventArgs e)
82 | {
83 | var windowInteropHelper = new WindowInteropHelper(this);
84 | windowInteropHelper.EnsureHandle();
85 |
86 | Handle = windowInteropHelper.Handle;
87 | OwnerHandle = windowInteropHelper.Owner;
88 | HwndSource = HwndSource.FromHwnd(Handle);
89 |
90 | _chrome.OnSourceInitialized();
91 |
92 | base.OnSourceInitialized(e);
93 | }
94 |
95 | protected override void OnStateChanged(EventArgs e)
96 | {
97 | base.OnStateChanged(e);
98 | _chrome.OnStateChanged();
99 | }
100 |
101 | public bool IsClosed { get; private set; }
102 |
103 | protected override void OnClosed(EventArgs e)
104 | {
105 | base.OnClosed(e);
106 | IsClosed = true;
107 | Owner.BringToFront();
108 | _chrome.OnClosed();
109 | }
110 |
111 | protected override void OnDeactivated(EventArgs e)
112 | {
113 | base.OnDeactivated(e);
114 | TopMostHack();
115 | }
116 |
117 | protected override void OnLostFocus(RoutedEventArgs e)
118 | {
119 | base.OnLostFocus(e);
120 | TopMostHack();
121 | }
122 |
123 | void TopMostHack()
124 | {
125 | if (!Topmost)
126 | return;
127 |
128 | SetCurrentValue(TopmostProperty, false);
129 | SetCurrentValue(TopmostProperty, true);
130 | }
131 |
132 | protected void SendCaptionMessage()
133 | {
134 | Win32.SendMessage(Handle, WM.NCLBUTTONDOWN, (IntPtr)HT.CAPTION, IntPtr.Zero);
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/Arthas.Shell/MetroWindowChrome.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Runtime.InteropServices;
4 | using System.Security;
5 | using System.Windows;
6 | using System.Windows.Shell;
7 | using Arthas.Shell.Interop;
8 |
9 | namespace Arthas.Shell;
10 |
11 | [SuppressMessage("ReSharper", "InconsistentNaming")]
12 | class MetroWindowChrome
13 | {
14 | readonly MetroWindowBase window;
15 |
16 | [SecuritySafeCritical]
17 | public MetroWindowChrome(MetroWindowBase window)
18 | {
19 | this.window = window;
20 |
21 | window.SetCurrentValue(Window.AllowsTransparencyProperty, false);
22 | window.SetCurrentValue(Window.WindowStyleProperty, WindowStyle.None);
23 | }
24 |
25 | public void OnSourceInitialized()
26 | {
27 | WindowChrome.SetWindowChrome(window, new()
28 | {
29 | CaptionHeight = 0,
30 | CornerRadius = new(0),
31 | GlassFrameThickness = new(1),
32 | NonClientFrameEdges = NonClientFrameEdges.None,
33 | ResizeBorderThickness = new(6),
34 | UseAeroCaptionButtons = false
35 | });
36 |
37 | if (window.SizeToContent != SizeToContent.Manual && window.WindowState == WindowState.Normal)
38 | window.InvalidateMeasure();
39 |
40 | window.HwndSource?.AddHook(WindowProc);
41 |
42 | UpdateFrameState(true);
43 | HandleMaximize();
44 | }
45 |
46 | bool isCleanedUp;
47 |
48 | public void OnClosed()
49 | {
50 | if (isCleanedUp)
51 | return;
52 |
53 | isCleanedUp = true;
54 |
55 | window.HwndSource?.RemoveHook(WindowProc);
56 | }
57 |
58 | public void OnStateChanged()
59 | {
60 | HandleMaximize();
61 | }
62 |
63 | static IntPtr HWND_NOTOPMOST { get; } = new(-2);
64 |
65 | void HandleMaximize()
66 | {
67 | if (window.WindowState != WindowState.Maximized)
68 | return;
69 |
70 | if (window.SizeToContent != SizeToContent.Manual)
71 | window.SetCurrentValue(Window.SizeToContentProperty, SizeToContent.Manual);
72 |
73 | if (window.Handle == IntPtr.Zero)
74 | return;
75 |
76 | var workingArea = ScreenHelper.FormWindow(window).WorkingArea;
77 | Win32.SetWindowPos(window.Handle, HWND_NOTOPMOST, workingArea.Left, workingArea.Top, workingArea.Width,
78 | workingArea.Height, SWP.SHOWWINDOW);
79 | }
80 |
81 | [SecurityCritical]
82 | IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
83 | {
84 | return (WM)msg switch
85 | {
86 | WM.NCPAINT => HandleNCPAINT(out handled),
87 | WM.DPICHANGED => HandleDPICHANGED(lParam, out handled),
88 | WM.NCCALCSIZE => HandleNCCALCSIZE(wParam, lParam, out handled),
89 | _ => IntPtr.Zero
90 | };
91 | }
92 |
93 | [SecurityCritical]
94 | static IntPtr HandleNCPAINT(out bool handled)
95 | {
96 | handled = false;
97 |
98 | return IntPtr.Zero;
99 | }
100 |
101 | static bool MinimizeAnimation => SystemParameters.MinimizeAnimation && Win32.DwmIsCompositionEnabled();
102 |
103 | bool dpiChanged;
104 |
105 | [SecurityCritical]
106 | IntPtr HandleDPICHANGED(IntPtr lParam, out bool handled)
107 | {
108 | dpiChanged = true;
109 |
110 | if (_GetHwndState() == WindowState.Normal)
111 | {
112 | var rect = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT))!;
113 | rect.Bottom += 1;
114 | Marshal.StructureToPtr(rect, lParam, true);
115 | }
116 |
117 | handled = false;
118 |
119 | return IntPtr.Zero;
120 | }
121 |
122 | [SecurityCritical]
123 | IntPtr HandleNCCALCSIZE(IntPtr wParam, IntPtr lParam, out bool handled)
124 | {
125 | // lParam is an [in, out] that can be either a RECT* (wParam == FALSE) or an NCCALCSIZE_PARAMS*.
126 | // Since the first field of NCCALCSIZE_PARAMS is a RECT and is the only field we care about
127 | // we can unconditionally treat it as a RECT.
128 |
129 | if (dpiChanged)
130 | {
131 | dpiChanged = false;
132 | handled = true;
133 |
134 | return IntPtr.Zero;
135 | }
136 |
137 | if (MinimizeAnimation
138 | && _GetHwndState() == WindowState.Maximized)
139 | {
140 | var workingArea = ScreenHelper.FormWindow(window).WorkingArea;
141 |
142 | var rc = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT))!;
143 | rc.Left = workingArea.Left;
144 | rc.Top = workingArea.Top;
145 | rc.Right = workingArea.Right;
146 | rc.Bottom = workingArea.Bottom;
147 |
148 | Marshal.StructureToPtr(rc, lParam, true);
149 | }
150 |
151 | handled = true;
152 |
153 | // Per MSDN for NCCALCSIZE, always return 0 when wParam == FALSE
154 | //
155 | // Returning 0 when wParam == TRUE is not appropriate - it will preserve
156 | // the old client area and align it with the upper-left corner of the new
157 | // client area. So we simply ask for a redraw (WVR_REDRAW)
158 |
159 | var retVal = IntPtr.Zero;
160 |
161 | if (wParam.ToInt32() != 0) // wParam == TRUE
162 | // Using the combination of WVR.VALIDRECTS and WVR.REDRAW gives the smoothest
163 | // resize behavior we can achieve here.
164 | retVal = new((int)(WVR.VALIDRECTS | WVR.REDRAW));
165 |
166 | return retVal;
167 | }
168 |
169 | [SecurityCritical]
170 | void UpdateFrameState(bool force)
171 | {
172 | if (window.Handle == IntPtr.Zero || window.HwndSource?.IsDisposed != false)
173 | return;
174 |
175 | if (!force)
176 | return;
177 |
178 | if (window.HwndSource.IsDisposed) // If the window got closed very early
179 | return;
180 |
181 | if (MinimizeAnimation)
182 | ModifyStyle(0, WS.CAPTION);
183 | else
184 | ModifyStyle(WS.CAPTION, 0);
185 |
186 | Win32.SetWindowPos(window.Handle, IntPtr.Zero, 0, 0, 0, 0,
187 | SWP.FRAMECHANGED | SWP.NOSIZE | SWP.NOMOVE | SWP.NOZORDER | SWP.NOOWNERZORDER | SWP.NOACTIVATE);
188 | }
189 |
190 | ///
191 | /// Get the WindowState as the native HWND knows it to be. This isn't necessarily the same as what Window thinks.
192 | ///
193 | [SecurityCritical]
194 | WindowState _GetHwndState()
195 | {
196 | var wpl = Win32.GetWindowPlacement(window.Handle);
197 |
198 | return wpl.showCmd switch
199 | {
200 | SW.SHOWMINIMIZED => WindowState.Minimized,
201 | SW.SHOWMAXIMIZED => WindowState.Maximized,
202 | _ => WindowState.Normal
203 | };
204 | }
205 |
206 | /// Add and remove a native WindowStyle from the HWND.
207 | /// The styles to be removed. These can be bitwise combined.
208 | /// The styles to be added. These can be bitwise combined.
209 | /// Whether the styles of the HWND were modified as a result of this call.
210 | ///
211 | /// Critical : Calls critical methods
212 | ///
213 | [SecurityCritical]
214 | void ModifyStyle(WS removeStyle, WS addStyle)
215 | {
216 | var dwStyle = Win32.GetWindowStyle(window.Handle);
217 | var dwNewStyle = (dwStyle & ~removeStyle) | addStyle;
218 |
219 | if (dwStyle == dwNewStyle)
220 | return;
221 |
222 | Win32.SetWindowStyle(window.Handle, dwNewStyle);
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/Arthas.Shell/ScreenHelper.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 | namespace Arthas.Shell;
4 |
5 | static class ScreenHelper
6 | {
7 | public static Screen FormWindow(MetroWindowBase window)
8 | {
9 | return Screen.FromHandle(window.Handle);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Arthas.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.28516.95
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arthas.Demo", "Arthas.Demo\Arthas.Demo.csproj", "{20827429-E998-4EA3-BB34-DB49CBD0FCC0}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Arthas", "Arthas\Arthas.csproj", "{F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_", "_", "{FE8A96FA-DB1E-45FA-A623-0C222B8B6ACC}"
11 | ProjectSection(SolutionItems) = preProject
12 | Build.bat = Build.bat
13 | Directory.Build.props = Directory.Build.props
14 | README.md = README.md
15 | .gitignore = .gitignore
16 | EndProjectSection
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Arthas.Shell", "Arthas.Shell\Arthas.Shell.csproj", "{CDE22618-45CA-45DE-ABDD-2FE46F3EAE6B}"
19 | EndProject
20 | Global
21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
22 | Debug|Any CPU = Debug|Any CPU
23 | Debug|x86 = Debug|x86
24 | Release|Any CPU = Release|Any CPU
25 | Release|x86 = Release|x86
26 | EndGlobalSection
27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
28 | {20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Debug|x86.ActiveCfg = Debug|Any CPU
31 | {20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Debug|x86.Build.0 = Debug|Any CPU
32 | {20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Release|x86.ActiveCfg = Release|Any CPU
35 | {20827429-E998-4EA3-BB34-DB49CBD0FCC0}.Release|x86.Build.0 = Release|Any CPU
36 | {F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Debug|x86.ActiveCfg = Debug|Any CPU
39 | {F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Debug|x86.Build.0 = Debug|Any CPU
40 | {F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Release|x86.ActiveCfg = Release|Any CPU
43 | {F5DBBC65-F7D3-4A0D-8A9F-3DAFD3DEB7ED}.Release|x86.Build.0 = Release|Any CPU
44 | {CDE22618-45CA-45DE-ABDD-2FE46F3EAE6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {CDE22618-45CA-45DE-ABDD-2FE46F3EAE6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {CDE22618-45CA-45DE-ABDD-2FE46F3EAE6B}.Debug|x86.ActiveCfg = Debug|Any CPU
47 | {CDE22618-45CA-45DE-ABDD-2FE46F3EAE6B}.Debug|x86.Build.0 = Debug|Any CPU
48 | {CDE22618-45CA-45DE-ABDD-2FE46F3EAE6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 | {CDE22618-45CA-45DE-ABDD-2FE46F3EAE6B}.Release|Any CPU.Build.0 = Release|Any CPU
50 | {CDE22618-45CA-45DE-ABDD-2FE46F3EAE6B}.Release|x86.ActiveCfg = Release|Any CPU
51 | {CDE22618-45CA-45DE-ABDD-2FE46F3EAE6B}.Release|x86.Build.0 = Release|Any CPU
52 | EndGlobalSection
53 | GlobalSection(SolutionProperties) = preSolution
54 | HideSolutionNode = FALSE
55 | EndGlobalSection
56 | GlobalSection(ExtensibilityGlobals) = postSolution
57 | SolutionGuid = {7C504695-968E-4B6B-9812-AD4D7B1EB6EC}
58 | EndGlobalSection
59 | EndGlobal
60 |
--------------------------------------------------------------------------------
/Arthas/Arthas.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Arthas/Binder/MetroDialogModel.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using Arthas.Controls;
3 | using OpenView;
4 |
5 | namespace Arthas.Binder;
6 |
7 | public abstract class MetroDialogModel : DialogModel where TUserControl : View, new()
8 | {
9 | protected override Window CreateWindowOverride()
10 | {
11 | return new MetroWindow();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Arthas/Binder/MetroWindowModel.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using Arthas.Controls;
3 | using OpenView;
4 |
5 | namespace Arthas.Binder;
6 |
7 | public abstract class MetroWindowModel : WindowModel where TUserControl : View, new()
8 | {
9 | protected override Window CreateWindowOverride()
10 | {
11 | return new MetroWindow();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroBorder.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroBorder : Border
7 | {
8 | static MetroBorder()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroBorder), new FrameworkPropertyMetadata(typeof(MetroBorder)));
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroBorder.xaml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroButton.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroButton : Button
7 | {
8 | static MetroButton()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroButton), new FrameworkPropertyMetadata(typeof(MetroButton)));
11 | }
12 |
13 | public static readonly DependencyProperty ButtonStateProperty = DependencyProperty.Register(nameof(ButtonState), typeof(MetroButtonState), typeof(MetroButton), new(MetroButtonState.None));
14 |
15 | public MetroButtonState ButtonState
16 | {
17 | get => (MetroButtonState)GetValue(ButtonStateProperty);
18 | set => SetValue(ButtonStateProperty, value);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroButton.xaml:
--------------------------------------------------------------------------------
1 |
6 |
70 |
71 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroButtonState.cs:
--------------------------------------------------------------------------------
1 | namespace Arthas.Controls;
2 |
3 | public enum MetroButtonState
4 | {
5 | None,
6 | Red,
7 | Green
8 | }
9 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroCaptionMenu.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroCaptionMenu : Menu
7 | {
8 | static MetroCaptionMenu()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroCaptionMenu), new FrameworkPropertyMetadata(typeof(MetroCaptionMenu)));
11 | }
12 |
13 | protected override DependencyObject GetContainerForItemOverride()
14 | {
15 | return new MetroCaptionMenuItem();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroCaptionMenu.xaml:
--------------------------------------------------------------------------------
1 |
5 |
14 |
15 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroCaptionMenuItem.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroCaptionMenuItem : MenuItem
7 | {
8 | static MetroCaptionMenuItem()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroCaptionMenuItem), new FrameworkPropertyMetadata(typeof(MetroCaptionMenuItem)));
11 | }
12 |
13 | protected override DependencyObject GetContainerForItemOverride()
14 | {
15 | return new MetroMenuItem();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroCaptionMenuItem.xaml:
--------------------------------------------------------------------------------
1 |
5 |
68 |
69 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroContextMenu.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroContextMenu : ContextMenu
7 | {
8 | static MetroContextMenu()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroContextMenu), new FrameworkPropertyMetadata(typeof(MetroContextMenu)));
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroContextMenu.xaml:
--------------------------------------------------------------------------------
1 |
6 |
25 |
26 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroExpander.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Media;
4 |
5 | namespace Arthas.Controls;
6 |
7 | public class MetroExpander : ContentControl
8 | {
9 | public static readonly DependencyProperty IsExpandedProperty = ElementBase.Property(nameof(IsExpandedProperty));
10 | public static readonly DependencyProperty CanHideProperty = ElementBase.Property(nameof(CanHideProperty));
11 | public static readonly DependencyProperty HeaderProperty = ElementBase.Property(nameof(HeaderProperty));
12 | public static readonly DependencyProperty HintProperty = ElementBase.Property(nameof(HintProperty));
13 | public static readonly DependencyProperty HintBackgroundProperty = ElementBase.Property(nameof(HintBackgroundProperty));
14 | public static readonly DependencyProperty HintForegroundProperty = ElementBase.Property(nameof(HintForegroundProperty));
15 | public static readonly DependencyProperty IconProperty = ElementBase.Property(nameof(IconProperty), null);
16 |
17 | public bool IsExpanded
18 | {
19 | get => (bool)GetValue(IsExpandedProperty);
20 | set
21 | {
22 | SetValue(IsExpandedProperty, value);
23 | VisualStateManager.GoToState(this, IsExpanded ? "Expand" : "Normal", false);
24 | }
25 | }
26 |
27 | public bool CanHide
28 | {
29 | get => (bool)GetValue(CanHideProperty);
30 | set => SetValue(CanHideProperty, value);
31 | }
32 |
33 | public string Header
34 | {
35 | get => (string)GetValue(HeaderProperty);
36 | set => SetValue(HeaderProperty, value);
37 | }
38 |
39 | public string Hint
40 | {
41 | get => (string)GetValue(HintProperty);
42 | set => SetValue(HintProperty, value);
43 | }
44 |
45 | public Brush HintBackground
46 | {
47 | get => (Brush)GetValue(HintBackgroundProperty);
48 | set => SetValue(HintBackgroundProperty, value);
49 | }
50 |
51 | public Brush HintForeground
52 | {
53 | get => (Brush)GetValue(HintForegroundProperty);
54 | set => SetValue(HintForegroundProperty, value);
55 | }
56 |
57 | public ImageSource Icon
58 | {
59 | get => (ImageSource)GetValue(IconProperty);
60 | set => SetValue(IconProperty, value);
61 | }
62 |
63 | public MetroExpander()
64 | {
65 | Loaded += delegate
66 | {
67 | if (Content == null)
68 | IsExpanded = false;
69 | else if (!CanHide)
70 | IsExpanded = true;
71 |
72 | VisualStateManager.GoToState(this, IsExpanded ? "StartExpand" : "StartNormal", false);
73 | };
74 | }
75 |
76 | static MetroExpander()
77 | {
78 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroExpander), new FrameworkPropertyMetadata(typeof(MetroExpander)));
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroExpander.xaml:
--------------------------------------------------------------------------------
1 |
5 |
139 |
140 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroFocusButton.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Media;
4 |
5 | namespace Arthas.Controls;
6 |
7 | public class MetroFocusButton : Button
8 | {
9 | public static readonly DependencyProperty MouseMoveForegroundProperty = ElementBase.Property(nameof(MouseMoveForegroundProperty));
10 | public static readonly DependencyProperty MouseMoveBorderBrushProperty = ElementBase.Property(nameof(MouseMoveBorderBrushProperty));
11 | public new static readonly DependencyProperty BorderThicknessProperty = ElementBase.Property(nameof(BorderThicknessProperty));
12 | public static readonly DependencyProperty MouseMoveBorderThicknessProperty = ElementBase.Property(nameof(MouseMoveBorderThicknessProperty));
13 | public static readonly DependencyProperty StrokeDashArrayProperty = ElementBase.Property(nameof(StrokeDashArrayProperty));
14 | public static readonly DependencyProperty MouseMoveStrokeDashArrayProperty = ElementBase.Property(nameof(MouseMoveStrokeDashArrayProperty));
15 | public static readonly DependencyProperty CornerRadiusProperty = ElementBase.Property(nameof(CornerRadiusProperty));
16 |
17 | public Brush MouseMoveForeground
18 | {
19 | get => (Brush)GetValue(MouseMoveForegroundProperty);
20 | set => SetValue(MouseMoveForegroundProperty, value);
21 | }
22 |
23 | public Brush MouseMoveBorderBrush
24 | {
25 | get => (Brush)GetValue(MouseMoveBorderBrushProperty);
26 | set => SetValue(MouseMoveBorderBrushProperty, value);
27 | }
28 |
29 | public new double BorderThickness
30 | {
31 | get => (double)GetValue(BorderThicknessProperty);
32 | set => SetValue(BorderThicknessProperty, value);
33 | }
34 |
35 | public double MouseMoveBorderThickness
36 | {
37 | get => (double)GetValue(MouseMoveBorderThicknessProperty);
38 | set => SetValue(MouseMoveBorderThicknessProperty, value);
39 | }
40 |
41 | public DoubleCollection StrokeDashArray
42 | {
43 | get => (DoubleCollection)GetValue(StrokeDashArrayProperty);
44 | set => SetValue(StrokeDashArrayProperty, value);
45 | }
46 |
47 | public DoubleCollection MouseMoveStrokeDashArray
48 | {
49 | get => (DoubleCollection)GetValue(MouseMoveStrokeDashArrayProperty);
50 | set => SetValue(MouseMoveStrokeDashArrayProperty, value);
51 | }
52 |
53 | public double CornerRadius
54 | {
55 | get => (double)GetValue(CornerRadiusProperty);
56 | set => SetValue(CornerRadiusProperty, value);
57 | }
58 |
59 | static MetroFocusButton()
60 | {
61 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroFocusButton), new FrameworkPropertyMetadata(typeof(MetroFocusButton)));
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroFocusButton.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
63 |
64 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroGridTile.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroGridTile : ContentControl
7 | {
8 | static MetroGridTile()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroGridTile),
11 | new FrameworkPropertyMetadata(typeof(MetroGridTile)));
12 | }
13 |
14 | public static readonly DependencyProperty TileSizeProperty =
15 | DependencyProperty.Register(nameof(TileSize), typeof(Size), typeof(MetroGridTile));
16 |
17 | public Size TileSize
18 | {
19 | get => (Size)GetValue(TileSizeProperty);
20 | set => SetValue(TileSizeProperty, value);
21 | }
22 |
23 | public static readonly DependencyProperty TileOpacityProperty =
24 | DependencyProperty.Register(nameof(TileOpacity), typeof(double), typeof(MetroGridTile));
25 |
26 | public double TileOpacity
27 | {
28 | get => (double)GetValue(TileOpacityProperty);
29 | set => SetValue(TileOpacityProperty, value);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroGridTile.xaml:
--------------------------------------------------------------------------------
1 |
5 |
36 |
37 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroGroup.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroGroup : GroupBox
7 | {
8 | static MetroGroup()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroGroup), new FrameworkPropertyMetadata(typeof(MetroGroup)));
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroGroup.xaml:
--------------------------------------------------------------------------------
1 |
6 |
29 |
30 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroMenuItem.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroMenuItem : MenuItem
7 | {
8 | static MetroMenuItem()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroMenuItem), new FrameworkPropertyMetadata(typeof(MetroMenuItem)));
11 | }
12 |
13 | protected override DependencyObject GetContainerForItemOverride()
14 | {
15 | return new MetroMenuItem();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroMenuItem.xaml:
--------------------------------------------------------------------------------
1 |
6 |
78 |
79 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroMenuSeparator.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroMenuSeparator : Separator
7 | {
8 | static MetroMenuSeparator()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroMenuSeparator), new FrameworkPropertyMetadata(typeof(MetroMenuSeparator)));
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroMenuSeparator.xaml:
--------------------------------------------------------------------------------
1 |
5 |
11 |
12 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroProgressBar.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroProgressBar : ProgressBar
7 | {
8 | static MetroProgressBar()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroProgressBar), new FrameworkPropertyMetadata(typeof(MetroProgressBar)));
11 | }
12 |
13 | public static readonly DependencyProperty ProgressBarStateProperty = ElementBase.Property(nameof(ProgressBarStateProperty));
14 | public static readonly DependencyProperty CornerRadiusProperty = ElementBase.Property(nameof(CornerRadiusProperty));
15 | public static readonly DependencyProperty TitleProperty = ElementBase.Property(nameof(TitleProperty));
16 | public static readonly DependencyProperty TextHorizontalAlignmentProperty = ElementBase.Property(nameof(TextHorizontalAlignmentProperty));
17 |
18 | public ProgressBarState ProgressBarState
19 | {
20 | get => (ProgressBarState)GetValue(ProgressBarStateProperty);
21 | set => SetValue(ProgressBarStateProperty, value);
22 | }
23 |
24 | public CornerRadius CornerRadius
25 | {
26 | get => (CornerRadius)GetValue(CornerRadiusProperty);
27 | set => SetValue(CornerRadiusProperty, value);
28 | }
29 |
30 | public string Title
31 | {
32 | get => (string)GetValue(TitleProperty);
33 | set => SetValue(TitleProperty, value);
34 | }
35 |
36 | public HorizontalAlignment TextHorizontalAlignment
37 | {
38 | get => (HorizontalAlignment)GetValue(TextHorizontalAlignmentProperty);
39 | set => SetValue(TextHorizontalAlignmentProperty, value);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroProgressBar.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
103 |
104 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroScrollViewer.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroScrollViewer : ScrollViewer
7 | {
8 | static MetroScrollViewer()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroScrollViewer), new FrameworkPropertyMetadata(typeof(MetroScrollViewer)));
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroScrollViewer.xaml:
--------------------------------------------------------------------------------
1 |
6 |
15 |
54 |
93 |
115 |
137 |
169 |
170 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroSwitch.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls.Primitives;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroSwitch : ToggleButton
7 | {
8 | public static readonly DependencyProperty TextHorizontalAlignmentProperty = DependencyProperty.Register(nameof(TextHorizontalAlignment), typeof(HorizontalAlignment), typeof(MetroSwitch), new(HorizontalAlignment.Left));
9 |
10 | public HorizontalAlignment TextHorizontalAlignment
11 | {
12 | get => (HorizontalAlignment)GetValue(TextHorizontalAlignmentProperty);
13 | set => SetValue(TextHorizontalAlignmentProperty, value);
14 | }
15 |
16 | public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register(nameof(CornerRadius), typeof(CornerRadius), typeof(MetroSwitch), new(new CornerRadius(10)));
17 |
18 | public CornerRadius CornerRadius
19 | {
20 | get => (CornerRadius)GetValue(CornerRadiusProperty);
21 | set => SetValue(CornerRadiusProperty, value);
22 | }
23 |
24 | public static readonly DependencyProperty BorderCornerRadiusProperty = DependencyProperty.Register(nameof(BorderCornerRadius), typeof(CornerRadius), typeof(MetroSwitch), new(new CornerRadius(12)));
25 |
26 | public CornerRadius BorderCornerRadius
27 | {
28 | get => (CornerRadius)GetValue(BorderCornerRadiusProperty);
29 | set => SetValue(BorderCornerRadiusProperty, value);
30 | }
31 |
32 | public MetroSwitch()
33 | {
34 | Loaded += delegate
35 | {
36 | VisualStateManager.GoToState(this, IsChecked is true ? "OpenLoaded" : "CloseLoaded", false);
37 | };
38 | }
39 |
40 | protected override void OnChecked(RoutedEventArgs e)
41 | {
42 | base.OnChecked(e);
43 | VisualStateManager.GoToState(this, "Open", false);
44 | }
45 |
46 | protected override void OnUnchecked(RoutedEventArgs e)
47 | {
48 | base.OnChecked(e);
49 | VisualStateManager.GoToState(this, "Close", false);
50 | }
51 |
52 | static MetroSwitch()
53 | {
54 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroSwitch), new FrameworkPropertyMetadata(typeof(MetroSwitch)));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroSwitch.xaml:
--------------------------------------------------------------------------------
1 |
5 |
68 |
69 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTabControl.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroTabControl : TabControl
7 | {
8 | void SelectionState()
9 | {
10 | VisualStateManager.GoToState(this, "SelectionStart", false);
11 | VisualStateManager.GoToState(this, "SelectionEnd", false);
12 | }
13 |
14 | protected override DependencyObject GetContainerForItemOverride()
15 | {
16 | return new MetroTabItem();
17 | }
18 |
19 | public MetroTabControl()
20 | {
21 | Loaded += delegate
22 | {
23 | VisualStateManager.GoToState(this, "SelectionLoaded", false);
24 | };
25 | SelectionChanged += delegate(object _, SelectionChangedEventArgs e)
26 | {
27 | if (e.Source is MetroTabControl)
28 | SelectionState();
29 | };
30 | }
31 |
32 | static MetroTabControl()
33 | {
34 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroTabControl), new FrameworkPropertyMetadata(typeof(MetroTabControl)));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTabControl.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
62 |
63 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTabItem.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Media;
4 |
5 | namespace Arthas.Controls;
6 |
7 | public class MetroTabItem : TabItem
8 | {
9 | public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon), typeof(ImageSource), typeof(MetroTabItem), new(null));
10 |
11 | public ImageSource? Icon
12 | {
13 | get => (ImageSource?)GetValue(IconProperty);
14 | set => SetValue(IconProperty, value);
15 | }
16 |
17 | static MetroTabItem()
18 | {
19 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroTabItem), new FrameworkPropertyMetadata(typeof(MetroTabItem)));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTabItem.xaml:
--------------------------------------------------------------------------------
1 |
5 |
54 |
55 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTextBlock.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Controls;
2 |
3 | namespace Arthas.Controls;
4 |
5 | public class MetroTextBlock : TextBlock
6 | {
7 | }
8 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTextBlock.xaml:
--------------------------------------------------------------------------------
1 |
5 |
32 |
35 |
36 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTextBox.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Input;
4 | using System.Windows.Media;
5 |
6 | namespace Arthas.Controls;
7 |
8 | public class MetroTextBox : TextBox
9 | {
10 | public static readonly DependencyProperty TitleProperty = ElementBase.Property(nameof(TitleProperty), "");
11 | public static readonly DependencyProperty TitleMinWidthProperty = ElementBase.Property(nameof(TitleMinWidthProperty));
12 | public static readonly DependencyProperty TitleForegroundProperty = ElementBase.Property(nameof(TitleForegroundProperty));
13 | public static readonly DependencyProperty MouseMoveBackgroundProperty = ElementBase.Property(nameof(MouseMoveBackgroundProperty));
14 | public static readonly DependencyProperty InputHintProperty = ElementBase.Property(nameof(InputHintProperty), "");
15 | public static readonly DependencyProperty ButtonTitleProperty = ElementBase.Property(nameof(ButtonTitleProperty), "");
16 | public static readonly DependencyProperty IconProperty = ElementBase.Property(nameof(IconProperty), null);
17 | public static readonly DependencyProperty StateProperty = ElementBase.Property(nameof(StateProperty), "");
18 | public static readonly DependencyProperty MultipleLineProperty = ElementBase.Property(nameof(MultipleLineProperty), false);
19 | public static readonly DependencyProperty CornerRadiusProperty = ElementBase.Property(nameof(CornerRadiusProperty));
20 |
21 | public static RoutedUICommand ButtonClickCommand = ElementBase.Command(nameof(ButtonClickCommand));
22 |
23 | public string Title
24 | {
25 | get => (string)GetValue(TitleProperty);
26 | set => SetValue(TitleProperty, value);
27 | }
28 |
29 | public double TitleMinWidth
30 | {
31 | get => (double)GetValue(TitleMinWidthProperty);
32 | set => SetValue(TitleMinWidthProperty, value);
33 | }
34 |
35 | public Brush TitleForeground
36 | {
37 | get => (Brush)GetValue(TitleForegroundProperty);
38 | set => SetValue(TitleForegroundProperty, value);
39 | }
40 |
41 | public Brush MouseMoveBackground
42 | {
43 | get => (Brush)GetValue(MouseMoveBackgroundProperty);
44 | set => SetValue(MouseMoveBackgroundProperty, value);
45 | }
46 |
47 | public string InputHint
48 | {
49 | get => (string)GetValue(InputHintProperty);
50 | set => SetValue(InputHintProperty, value);
51 | }
52 |
53 | public string ButtonTitle
54 | {
55 | get => (string)GetValue(ButtonTitleProperty);
56 | set => SetValue(ButtonTitleProperty, value);
57 | }
58 |
59 | public ImageSource Icon
60 | {
61 | get => (ImageSource)GetValue(IconProperty);
62 | set => SetValue(IconProperty, value);
63 | }
64 |
65 | public string State
66 | {
67 | get => (string)GetValue(StateProperty);
68 | set => SetValue(StateProperty, value);
69 | }
70 |
71 | public bool MultipleLine
72 | {
73 | get => (bool)GetValue(MultipleLineProperty);
74 | set => SetValue(MultipleLineProperty, value);
75 | }
76 |
77 | public CornerRadius CornerRadius
78 | {
79 | get => (CornerRadius)GetValue(CornerRadiusProperty);
80 | set => SetValue(CornerRadiusProperty, value);
81 | }
82 |
83 | public Func? ErrorCheckAction { get; set; }
84 |
85 | public event EventHandler? ButtonClick;
86 |
87 | public MetroTextBox()
88 | {
89 | ContextMenu = null;
90 | Loaded += delegate
91 | {
92 | ErrorCheck();
93 | };
94 | TextChanged += delegate
95 | {
96 | ErrorCheck();
97 | };
98 | CommandBindings.Add(new(ButtonClickCommand, delegate
99 | {
100 | ButtonClick?.Invoke(this, EventArgs.Empty);
101 | }));
102 | }
103 |
104 | void ErrorCheck()
105 | {
106 | // if (PopupHint == null || PopupHint == "") { PopupHint = InputHint; }
107 | if (ErrorCheckAction != null)
108 | State = ErrorCheckAction(Text) ? "true" : "false";
109 | }
110 |
111 | static MetroTextBox()
112 | {
113 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroTextBox), new FrameworkPropertyMetadata(typeof(MetroTextBox)));
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTextBox.xaml:
--------------------------------------------------------------------------------
1 |
6 |
33 |
139 |
140 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTextButton.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace Arthas.Controls;
5 |
6 | public class MetroTextButton : Button
7 | {
8 | static MetroTextButton()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroTextButton), new FrameworkPropertyMetadata(typeof(MetroTextButton)));
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTextButton.xaml:
--------------------------------------------------------------------------------
1 |
5 |
42 |
43 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTile.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Media;
4 |
5 | #pragma warning disable 1591
6 |
7 | namespace Arthas.Controls;
8 |
9 | public class MetroTile : ContentControl
10 | {
11 | static MetroTile()
12 | {
13 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroTile), new FrameworkPropertyMetadata(typeof(MetroTile)));
14 | }
15 |
16 | public static readonly DependencyProperty TileBackgroundProperty =
17 | DependencyProperty.Register(nameof(TileBackground), typeof(VisualBrush), typeof(MetroTile));
18 |
19 | public VisualBrush TileBackground
20 | {
21 | get => (VisualBrush)GetValue(TileBackgroundProperty);
22 | private set => SetValue(TileBackgroundProperty, value);
23 | }
24 |
25 | public static readonly DependencyProperty TileProperty =
26 | DependencyProperty.Register(nameof(Tile), typeof(FrameworkElement), typeof(MetroTile),
27 | new FrameworkPropertyMetadata(null, OnTileChanged));
28 |
29 | public FrameworkElement? Tile
30 | {
31 | get => (FrameworkElement)GetValue(TileProperty);
32 | set => SetValue(TileProperty, value);
33 | }
34 |
35 | public static readonly DependencyProperty TileSizeProperty =
36 | DependencyProperty.Register(nameof(TileSize), typeof(Size), typeof(MetroTile),
37 | new FrameworkPropertyMetadata(new Size(100, 100), OnTileChanged));
38 |
39 | public Size TileSize
40 | {
41 | get => (Size)GetValue(TileSizeProperty);
42 | set => SetValue(TileSizeProperty, value);
43 | }
44 |
45 | static void OnTileChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
46 | {
47 | ((MetroTile)d).OnTileChanged();
48 | }
49 |
50 | void OnTileChanged()
51 | {
52 | if (Tile is null)
53 | return;
54 |
55 | Tile.Width = TileSize.Width;
56 | Tile.Height = TileSize.Height;
57 |
58 | TileBackground = new()
59 | {
60 | TileMode = TileMode.Tile,
61 | ViewportUnits = BrushMappingMode.Absolute,
62 | Visual = Tile,
63 | Viewport = new(TileSize)
64 | };
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroTile.xaml:
--------------------------------------------------------------------------------
1 |
5 |
16 |
17 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroWaterfallFlow.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Controls.Primitives;
4 |
5 | namespace Arthas.Controls;
6 |
7 | public class MetroWaterfallFlow : Panel
8 | {
9 | public static readonly DependencyProperty SizeProperty =
10 | DependencyProperty.Register(nameof(Size), typeof(double), typeof(MetroWaterfallFlow),
11 | new FrameworkPropertyMetadata(double.NaN,
12 | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault |
13 | FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange));
14 |
15 | public double Size
16 | {
17 | get => (double)GetValue(SizeProperty);
18 | set => SetValue(SizeProperty, value);
19 | }
20 |
21 | protected override Size MeasureOverride(Size availableSize)
22 | {
23 | return Layout(this, availableSize, true);
24 | }
25 |
26 | protected override Size ArrangeOverride(Size finalSize)
27 | {
28 | return Layout(this, finalSize, false);
29 | }
30 |
31 | IEnumerable GetChildren()
32 | {
33 | foreach (UIElement child in InternalChildren)
34 | {
35 | if (child is Popup)
36 | continue;
37 |
38 | if (child.Visibility == Visibility.Collapsed)
39 | continue;
40 |
41 | yield return child;
42 | }
43 | }
44 |
45 | double GetValue(double num, double defVal = 0.0)
46 | {
47 | return double.IsNaN(num) || double.IsNegativeInfinity(num) || double.IsPositiveInfinity(num) ? defVal : num;
48 | }
49 |
50 | void ForEach(int column, Action action)
51 | {
52 | var elements = GetChildren().ToList();
53 | var count = elements.Count;
54 |
55 | var items = new List();
56 | var row = 0;
57 |
58 | for (var i = 0; i < count; i++)
59 | {
60 | var child = elements[i];
61 |
62 | items.Add(child);
63 |
64 | if (items.Count != column)
65 | continue;
66 |
67 | action(count, row++, items.ToArray());
68 | items.Clear();
69 | }
70 |
71 | if (items.Count == 0)
72 | return;
73 |
74 | action(count, ++row, items.ToArray());
75 | items.Clear();
76 | }
77 |
78 | double GetSize()
79 | {
80 | return GetValue(Size, 100d);
81 | }
82 |
83 | int GetColumn(double width)
84 | {
85 | var size = GetSize();
86 | var value = GetValue(width);
87 | var column = value / size;
88 |
89 | return (int)Math.Max(column, 1);
90 | }
91 |
92 | static Size Layout(MetroWaterfallFlow layout, Size size, bool isMeasure)
93 | {
94 | var result = default(Size);
95 |
96 | var column = layout.GetColumn(size.Width);
97 | var itemSize = layout.GetValue(size.Width / column);
98 |
99 | var bottoms = new Dictionary();
100 |
101 | for (var i = 0; i < column; i++)
102 | bottoms[i] = 0.0;
103 |
104 | layout.ForEach(column, (_, index, items) =>
105 | {
106 | for (var i = 0; i < items.Length; i++)
107 | {
108 | var child = items[i];
109 |
110 | if (isMeasure)
111 | child.Measure(new(itemSize, double.PositiveInfinity));
112 |
113 | var newIndex = i;
114 |
115 | if (index >= column)
116 | {
117 | var current = bottoms[0];
118 | newIndex = 0;
119 |
120 | for (var n = 1; n < bottoms.Count; n++)
121 | if (bottoms[n] < current)
122 | {
123 | current = bottoms[n];
124 | newIndex = n;
125 | }
126 | }
127 |
128 | if (!isMeasure)
129 | child.Arrange(new(newIndex * itemSize, bottoms[newIndex], itemSize,
130 | child.DesiredSize.Height));
131 |
132 | bottoms[newIndex] += child.DesiredSize.Height;
133 | }
134 | });
135 |
136 | result.Width = layout.GetValue(size.Width);
137 |
138 | foreach (var bottom in bottoms)
139 | result.Height = Math.Max(result.Height, bottom.Value);
140 |
141 | return result;
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroWindow.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Input;
4 | using System.Windows.Media;
5 | using Arthas.Shell;
6 |
7 | namespace Arthas.Controls;
8 |
9 | public class MetroWindow : MetroWindowBase
10 | {
11 | static MetroWindow()
12 | {
13 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroWindow), new FrameworkPropertyMetadata(typeof(MetroWindow)));
14 | }
15 |
16 | public static readonly DependencyProperty CaptionBackgroundProperty = DependencyProperty.Register(nameof(CaptionBackground), typeof(Brush), typeof(MetroWindow));
17 |
18 | public Brush? CaptionBackground
19 | {
20 | get => (Brush?)GetValue(CaptionBackgroundProperty);
21 | set => SetValue(CaptionBackgroundProperty, value);
22 | }
23 |
24 | public static readonly DependencyProperty CaptionForegroundProperty = DependencyProperty.Register(nameof(CaptionForeground), typeof(Brush), typeof(MetroWindow));
25 |
26 | public Brush? CaptionForeground
27 | {
28 | get => (Brush?)GetValue(CaptionForegroundProperty);
29 | set => SetValue(CaptionForegroundProperty, value);
30 | }
31 |
32 | public static readonly DependencyProperty CaptionContentProperty = DependencyProperty.Register(nameof(CaptionContent), typeof(object), typeof(MetroWindow));
33 |
34 | public object? CaptionContent
35 | {
36 | get => GetValue(CaptionContentProperty);
37 | set => SetValue(CaptionContentProperty, value);
38 | }
39 |
40 | Grid? PART_Caption;
41 |
42 | public override void OnApplyTemplate()
43 | {
44 | base.OnApplyTemplate();
45 |
46 | PART_Caption = GetTemplateChild(nameof(PART_Caption)) as Grid;
47 |
48 | if (PART_Caption is null)
49 | return;
50 |
51 | PART_Caption.MouseLeftButtonDown += ElementOnMouseLeftButtonDown;
52 | }
53 |
54 | void ElementOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
55 | {
56 | if (Handle == IntPtr.Zero)
57 | return;
58 |
59 | if (e.ClickCount == 2)
60 | ChangWindowState();
61 |
62 | else
63 | SendCaptionMessage();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Arthas/Controls/MetroWindow.xaml:
--------------------------------------------------------------------------------
1 |
6 |
39 |
126 |
127 |
--------------------------------------------------------------------------------
/Arthas/Controls/ProgressBarState.cs:
--------------------------------------------------------------------------------
1 | namespace Arthas.Controls;
2 |
3 | public enum ProgressBarState
4 | {
5 | None,
6 | Error,
7 | Wait
8 | }
9 |
--------------------------------------------------------------------------------
/Arthas/Converter/CornerRadiusToDouble.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 | using System.Windows;
3 | using System.Windows.Data;
4 |
5 | namespace Arthas.Converter;
6 |
7 | public class CornerRadiusToDouble : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object? parameter, CultureInfo culture)
10 | {
11 | if (parameter != null)
12 | return ((CornerRadius)value).TopLeft * System.Convert.ToDouble(parameter);
13 | return ((CornerRadius)value).TopLeft;
14 | }
15 |
16 | public object ConvertBack(object value, Type targetType, object? parameter, CultureInfo culture)
17 | {
18 | if (parameter != null)
19 | return new CornerRadius((double)value / System.Convert.ToDouble(parameter));
20 | return new CornerRadius((double)value);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Arthas/Converter/DoubleToCornerRadius.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 | using System.Windows;
3 | using System.Windows.Data;
4 |
5 | namespace Arthas.Converter;
6 |
7 | public class DoubleToCornerRadius : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object? parameter, CultureInfo culture)
10 | {
11 | if (parameter != null)
12 | return new CornerRadius((double)value / System.Convert.ToDouble(parameter));
13 | return new CornerRadius((double)value);
14 | }
15 |
16 | public object ConvertBack(object value, Type targetType, object? parameter, CultureInfo culture)
17 | {
18 | if (parameter != null)
19 | return ((CornerRadius)value).TopLeft * System.Convert.ToDouble(parameter);
20 | return ((CornerRadius)value).TopLeft;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Arthas/Converter/DoubleToThickness.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 | using System.Windows;
3 | using System.Windows.Data;
4 |
5 | namespace Arthas.Converter;
6 |
7 | public class DoubleToThickness : IValueConverter
8 | {
9 | public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
10 | {
11 | if (value != null)
12 | {
13 | if (parameter != null)
14 | switch (parameter.ToString())
15 | {
16 | case "Left":
17 | return new Thickness(System.Convert.ToDouble(value), 0, 0, 0);
18 |
19 | case "Top":
20 | return new Thickness(0, System.Convert.ToDouble(value), 0, 0);
21 |
22 | case "Right":
23 | return new Thickness(0, 0, System.Convert.ToDouble(value), 0);
24 |
25 | case "Buttom":
26 | return new Thickness(0, 0, 0, System.Convert.ToDouble(value));
27 |
28 | case "LeftTop":
29 | return new Thickness(System.Convert.ToDouble(value), System.Convert.ToDouble(value), 0, 0);
30 |
31 | case "LeftButtom":
32 | return new Thickness(System.Convert.ToDouble(value), 0, 0, System.Convert.ToDouble(value));
33 |
34 | case "RightTop":
35 | return new Thickness(0, System.Convert.ToDouble(value), System.Convert.ToDouble(value), 0);
36 |
37 | case "RigthButtom":
38 | return new Thickness(0, 0, System.Convert.ToDouble(value), System.Convert.ToDouble(value));
39 |
40 | case "LeftRight":
41 | return new Thickness(System.Convert.ToDouble(value), 0, System.Convert.ToDouble(value), 0);
42 |
43 | case "TopButtom":
44 | return new Thickness(0, System.Convert.ToDouble(value), 0, System.Convert.ToDouble(value));
45 |
46 | default:
47 | return new Thickness(System.Convert.ToDouble(value));
48 | }
49 |
50 | return new Thickness(System.Convert.ToDouble(value));
51 | }
52 |
53 | return new Thickness(0);
54 | }
55 |
56 | public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
57 | {
58 | if (value != null)
59 | {
60 | if (parameter != null)
61 | switch (parameter.ToString())
62 | {
63 | case "Left":
64 | return ((Thickness)value).Left;
65 |
66 | case "Top":
67 | return ((Thickness)value).Top;
68 |
69 | case "Right":
70 | return ((Thickness)value).Right;
71 |
72 | case "Buttom":
73 | return ((Thickness)value).Bottom;
74 |
75 | default:
76 | return ((Thickness)value).Left;
77 | }
78 |
79 | return ((Thickness)value).Left;
80 | }
81 |
82 | return 0.0;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Arthas/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Markup;
3 |
4 | [assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
5 | [assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Arthas.Controls")]
6 |
--------------------------------------------------------------------------------
/Arthas/Resource.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Reflection;
3 | using System.Windows;
4 | using System.Windows.Media.Imaging;
5 |
6 | namespace Arthas;
7 |
8 | public static class Resource
9 | {
10 | public static BitmapImage? AsBitmapImage(Uri uri)
11 | {
12 | using var stream = AsStream(uri);
13 |
14 | return Stream2BitmapImage(stream);
15 | }
16 |
17 | public static BitmapImage? AsBitmapImage(string path, Assembly? assembly = null)
18 | {
19 | var callingAssembly = assembly ?? Assembly.GetCallingAssembly();
20 |
21 | return AsBitmapImage(AsUri(path, callingAssembly));
22 | }
23 |
24 | public static Stream? AsStream(Uri uri)
25 | {
26 | return Application.GetResourceStream(uri)?.Stream;
27 | }
28 |
29 | public static Stream? AsStream(string path, Assembly? assembly = null)
30 | {
31 | var callingAssembly = assembly ?? Assembly.GetCallingAssembly();
32 |
33 | return AsStream(AsUri(path, callingAssembly));
34 | }
35 |
36 | public static Uri AsUri(string path, Assembly? assembly = null)
37 | {
38 | var callingAssembly = assembly ?? Assembly.GetCallingAssembly();
39 |
40 | return new($"pack://application:,,,/{callingAssembly.GetName().Name};component/{path}");
41 | }
42 |
43 | static BitmapImage? Stream2BitmapImage(Stream? stream)
44 | {
45 | if (stream is null)
46 | return null;
47 |
48 | var bitmapImage = new BitmapImage
49 | {
50 | CacheOption = BitmapCacheOption.OnLoad
51 | };
52 |
53 | bitmapImage.BeginInit();
54 | bitmapImage.StreamSource = stream;
55 | bitmapImage.EndInit();
56 | bitmapImage.Freeze();
57 |
58 | return bitmapImage;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Arthas/ThemeBrush.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Markup;
2 | using System.Windows.Media;
3 |
4 | namespace Arthas;
5 |
6 | public class ThemeBrushExtension : MarkupExtension
7 | {
8 | readonly ThemeKey _key;
9 |
10 | public ThemeBrushExtension(ThemeKey key)
11 | {
12 | _key = key;
13 | }
14 |
15 | public override object ProvideValue(IServiceProvider serviceProvider)
16 | {
17 | return _key switch
18 | {
19 | ThemeKey.Primary => new SolidColorBrush(Color.FromRgb(92, 90, 238)),
20 |
21 | ThemeKey.Background => new(Color.FromRgb(247, 247, 247)),
22 | ThemeKey.BorderBrush => new(Color.FromArgb((byte)(255 * 0.1), 38, 38, 38)),
23 | ThemeKey.Foreground => new(Color.FromRgb(38, 38, 38)),
24 |
25 | ThemeKey.CaptionBackground => new(Color.FromRgb(92, 90, 238)),
26 | ThemeKey.CaptionForeground => new(Color.FromRgb(255, 255, 255)),
27 |
28 | _ => throw new ArgumentOutOfRangeException()
29 | };
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Arthas/ThemeKey.cs:
--------------------------------------------------------------------------------
1 | namespace Arthas;
2 |
3 | public enum ThemeKey
4 | {
5 | Primary,
6 |
7 | Background,
8 | BorderBrush,
9 | Foreground,
10 |
11 | CaptionBackground,
12 | CaptionForeground
13 | }
14 |
--------------------------------------------------------------------------------
/Arthas/Themes/Generic.xaml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Build.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | dotnet clean --nologo -c Release
3 | dotnet pack --nologo -c Release -o ./Output
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | net7.0-windows
4 | enable
5 | latest
6 | enable
7 | true
8 | true
9 | 1.0.0
10 |
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 ONEO
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Arthas
2 |
3 | > 一个 WPF 控件库,在学习 WPF 开发时创作
4 |
5 | ## 开发计划
6 |
7 | - 目前在 [develop](https://github.com/oneo-me/Arthas-WPFUI/tree/develop) 分支创作
8 | - MVVM 框架使用我另一个库 [OpenView](https://github.com/oneo-me/OpenView)
9 | - 我会尽可能的把这个库的全部问题修复
10 | - 不会增加新功能
11 | - 如果时间允许,我会开发一个基于 [Avalonia](https://avaloniaui.net/) 的界面库(与 WPF 写法类似,但可以跨主流平台)
12 |
13 | ## 截屏
14 |
15 | 
16 |
17 | ## 支持
18 |
19 | - .Net 7.0 Windows Desktop
20 |
21 | ## 食用方法
22 |
23 | - Clone 代码到本地
24 | - 打开项目
25 |
--------------------------------------------------------------------------------
/Screenshots/1.png:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:f0227d2a9b3effe6f729bd514c9e701551ec1bb17f587ff3e4027f1d546548df
3 | size 122772
4 |
--------------------------------------------------------------------------------