Create a new project of type Class Library named CustomControls.
CustomWindow.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Windows.Interop; using System.Runtime.InteropServices; namespace CustomControls { public partial class CustomWindow : Window { #region Click events protected void MinimizeClick(object sender, RoutedEventArgs e) { WindowState = WindowState.Minimized; } protected void RestoreClick(object sender, RoutedEventArgs e) { WindowState = (WindowState == WindowState.Normal) ? WindowState.Maximized : WindowState.Normal; } protected virtual void CloseClick(object sender, RoutedEventArgs e) { Close(); } #endregion static CustomWindow() { DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomWindow), new FrameworkPropertyMetadata(typeof(CustomWindow))); } public CustomWindow() : base() { PreviewMouseMove += OnPreviewMouseMove; } private HwndSource _hwndSource; protected override void OnInitialized(EventArgs e) { SourceInitialized += OnSourceInitialized; base.OnInitialized(e); } private void OnSourceInitialized(object sender, EventArgs e) { _hwndSource = (HwndSource)PresentationSource.FromVisual(this); } public override void OnApplyTemplate() { Rectangle moveRectangle = GetTemplateChild("moveRectangle") as Rectangle; if (moveRectangle != null) moveRectangle.PreviewMouseDown += moveRectangle_PreviewMouseDown; Button minimizeButton = GetTemplateChild("minimizeButton") as Button; if (minimizeButton != null) minimizeButton.Click += MinimizeClick; Button restoreButton = GetTemplateChild("restoreButton") as Button; if (restoreButton != null) restoreButton.Click += RestoreClick; Button closeButton = GetTemplateChild("closeButton") as Button; if (closeButton != null) closeButton.Click += CloseClick; Grid resizeGrid = GetTemplateChild("resizeGrid") as Grid; if (resizeGrid != null) { foreach (UIElement element in resizeGrid.Children) { Rectangle resizeRectangle = element as Rectangle; if (resizeRectangle != null) { resizeRectangle.PreviewMouseDown += ResizeRectangle_PreviewMouseDown; resizeRectangle.MouseMove += ResizeRectangle_MouseMove; } } } base.OnApplyTemplate(); } protected void ResizeRectangle_MouseMove(Object sender, MouseEventArgs e) { Rectangle rectangle = sender as Rectangle; switch (rectangle.Name) { case "top": Cursor = Cursors.SizeNS; break; case "bottom": Cursor = Cursors.SizeNS; break; case "left": Cursor = Cursors.SizeWE; break; case "right": Cursor = Cursors.SizeWE; break; case "topLeft": Cursor = Cursors.SizeNWSE; break; case "topRight": Cursor = Cursors.SizeNESW; break; case "bottomLeft": Cursor = Cursors.SizeNESW; break; case "bottomRight": Cursor = Cursors.SizeNWSE; break; default: break; } } private void moveRectangle_PreviewMouseDown(object sender, MouseButtonEventArgs e) { if (Mouse.LeftButton == MouseButtonState.Pressed) DragMove(); } protected void OnPreviewMouseMove(object sender, MouseEventArgs e) { if (Mouse.LeftButton != MouseButtonState.Pressed) Cursor = Cursors.Arrow; } [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam); protected void ResizeRectangle_PreviewMouseDown(object sender, MouseButtonEventArgs e) { Rectangle rectangle = sender as Rectangle; switch (rectangle.Name) { case "top": Cursor = Cursors.SizeNS; ResizeWindow(ResizeDirection.Top); break; case "bottom": Cursor = Cursors.SizeNS; ResizeWindow(ResizeDirection.Bottom); break; case "left": Cursor = Cursors.SizeWE; ResizeWindow(ResizeDirection.Left); break; case "right": Cursor = Cursors.SizeWE; ResizeWindow(ResizeDirection.Right); break; case "topLeft": Cursor = Cursors.SizeNWSE; ResizeWindow(ResizeDirection.TopLeft); break; case "topRight": Cursor = Cursors.SizeNESW; ResizeWindow(ResizeDirection.TopRight); break; case "bottomLeft": Cursor = Cursors.SizeNESW; ResizeWindow(ResizeDirection.BottomLeft); break; case "bottomRight": Cursor = Cursors.SizeNWSE; ResizeWindow(ResizeDirection.BottomRight); break; default: break; } } private void ResizeWindow(ResizeDirection direction) { SendMessage(_hwndSource.Handle, 0x112, (IntPtr)(61440 + direction), IntPtr.Zero); } private enum ResizeDirection { Left = 1, Right = 2, Top = 3, TopLeft = 4, TopRight = 5, Bottom = 6, BottomLeft = 7, BottomRight = 8, } } }
Themes\Generic.xaml
<resourcedictionary xmlns:local="clr-namespace:CustomControls" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <!-- Window Button style --> <style targettype="{x:Type Button}" x:key="WindowButtonStyle"> <setter Property="Background" Value="Transparent"/> <setter Property="Foreground" Value="{DynamicResource GreyLightBrush}" /> <setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/> <setter Property="FontFamily" Value="Webdings"/> <setter Property="FontSize" Value="13.333" /> <setter Property="Margin" Value="1,1,1,0"/> <setter Property="Template"> <Setter.Value> <controltemplate TargetType="{x:Type ButtonBase}"> <border x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Margin="0" SnapsToDevicePixels="True"> <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" /> </Border> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <trigger Property="IsMouseOver" Value="True"> <setter Property="Foreground" Value="{DynamicResource WhiteBrush}" /> </Trigger> </Style.Triggers> </style> <!-- Window style --> <style targettype="{x:Type local:CustomWindow}"> <setter Property="WindowStyle" Value="None"/> <setter Property="ResizeMode" Value="NoResize"/> <setter Property="Foreground" Value="{DynamicResource ForegroundBrush}" /> <setter Property="Background" Value="{DynamicResource BackgroundBrush}"/> <setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/> <setter Property="BorderThickness" Value="1"/> <setter Property="Template"> <Setter.Value> <controltemplate TargetType="{x:Type local:CustomWindow}"> <border BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}"> <grid> <grid> <Grid.RowDefinitions> <rowdefinition Height="Auto"/> <rowdefinition /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <columndefinition /> <columndefinition Width="Auto"/> </Grid.ColumnDefinitions> <rectangle x:Name="moveRectangle" Fill="Transparent" Grid.Row="0" Grid.Column="0"/> <textblock x:Name="windowTitle" Margin="10 0" FontSize="16" Grid.Column="0" Grid.Row="0" Panel.ZIndex="-1" Foreground="{DynamicResource GreyLightBrush}" Text="{TemplateBinding Title}"/> <stackpanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal"> <button x:Name="minimizeButton" Style="{StaticResource WindowButtonStyle}" Content="0" /> <button x:Name="restoreButton" Style="{StaticResource WindowButtonStyle}" Content="1" /> <button x:Name="closeButton" Style="{StaticResource WindowButtonStyle}" Content="r" /> </StackPanel> <grid Background="{TemplateBinding Background}" Grid.Row="1" Grid.ColumnSpan="2" Margin="5,5,5,5"> <adornerdecorator> <ContentPresenter/> </AdornerDecorator> </Grid> </Grid> <grid x:Name="resizeGrid"> <Rectangle Stroke="{x:Null}" Fill="Transparent" VerticalAlignment="Top" Height="5" x:Name="top" Margin="5,0,5,0" /> <Rectangle Stroke="{x:Null}" Fill="Transparent" x:Name="bottom" Height="5" VerticalAlignment="Bottom" Margin="5,0,5,0" /> <Rectangle Stroke="{x:Null}" Fill="Transparent" HorizontalAlignment="Left" Margin="0,5,0,5" Width="5" x:Name="left"/> <Rectangle Stroke="{x:Null}" Fill="Transparent" Margin="0,5,0,5" Width="5" HorizontalAlignment="Right" x:Name="right" /> <Rectangle Stroke="{x:Null}" Fill="Transparent" HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="5" Height="5" x:Name="bottomLeft" /> <Rectangle Stroke="{x:Null}" Fill="Transparent" VerticalAlignment="Bottom" Height="5" Width="5" HorizontalAlignment="Right" x:Name="bottomRight" /> <Rectangle Stroke="{x:Null}" Fill="Transparent" HorizontalAlignment="Right" Width="5" Height="5" VerticalAlignment="Top" x:Name="topRight" /> <Rectangle Stroke="{x:Null}" Fill="Transparent" HorizontalAlignment="Left" Width="6" VerticalAlignment="Top" Height="5" x:Name="topLeft" /> </Grid> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </style> </resourcedictionary>
Now you can include this custom controls project as a reference in whichever project you want to use the custom window. After adding it as a reference, here is how to implement it, very simple!
MainWindow.xaml
<control:customwindow height="350" title="MainWindow" width="525" x:class="YourApp.MainWindow" xmlns:control="clr-namespace:CustomControls;assembly=CustomControls" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <grid> </grid> </control:customwindow>
And in the code behind we inherit from our custom class:
MainWindow.xaml.cs
public partial class MainWindow : CustomControls.CustomWindow { public MainWindow() { InitializeComponent(); } }
No comments:
Post a Comment