原文:
WPF 创建自定义窗体
在前面的一篇博客"WPF 自定义Metro Style窗体",展示了如何创建一个类似于Metro Style的Window,并在程序中使用。但是这个窗体不能够自由的改变大小。今天的博客中将展示如何创建一个可以通过拖拽来改变大小的Metro Style窗体。
实现思路,在Windows ControlTemplate中增加8个背景透明Rectangle,分别放置于Left, Right, Top, TopLeft, TopRight, Bottom, BottomLeft, BottomRight这8个位置,
XAML:
<ControlTemplate x:Key="MetroWindowControlTemplate" TargetType="{x:Type Window}"> <Border BorderThickness="1" BorderBrush="LightBlue" Background="White"> <Grid> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Rectangle x:Name="MoveableRectangle" Fill="LightGray" Grid.Row="0" Grid.Column="0"/> <StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal" Background="LightGray"> <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>
C#:
ControlTemplate template = App.Current.FindResource("MetroWindowControlTemplate") as ControlTemplate; if(template != null) { //.... Grid resizeGrid = template.FindName("ResizeGrid", this) 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; } } } } private void ResizeRectangle_PreviewMouseDown(object sender, MouseButtonEventArgs e) { Rectangle rectangle = sender as Rectangle; if(rectangle != null) { 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 ResizeRectangle_MouseMove(object sender, MouseEventArgs e) { Rectangle rectangle = sender as Rectangle; if (rectangle != null) { 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; } } } [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam); private void ResizeWindow(ResizeDirection direction) { SendMessage(_hwndSource.Handle, 0x112, (IntPtr)(61440 + direction), IntPtr.Zero); }
到此为止,就实现了一个可以拖拽改变大小的自定义窗体。
运行效果:
感谢您的阅读,代码点击这里下载。