WPF 自定義窗體實現拖動邊框改變窗體大小(2種方法)
阿新 • • 發佈:2018-11-28
方式一:呼叫user32.dllAPI
這種方式在網上有很多,這裡只是按步驟重新建立一次。讀者只需要跟著做就行。
第一步:建立一個WPF專案:WpfResizeWithoutBorder,右鍵專案檔案---->新增----->資源字典,並命名為:WindowsResizeBorderTemplete.xaml。
第二步:在剛剛建立的資原始檔(WindowsResizeBorderTemplete.xaml)中複製如下程式碼:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <ControlTemplate x:Key="CustomWindowTemplete" TargetType="Window"> <Border BorderBrush="Transparent" BorderThickness="12" x:Name="outBorder"> <Border.Effect> <DropShadowEffect BlurRadius="15" Color="#000000" Opacity=".25" Direction="90" ShadowDepth="1"/> </Border.Effect> <Grid> <Grid.RowDefinitions> <RowDefinition Height="1"/> <RowDefinition/> <RowDefinition Height="1"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="1"/> <ColumnDefinition/> <ColumnDefinition Width="1"/> </Grid.ColumnDefinitions> <Grid Grid.Row="1" Grid.Column="1" Background="White" > <AdornerDecorator> <ContentPresenter></ContentPresenter> </AdornerDecorator> </Grid> <Rectangle Name="ResizeTopLeft" Fill="Red" Grid.Row="0" Grid.Column="0" Opacity=".25"/> <Rectangle Name="ResizeTop" Fill="Red" Grid.Row="0" Grid.Column="1" Opacity=".25"/> <Rectangle Name="ResizeTopRight" Fill="Red" Grid.Row="0" Grid.Column="2" Opacity=".25"/> <Rectangle Name="ResizeLeft" Fill="Red" Grid.Row="1" Grid.Column="0" Opacity=".25"/> <Rectangle Name="ResizeRight" Fill="Red" Grid.Row="1" Grid.Column="2" Opacity=".25"/> <Rectangle Name="ResizeBottomLeft" Fill="Red" Grid.Row="2" Grid.Column="0" Opacity=".25"/> <Rectangle Name="ResizeBottom" Fill="Red" Grid.Row="2" Grid.Column="1" Opacity=".25"/> <Rectangle Name="ResizeBottomRight" Fill="Red" Grid.Row="2" Grid.Column="2" Opacity=".25"/> </Grid> </Border> </ControlTemplate> <Style x:Key="CustomWindow" TargetType="Window"> <Setter Property="AllowsTransparency" Value="True"/> <Setter Property="WindowStyle" Value="None"/> <Setter Property="Template" Value="{StaticResource CustomWindowTemplete}"></Setter> </Style> </ResourceDictionary>
第三步:新增一個類檔案:VcreditWindowBehindCode.cs,複製程式碼如下:
///Editor:Mey Eaphone ///Date:20180929 using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Shapes; namespace WpfResizeWithoutBorder { public class VcreditWindowBehindCode : Window { public const int WM_SYSCOMMAND = 0x112; public HwndSource HwndSource; public Dictionary<ResizeDirection, Cursor> cursors = new Dictionary<ResizeDirection, Cursor> { {ResizeDirection.Top, Cursors.SizeNS}, {ResizeDirection.Bottom, Cursors.SizeNS}, {ResizeDirection.Left, Cursors.SizeWE}, {ResizeDirection.Right, Cursors.SizeWE}, {ResizeDirection.TopLeft, Cursors.SizeNWSE}, {ResizeDirection.BottomRight, Cursors.SizeNWSE}, {ResizeDirection.TopRight, Cursors.SizeNESW}, {ResizeDirection.BottomLeft, Cursors.SizeNESW} }; public enum ResizeDirection { Left = 1, Right = 2, Top = 3, TopLeft = 4, TopRight = 5, Bottom = 6, BottomLeft = 7, BottomRight = 8, } [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); public VcreditWindowBehindCode() { this.SourceInitialized += VcreditWindowBehindCode_SourceInitialized; this.Loaded += VcreditWindowBehindCode_Loaded; this.MouseMove += VcreditWindowBehindCode_MouseMove; } private void VcreditWindowBehindCode_MouseMove(object sender, MouseEventArgs e) { if (Mouse.LeftButton != MouseButtonState.Pressed) { FrameworkElement element = e.OriginalSource as FrameworkElement; if (element != null && !element.Name.Contains("Resize")) { this.Cursor = Cursors.Arrow; } } } private void VcreditWindowBehindCode_SourceInitialized(object sender, EventArgs e) { this.HwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource; } private void VcreditWindowBehindCode_Loaded(object sender, RoutedEventArgs e) { ControlTemplate customWindowTemplate = App.Current.Resources["CustomWindowTemplete"] as ControlTemplate; if (customWindowTemplate != null) { var TopLeft = customWindowTemplate.FindName("ResizeTopLeft", this) as Rectangle; TopLeft.MouseMove += ResizePressed; TopLeft.MouseDown += ResizePressed; var Top = customWindowTemplate.FindName("ResizeTop", this) as Rectangle; Top.MouseMove += ResizePressed; Top.MouseDown += ResizePressed; var TopRight = customWindowTemplate.FindName("ResizeTopRight", this) as Rectangle; TopRight.MouseMove += ResizePressed; TopRight.MouseDown += ResizePressed; var Left = customWindowTemplate.FindName("ResizeLeft", this) as Rectangle; Left.MouseMove += ResizePressed; Left.MouseDown += ResizePressed; var Right = customWindowTemplate.FindName("ResizeRight", this) as Rectangle; Right.MouseMove += ResizePressed; Right.MouseDown += ResizePressed; var BottomLeft = customWindowTemplate.FindName("ResizeBottomLeft", this) as Rectangle; BottomLeft.MouseMove += ResizePressed; BottomLeft.MouseDown += ResizePressed; var Bottom = customWindowTemplate.FindName("ResizeBottom", this) as Rectangle; Bottom.MouseMove += ResizePressed; Bottom.MouseDown += ResizePressed; var BottomRight = customWindowTemplate.FindName("ResizeBottomRight", this) as Rectangle; BottomRight.MouseMove += ResizePressed; BottomRight.MouseDown += ResizePressed; } } public void ResizePressed(object sender, MouseEventArgs e) { FrameworkElement element = sender as FrameworkElement; ResizeDirection direction = (ResizeDirection)Enum.Parse(typeof(ResizeDirection), element.Name.Replace("Resize", "")); this.Cursor = cursors[direction]; if (e.LeftButton == MouseButtonState.Pressed) { ResizeWindow(direction); } } public void ResizeWindow(ResizeDirection direction) { SendMessage(HwndSource.Handle, WM_SYSCOMMAND, (IntPtr)(61440 + direction), IntPtr.Zero); } } }
第四步:再右鍵專案檔案,新增一個窗體,命名為Window3.xaml。並在檔案資源管理器中找到Window3.xaml.cs並點選刪除。然後在建立一個類檔案Window3.cs。此時專案結構如下所示。
第五步:開啟Window3.xaml檔案,將複製程式碼如下:
<local:VcreditWindowBehindCode x:Class="WpfResizeWithoutBorder.Window3" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfResizeWithoutBorder" Title="MainWindow" Height="350" Width="525" WindowStyle="None" ResizeMode="CanResizeWithGrip" AllowsTransparency="True" Style="{StaticResource CustomWindow}" > <Grid> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Canvas Name="nav_Bar" Grid.Row="0" Background="Blue"> <Button Name="btnMax" Content="Max" Canvas.Left="375" Canvas.Top="10" Width="75"/> </Canvas> </Grid> </local:VcreditWindowBehindCode>
第六步:開啟Window3.cs檔案,然後將程式碼複製如下
///Editor:Mey Eaphone
///Date:20180929
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfResizeWithoutBorder
{
/// <summary>
///
/// </summary>
public partial class Window3:VcreditWindowBehindCode
{
/// <summary>
///
/// </summary>
public Window3()
{
InitializeComponent();
InitializeRouted();
}
/// <summary>
/// 初始化事件
/// </summary>
private void InitializeRouted()
{
nav_Bar.AddHandler(Canvas.MouseDownEvent, new MouseButtonEventHandler(Window3_MouseMove),true);
btnMax.AddHandler(Button.MouseDoubleClickEvent, new MouseButtonEventHandler(Window3_Maxied), true);
}
/// <summary>
/// 最大普通化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Window3_Maxied(object sender, MouseButtonEventArgs e)
{
if (this.WindowState == System.Windows.WindowState.Normal)
{
this.WindowState = System.Windows.WindowState.Maximized;
}
else
{
this.WindowState = System.Windows.WindowState.Normal;
}
}
/// <summary>
/// 窗體拖動
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Window3_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
this.DragMove();
}
}
}
第七步:開啟App.xaml檔案,將複製程式碼,修改為:
<Application x:Class="WpfResizeWithoutBorder.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window3.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="WindowsResizeBorderTemplete.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
最後F5檢視效果。
方式二:直接使用WindowChrome(.Net4.5.1以上)
第一種方式非常複雜,在.net4.5.1之後,迎來了革新的東西——WindowChrome,使用方法很簡單。
第一步:新建窗體Window1.xaml,開啟檔案,並複製程式碼如下:
<Window x:Class="WpfResizeWithoutBorder.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfResizeWithoutBorder"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<Window.Style>
<Style TargetType="Window">
<Setter Property="Background" Value="Transparent" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="ResizeMode" Value="CanResize" />
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome CaptionHeight="80" ResizeBorderThickness="20" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Window">
<Border Padding="10">
<Border Background="White"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="4"
SnapsToDevicePixels="True">
<!--陰影效果-->
<!--<Border.Effect>
<DropShadowEffect BlurRadius="10"
Direction="0"
ShadowDepth="0" />
</Border.Effect>-->
<ContentPresenter />
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Style>
</Window>
第二步:修改App.xaml檔案的啟動連結,複製程式碼如下:
<Application x:Class="WpfResizeWithoutBorder.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="WindowsResizeBorderTemplete.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
最後F5,出現的效果是不是你想要的,是不是很簡單。
總結:
1.方法一比較複雜,但是我們很清楚從無到有的整個過程,值得我們深入學習研究。
2.方法二簡單粗暴,使用.net新屬性,分分鐘搞定,實用性高。