C# wpf 實現(xiàn)窗口任意區(qū)域點擊拖動
前言
點擊窗口任意區(qū)域可移動功能,在一些業(yè)務(wù)場景中會使用到,比如工具條或者球形狀的窗口等。在wpf要實現(xiàn)此功能簡單形式還是比較容易的,但是有一些細(xì)節(jié)需要專門處理,比如與按鈕的點擊事件沖突問題,解決事件沖突問題后拖動的靈敏度,可復(fù)用性等。
一、簡單拖動
基礎(chǔ)的拖動功能直接使用Window類的DragMove即可實現(xiàn):
在Window的PreviewMouseLeftButtonDown中調(diào)用DragMove即可。
示例如下:
<Window PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown" />
void Window_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
DragMove();
}注:本文實現(xiàn)的是窗口任意區(qū)域拖動(比如按鈕占滿整個窗口),不適用于一般窗口拖動,一般窗口拖動請使用MouseLeftButtonDown事件
二、事件沖突問題
根據(jù)上述方法實現(xiàn)窗口拖動后發(fā)現(xiàn)出現(xiàn)了事件沖突,即窗口內(nèi)的控件無法相應(yīng)鼠標(biāo)點擊事件了。因為DragMove的內(nèi)部實現(xiàn)使用了SC_MOVE,使標(biāo)題欄(win32窗口)捕獲鼠標(biāo),原本窗口失去鼠標(biāo)捕獲。窗口內(nèi)的控件無法響應(yīng)鼠標(biāo)消息,因此上述簡單拖動在有控件的窗口中是不可行的(局部拖動是可行的,但本文講的是任意區(qū)域拖動)。

三、解決方法
解決方法是不在鼠標(biāo)按下事件中觸發(fā)拖動,而是在鼠標(biāo)移動后觸發(fā)拖動操作。具體步驟如下:
1、注冊3個事件如下:
<Window PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown"
PreviewMouseMove="Window_PreviewMouseMove"
PreviewMouseLeftButtonUp="Window_PreviewMouseLeftButtonUp"/>2、定義2個變量記錄信息。
Point _pressedPosition ; bool _isDragMoved = false;
3.記錄鼠標(biāo)按下位置
void Window_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
_pressedPosition = e.GetPosition(this);
}4.鼠標(biāo)移動觸發(fā)拖動
void Window_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (Mouse.LeftButton==MouseButtonState.Pressed && _pressedPosition != e.GetPosition(this))
{
_isDragMoved = true;
DragMove();
}
}5.鼠標(biāo)彈起屏蔽消息
void Window_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_isDragMoved)
{
_isDragMoved = false;
e.Handled = true;
}
}四、效果預(yù)覽

