Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >2020-5-22-如何使WPF在窗口外部区域可拖动缩放

2020-5-22-如何使WPF在窗口外部区域可拖动缩放

作者头像
黄腾霄
发布于 2020-06-10 07:42:45
发布于 2020-06-10 07:42:45
1.9K01
代码可运行
举报
文章被收录于专栏:黄腾霄的博客黄腾霄的博客
运行总次数:1
代码可运行

今天来和大家聊如何使WPF在窗口外部区域可拖动缩放。


问题来源

对于WPF窗口来说,默认的可拖动缩放区域较小。

在某些应用场景下我们期望能够设置一个较大的可拖动的缩放区域。

自定义WindowChrome

有同学马上想到了,通过WindowChromeResizeBorderThickness属性进行设置

比如下面的方式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<Window x:Class="WpfApp2.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"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <WindowChrome.WindowChrome>
        <WindowChrome ResizeBorderThickness="100"></WindowChrome>
    </WindowChrome.WindowChrome>
    <Grid Background="Transparent" MouseDown="UIElement_OnMouseDown">
        <Grid Margin="100" Background="White" />
        <Button Width="100" Height="100" Command="Undo" />
    </Grid>
</Window>

但是ResizeBorderThickness只能向窗口内部扩展,而在外部依然不可以进行拖动缩放

添加外部窗口

想要在WPF窗口外部能够拖动缩放,问题的关键就在于如何能在外部收到鼠标点击拖动等消息。

那么实际上我们只需要在主窗口周围添加四个alpha值为1窗口。

这些窗口用于接受消息,并传递给主窗口进行拖动变化即可实现。

(注:visual studio就是这样做的,可以通过工具抓到他周围包含了4个宽度为9像素的窗口)

监听主窗口状态变化

现在我们一共有了5个窗口。

要想这5个窗口能像一个窗口一样工作,必须要让周围的辅助窗口跟随主窗口的状态变化。

这里我主要关注主窗口的下面5个事件:

  • LocationChanged
  • SizeChanged
  • StateChanged
  • IsVisibleChanged
  • Closed

LocationChanged 和SizeChanged主要是通知辅助窗口调整位置和大小,确定包裹在主窗口周围

StateChanged和IsVisibleChanged用于通知窗口的显示隐藏,避免主窗口隐藏时,辅助窗口还能被拖动

Closed用于在主窗口关闭后,关闭辅助窗口以及释放资源。

有了这些事件,辅助窗口就能够跟随主窗口进行变换了。

通知主窗口

接下来一个重要的事情就是辅助窗口被点击拖动时,通知主窗口进行拖动缩放。

这个行为有很多实现方法,最简单的一种是,让辅助窗口假装自己是主窗口的非客户区。

听着很复杂,实际做起来很简单,就是在辅助窗口被点击时,给主窗口发一个非客户区被点击的win消息。

例如下面的代码加入到辅助左侧的辅助窗口中,就能让它在接收到windows的鼠标左键点击时,向主窗口发出一个左侧非客户区的border被点击的消息。

于是主窗口就傻傻的以为自己左侧非客户区的border被点中了,就进入了拖拽缩放的行为。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == (int)WM.LBUTTONDOWN)
            {
                Win32.PostMessage(new WindowInteropHelper(Owner).Handle,
                    (int) WM.NCLBUTTONDOWN, (int) HitTestValues.HTLEFT,
                    0);
            }

            return IntPtr.Zero;
        }

辅助窗口隐藏

有了双向的通知机制后,需要接下来需要将辅助窗口设置为透明。

这里参考了毅仔同学的高性能透明窗口做法。

具体内容不做详细讲解,有兴趣的同学可以参考毅仔同学的博客。

WPF 制作高性能的透明背景异形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True) - walterlv

关键代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//设置窗口非客户区大小为0
ResizeMode = ResizeMode.NoResize;
WindowStyle = WindowStyle.None;
WindowChrome.SetWindowChrome(this, new WindowChrome()
{
    GlassFrameThickness = new Thickness(-),
    CaptionHeight = 
});
//设置窗口alpha值为0x01
Opacity = 1.0 / ;

效果呈现

最后就可以得到如下的效果,我们可以在窗口的外部进行拖动,让主窗口进行缩放了。

另外,这里对整个代码做了封装,所以在使用时可以非常简单。

