C# wpf 实现窗口任意区域点击拖动

 更新时间:2024年03月27日 11:15:59   作者:CodeOfCC  
在wpf要实现此功能简单形式还是比较容易的,但是有一些细节需要专门处理,比如与按钮的点击事件冲突问题,解决事件冲突问题后拖动的灵敏度,可复用性等,这篇文章主要介绍了C# wpf 实现窗口任意区域点击拖动,需要的朋友可以参考下
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

前言

点击窗口任意区域可移动功能,在一些业务场景中会使用到,比如工具条或者球形状的窗口等。在wpf要实现此功能简单形式还是比较容易的,但是有一些细节需要专门处理,比如与按钮的点击事件冲突问题,解决事件冲突问题后拖动的灵敏度,可复用性等。

一、简单拖动

基础的拖动功能直接使用Window类的DragMove即可实现:
在Window的PreviewMouseLeftButtonDown中调用DragMove即可。
示例如下:

<Window PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown" />
void Window_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    DragMove();
}

注:本文实现的是窗口任意区域拖动(比如按钮占满整个窗口),不适用于一般窗口拖动,一般窗口拖动请使用MouseLeftButtonDown事件

二、事件冲突问题

根据上述方法实现窗口拖动后发现出现了事件冲突,即窗口内的控件无法相应鼠标点击事件了。因为DragMove的内部实现使用了SC_MOVE,使标题栏(win32窗口)捕获鼠标,原本窗口失去鼠标捕获。窗口内的控件无法响应鼠标消息,因此上述简单拖动在有控件的窗口中是不可行的(局部拖动是可行的,但本文讲的是任意区域拖动)。

三、解决方法

解决方法是不在鼠标按下事件中触发拖动,而是在鼠标移动后触发拖动操作。具体步骤如下:
1、注册3个事件如下:

<Window PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown"
        PreviewMouseMove="Window_PreviewMouseMove"
        PreviewMouseLeftButtonUp="Window_PreviewMouseLeftButtonUp"/>

2、定义2个变量记录信息。

Point _pressedPosition ;
bool _isDragMoved = false;

3.记录鼠标按下位置

void Window_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    _pressedPosition = e.GetPosition(this);
}

4.鼠标移动触发拖动

 void Window_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
 {
     if (Mouse.LeftButton==MouseButtonState.Pressed && _pressedPosition != e.GetPosition(this))
     {
         _isDragMoved = true;
         DragMove();
     }
 }

5.鼠标弹起屏蔽消息

 void Window_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
 {
     if (_isDragMoved)
     {
         _isDragMoved = false;
         e.Handled = true;
     }
 }

四、效果预览

五、使用示例

由于评论区反馈上述方法存在bug,但是无奈笔者始终没有重现,怀疑是使用方法不正确,或者对本博文讲述功能理解上的差异导致的,在此根据上述方法初版原封不动的编写如下使用示例,以说明使用场景以及使用方法

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="关闭"  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)、效果预览

总结

本文介绍了在窗口任意区域点击拖动的方法。简单的拖动是不可行的,往深一步探究,发现了巧妙的解决方法:在鼠标移动时触发拖动。但这也不是一蹴而就的,这是笔者曾经做项目经过了一定的探究最终得以实现,而本文呈现的是优化后的精简版本,易于实现也很好理解,即是所谓的大道至简。

到此这篇关于C# wpf 实现窗口任意区域点击拖动的文章就介绍到这了,更多相关C# wpf窗口拖动内容请搜索程序员之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持程序员之家!

相关文章

  • c#判断email地址是否为合法

    c#判断email地址是否为合法

    输入email地址使用c#语言检测出email地址是否是合法的,这篇文章主要介绍了c#判断email地址是否为合法的相关资料,需要的朋友可以参考下
    2016-07-07
  • WPF使用Dragablz构建可拖拽分离的Tab页程序

    WPF使用Dragablz构建可拖拽分离的Tab页程序

    这篇文章介绍了WPF使用Dragablz构建可拖拽分离Tab页的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • C# 重写ComboBox实现下拉任意组件的方法

    C# 重写ComboBox实现下拉任意组件的方法

    C#种的下拉框ComboBox不支持下拉复选框列表与下拉树形列表等,系统中需要用到的地方使用了第三方组件,现在需要将第三方组件替换掉。这篇文章主要介绍了C# 重写ComboBox实现下拉任意组件的相关资料,需要的朋友可以参考下
    2016-10-10
  • C#实现windows form限制文本框输入的方法

    C#实现windows form限制文本框输入的方法

    这篇文章主要介绍了C#实现windows form限制文本框输入的方法,涉及C#限制文本框输入的技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04
  • Unity实现卡片循环滚动效果的示例详解

    Unity实现卡片循环滚动效果的示例详解

    这篇文章主要为大家详细介绍了如何利用Unity实现卡片循环滚动的效果,文中的实现步骤讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2022-12-12
  • 详解如何在C#/.NET Core中使用责任链模式

    详解如何在C#/.NET Core中使用责任链模式

    这篇文章主要介绍了详解如何在C#/.NET Core中使用责任链模式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • C#中ManualResetEvent用法详解

    C#中ManualResetEvent用法详解

    这篇文章主要为大家详细介绍了C#中ManualResetEvent用法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • C# 游戏外挂实现核心代码

    C# 游戏外挂实现核心代码

    最近打算学习下游戏外挂,因为c#语言,感觉比较顺,高手用delphi的多,不知道哪个最好。
    2009-01-01
  • C#实现读取ini配置文件的内容

    C#实现读取ini配置文件的内容

    INI就是扩展名为"INI"的文件,其实他本身是个文本文件,可以用记事本打开,本文主要为大家详细介绍了C#实现读取ini配置文件内容的方法,需要的小伙伴可以了解下
    2023-12-12
  • c#的dllimport使用方法详解

    c#的dllimport使用方法详解

    DllImport是System.Runtime.InteropServices命名空间下的一个属性类,其功能是提供从非托管DLL导出的函数的必要调用信息
    2014-01-01

最新评论

?


http://www.vxiaotou.com