五、使用示例
由于評論區(qū)反饋上述方法存在bug,但是無奈筆者始終沒有重現(xiàn),懷疑是使用方法不正確,或者對本博文講述功能理解上的差異導(dǎo)致的,在此根據(jù)上述方法初版原封不動的編寫如下使用示例,以說明使用場景以及使用方法。
1、白板的工具條
(1)、MainWindow.xaml
<Window x:Class="WpfApp3.MainWindow"
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:WpfApp3"
mc:Ignorable="d"
Background="Transparent"
AllowsTransparency="True"
WindowStyle="None"
Title="MainWindow" Height="60" Width="410"
PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown"
PreviewMouseMove="Window_PreviewMouseMove"
PreviewMouseLeftButtonUp="Window_PreviewMouseLeftButtonUp">
<Border Background="White" CornerRadius="25" Margin="5">
<Border.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="5" Opacity="0.8" Color="#AAAAAA"/>
</Border.Effect>
<StackPanel Margin="20,0,0,0" Orientation="Horizontal">
<RadioButton Content="畫筆" Width="50" Height="50" Cursor="Hand">
<RadioButton.Template>
<ControlTemplate TargetType="RadioButton" >
<Border Background="Transparent">
<TextBlock x:Name="txt" Background="Transparent" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#666666" FontSize="18"
Text="{TemplateBinding Content}"></TextBlock>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="txt" Property="Foreground" Value="red"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
<RadioButton Content="矩形" Width="50" Height="50" Cursor="Hand">
<RadioButton.Template>
<ControlTemplate TargetType="RadioButton" >
<Border Background="Transparent">
<TextBlock x:Name="txt" Background="Transparent" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#666666" FontSize="18"
Text="{TemplateBinding Content}"></TextBlock>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="txt" Property="Foreground" Value="red"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
<RadioButton Content="文本" Width="50" Height="50" Cursor="Hand">
<RadioButton.Template>
<ControlTemplate TargetType="RadioButton" >
<Border Background="Transparent">
<TextBlock x:Name="txt" Background="Transparent" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#666666" FontSize="18"
Text="{TemplateBinding Content}"></TextBlock>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="txt" Property="Foreground" Value="red"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
<RadioButton Content="箭頭" Width="50" Height="50" Cursor="Hand">
<RadioButton.Template>
<ControlTemplate TargetType="RadioButton" >
<Border Background="Transparent">
<TextBlock x:Name="txt" Background="Transparent" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#666666" FontSize="18"
Text="{TemplateBinding Content}"></TextBlock>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="txt" Property="Foreground" Value="red"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
<RadioButton Content="圖片" Width="50" Height="50" Cursor="Hand">
<RadioButton.Template>
<ControlTemplate TargetType="RadioButton" >
<Border Background="Transparent">
<TextBlock x:Name="txt" Background="Transparent" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#666666" FontSize="18"
Text="{TemplateBinding Content}"></TextBlock>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="txt" Property="Foreground" Value="red"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
<Border Margin="10,0,0,0" BorderThickness="1,0,0,0" BorderBrush="#999999"></Border>
<Button Name="btn_upload" Margin="0,0,0,0" Content="上傳" Width="50" Height="50" Cursor="Hand" Click="btn_upload_Click">
<Button.Template>
<ControlTemplate TargetType="Button" >
<Border Background="Transparent">
<TextBlock Background="Transparent" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#666666" FontSize="18"
Text="{TemplateBinding Content}"></TextBlock>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<Button Name="btn_close" Margin="0,0,0,0" Content="關(guān)閉" Width="50" Height="50" Cursor="Hand" Click="btn_close_Click">
<Button.Template>
<ControlTemplate TargetType="Button" >
<Border Background="Transparent">
<TextBlock Background="Transparent" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#666666" FontSize="18"
Text="{TemplateBinding Content}"></TextBlock>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
</Border>
</Window>(2)、MainWindow.xaml.cs
using System.Windows;
using System.Windows.Input;
namespace WpfApp3
{
/// <summary>
/// MainWindow.xaml 的交互邏輯
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
Point _pressedPosition;
bool _isDragMoved = false;
void Window_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
_pressedPosition = e.GetPosition(this);
}
void Window_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (Mouse.LeftButton == MouseButtonState.Pressed && _pressedPosition != e.GetPosition(this))
{
_isDragMoved = true;
DragMove();
}
}
void Window_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_isDragMoved)
{
_isDragMoved = false;
e.Handled = true;
}
}
private void btn_upload_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("上傳成功");
}
private void btn_close_Click(object sender, RoutedEventArgs e)
{
Close();
}
}
}(3)、效果預(yù)覽

總結(jié)
本文介紹了在窗口任意區(qū)域點擊拖動的方法。簡單的拖動是不可行的,往深一步探究,發(fā)現(xiàn)了巧妙的解決方法:在鼠標(biāo)移動時觸發(fā)拖動。但這也不是一蹴而就的,這是筆者曾經(jīng)做項目經(jīng)過了一定的探究最終得以實現(xiàn),而本文呈現(xiàn)的是優(yōu)化后的精簡版本,易于實現(xiàn)也很好理解,即是所謂的大道至簡。
到此這篇關(guān)于C# wpf 實現(xiàn)窗口任意區(qū)域點擊拖動的文章就介紹到這了,更多相關(guān)C# wpf窗口拖動內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# networkcomms 3.0實現(xiàn)模擬登陸總結(jié)
這篇文章主要介紹了C# networkcomms 3.0實現(xiàn)模擬登陸總結(jié),需要的朋友可以參考下2017-06-06
C# 使用multipart form-data方式post數(shù)據(jù)到服務(wù)器
這篇文章主要介紹了C# 使用multipart form-data方式post數(shù)據(jù)到服務(wù)器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
C#利用Task實現(xiàn)任務(wù)超時多任務(wù)一起執(zhí)行的方法
這篇文章主要給大家介紹了關(guān)于C#利用Task實現(xiàn)任務(wù)超時,多任務(wù)一起執(zhí)行的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友下面來一起看看吧。2017-12-12