只需要在xaml中配置一个附加属性即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<Window x:Class="WpfApp2.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:extendedResizeBorder="clr-namespace:ExtendedResizeBorder;assembly=ExtendedResizeBorder"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <extendedResizeBorder:ExtendedResizeBorder.ExtendedResizeBorder>
        <extendedResizeBorder:ExtendedResizeBorder Radius="100" />
    </extendedResizeBorder:ExtendedResizeBorder.ExtendedResizeBorder>
    <Grid Background="Transparent" MouseDown="UIElement_OnMouseDown">
        <Grid Margin="100" Background="White" />
        <Button Width="100" Height="100" Command="Undo" />
    </Grid>
</Window>

代码

文中对应的代码已经推送到github的dotnet-campus组织下。

欢迎大家issue和star

dotnet-campus/ExtendedResizeBorder: Enable WPF window has an outside resizable border


参考文档:


本文会经常更新,请阅读原文: https://xinyuehtx.github.io/post/%E5%A6%82%E4%BD%95%E4%BD%BFWPF%E5%9C%A8%E7%AA%97%E5%8F%A3%E5%A4%96%E9%83%A8%E5%8C%BA%E5%9F%9F%E5%8F%AF%E6%8B%96%E5%8A%A8.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接: https://xinyuehtx.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-05-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
WPF窗体透明控件不透明实例
最近在做一个大屏展示视频图片的项目,功能并不复杂,半天的工作量吧,一开始同事采用的Unity3D进行开发,但是里面要播放4K视频,Unity 的短板就是视频的播放了,今晚就要交付了,我一早就来公司,决定用WPF重新开发一版,各项功能都好了,唯独顶部总是显示一条白色的边,已经设置WindowStyle为None了也没用,幸得网上大神提供的资料,终于解决了这个小问题。
zls365
2020/12/15
2.3K0
WPF 制作高性能的透明背景异形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True)
在 WPF 中,如果想做一个背景透明的异形窗口,基本上都要设置 WindowStyle="None"、AllowsTransparency="True" 这两个属性。如果不想自定义窗口样式,还需要设置 Background="Transparent"。这样的设置会让窗口变成 Layered Window,WPF 在这种类型窗口上的渲染性能是非常糟糕的。
walterlv
2023/10/22
1.8K0
WPF 制作高性能的透明背景异形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True)
WPF 按钮 Button 的 IsEnabled 属性对 WindowChrome 的 IsHitTestVisibleInChrome 的影响
在 WPF 里面,默认标题栏的交互相对复杂,如按钮没有设置 WindowChrome.IsHitTestVisibleInChrome 属性为 True 那按钮是拿不到点击事件的。本文来告诉大家按钮 Button 的 IsEnabled 属性对 WindowChrome 的 IsHitTestVisibleInChrome 的影响
林德熙
2020/12/21
1.7K0
修复 WPF 窗口在启动期间短暂的白底显示
2017-11-03 15:08
walterlv
2018/09/18
2.6K0
修复 WPF 窗口在启动期间短暂的白底显示
使用 WPF 做一个可以逼真地照亮你桌面的高性能阳光
本文想要做的,可不是随便弄一点阳光的半透明形状,然后简单地放到桌面上,而是真真正正地要照亮桌面上的窗口元素!并且,全程使用 GPU 加速,而且代码超简单。
walterlv
2023/10/23
5640
使用 WPF 做一个可以逼真地照亮你桌面的高性能阳光
WPF中图片剪裁并显示
XAML: <Window x:Class="WpfApp6.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"
zls365
2020/12/29
1.1K0
WPF中图片剪裁并显示
WPF 使用 WindowChrome,在自定义窗口标题栏的同时最大程度保留原生窗口样式(类似 UWP/Chrome)
发布于 2018-07-12 07:57 更新于 2018-09-05 05:46
walterlv
2018/09/18
6.8K0
WPF 使用 WindowChrome,在自定义窗口标题栏的同时最大程度保留原生窗口样式(类似 UWP/Chrome)
在 Windows 10 上为 WPF 窗口添加模糊特效(就像开始菜单和操作中心那样)
发布于 2017-10-01 16:14 更新于 2018-02-19 22:31
walterlv
2018/09/18
5.4K1
在 Windows 10 上为 WPF 窗口添加模糊特效(就像开始菜单和操作中心那样)
使用 SetWindowCompositionAttribute 来控制程序的窗口边框和背景(可以做 Acrylic 亚克力效果、模糊效果、主题色效果等)
Windows 系统中有一个没什么文档的 API,SetWindowCompositionAttribute,可以允许应用的开发者将自己窗口中的内容渲染与窗口进行组合。这可以实现很多系统中预设的窗口特效,比如 Windows 7 的毛玻璃特效,Windows 8/10 的前景色特效,Windows 10 的模糊特效,以及 Windows 10 1709 的亚克力(Acrylic)特效。而且这些组合都发生在 dwm 进程中,不会额外占用应用程序的渲染性能。
walterlv
2023/10/22
1.7K0
使用 SetWindowCompositionAttribute 来控制程序的窗口边框和背景(可以做 Acrylic 亚克力效果、模糊效果、主题色效果等)
.NET6三分钟搭建WPF三维应用
要运行本文中的示例,请先安装Vistual Studio 2022,社区版就可以了。
郑子铭
2023/12/19
2790
.NET6三分钟搭建WPF三维应用
C#WPF基础02
可分为普通菜单(Menu)和上下文菜单(ContextMenu俗称右键菜单),Menu下可以放Menuitems,Menuitem下又可以放Menuitem。
Echo_Wish
2023/11/30
1760
C# WPF资源使用入门实例
1. 添加两个textbox,第一个textbox从XMAL资源中获取字符串,第二个textbox从C#中获取资源
zls365
2020/12/29
1K0
C# WPF资源使用入门实例
WPF / Windows Forms 检测窗口在哪个屏幕
使用 Windows Forms 自带的 System.Windows.Forms.Screen 类可以从一个窗口句柄获取到对应的屏幕。随后可以使用此 Screen 类获取各种屏幕信息。
walterlv
2023/10/22
4790
WPF / Windows Forms 检测窗口在哪个屏幕
WPF DataGrid 直接绑定数据
初学WPF 以前用的Winform中的 DatagridView就是直接绑定Datasource 就ok了
zls365
2020/12/15
3.7K0
Windows 10 应用创建模糊背景窗口的三种方法
发布于 2018-07-16 11:44 更新于 2018-08-31 23:59
walterlv
2018/09/18
3K0
Windows 10 应用创建模糊背景窗口的三种方法
C# WPF基础之Timer
。WPF性能跟WinForm没得比,只是可以做出漂亮的界面, , 我推荐几个入门教程吧.。首先WPF常规开发都是用MVVM模式,MVVM的框架这里推荐MVVMLight,直接NuGet安装即可, 下边是推荐的链接 这个是视频教程,如果没权限下载直接百度搜索就能找到免费下载的 https://www.cnblogs.com/prism/archive/2011/12/15/2288309.html 这个是WPF各种布局入门 http://www.cnblogs.com/zhili/p/WPFLayout.html
zls365
2020/08/19
1.1K0
C# WPF基础之Timer
WPF旋转板栈设计一例
项目中需要做一个机台的平面视图,点击其中一个料盒时,弹出该料盒的料管列表,用WPF示例做了一下,效果如下:
DotNet Whisperer
2025/04/13
550
WPF旋转板栈设计一例
WPF 设置 ShowInTaskbar 对窗口最小化的影响
在 WPF 中,如果设置了 ShowInTaskbar 为 False 那么窗口将不会在任务栏显示。此时如果设置窗口最小化,那么窗口将会收起来作为没有任务栏时的显示方法
林德熙
2021/03/23
1.3K0
WPF 设置 ShowInTaskbar 对窗口最小化的影响
.NET CORE(C#) WPF亚克力窗体
使用 .Net Core 3.1 创建名为 “AcrylicWindow” 的WPF模板项目,添加三个Nuget库:MaterialDesignThemes、MaterialDesignColors和FluentWPF,其中亚克力效果是由FluentWPF控件库实现的。
沙漠尽头的狼
2020/01/16
2.3K0
WPF MVVM实例三
WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的,WPF提供了数据绑定机制,当数据发生变化时,WPF会自动发出通知去更新UI。
zls365
2021/02/26
8660
推荐阅读
相关推荐
WPF窗体透明控件不透明实例
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验