WPF 创建自定义窗体

时间:2023-01-27 09:01:32

在前面的一篇博客"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);
}

到此为止,就实现了一个可以拖拽改变大小的自定义窗体。

运行效果:

WPF 创建自定义窗体

感谢您的阅读,代码点击这里下载。