TDS文件搜索_Winform版本与avalonia开发差异比较:(一)系统消息的接收与无标题栏/边框窗体的移动与尺寸调整

news/2025/9/27 0:27:45/文章来源:https://www.cnblogs.com/luojin765/p/19114611

TDS文件搜索_Winform版本与avalonia开发差异比较:(一)系统消息的接收与无标题栏/边框窗体的移动与尺寸调整

一、Winform和Avalonia的选择

收到私信,有看过上一篇的朋友说想了解Winform相关内容,感谢建议,因为因此稍作回忆后就想稍作一些记录和对比。
最早的时候TDS文件搜索这款工具是用Winform实现的,最早版本是4.72的Winform,后来变成了net8。当时有想过改WPF,但一直感觉必要性不大。直到后来net8开始尝试了avalonia,才觉得有了些必要对界面及一些逻辑进行了重写。
个人看来,Winform开发速度快,UI资源占用少,界面响应也快,而且本身的开发框架与windows系统功能兼容性很高,不少效果都能通过黑科技般的操作实现。
为了追求高画质/自由度,可能不得不用Avalonia UI,这时很多习惯了的处理都需要重新找解决方案。尽管Avalonia类似WPF,但很多语法细节差异还较大,学习资料相对较少,如果没有ai辅助,刚入门甚至会有无从下手的感觉。而且Avalonia开发要从sdk开始安装,开发界面也没法直观拖拉拽调试,开发热更新需要适应。

AVALONIA WINFORM

尽管用了Avalonia,但对Winform还是很喜欢的,给了很多C#程序员一开始写代码的动力,也是快速测试想法的首要选择。因此呢,这里我把一些在tds这个软件中winform和avalonia相关实现的差异和走过的坑简单分享一下。Winform版本的代码也全部开源推送仓库了(关注公众号发送tds消息自取)。如果有仍在用Winform想实现特殊效果的,或者有想尝试下Avalonia的可以参考。我们将分为五个TDS开发过程中的实例,对Windows操作系统上的Winform和Avalonia两者实现相同的功能进行对比,分别是:

  • 系统消息接收
  • 无标题栏/边框窗体的窗体移动
  • 无标题栏/边框下的窗体尺寸改变

二、系统消息接收

在windows操作系统下,响应系统级别快捷键响应最高效的实现自然是RegisterHotKey。当程序注册成功一个热键后,用户按下了热键,操作系统会向你的程序窗体局部发送一个标准的系统消息。注册热键直接调用系统api就可以了,但是如何拿到消息呢?

        [System.Runtime.InteropServices.DllImport("user32.dll")]public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint keyValue, Keys vk);
2.1 Winform的消息循环

Winform拿到消息很简单,在Form类下面重写WndProc函数即可,通过判定Message的值即可实现响应功能的触发。这个函数是不断触发的,他不光处理按键,还处理其他各种各样的消息,因此写功能的时候一定要考虑到代码的执行效率。

protected override void WndProc(ref Message m)
{switch (m.Msg){case 0x0312:switch (m.WParam.ToString())  //处理热键消息id{case "8617":autoshoworhide(); //窗口隐藏或显现break;}base.WndProc(ref m);break;// ....其他消息的处理default:base.WndProc(ref m);break;}
}
2.2 Avalonia的消息循环

Avalonia中,一开始尝试过用非阻塞式系统索API函数 PeekMessage,尽管同样能拿到系统消息,但由于各种原因,总是会出现丢消息以及界面卡顿的情况。知道后来发现了可通过Avalonia.Controls下面的Win32Properties.AddWndProcHookCallback函数。Win32Properties.AddWndProcHookCallback(this, WndProc),需要将本窗体对象(Avalonia.controls.Window)也就是this,和回调函数WndProc传入,即可像Winform一样流畅处理系统消息了。

private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{// If not a hotkey message or the global hotkey for showing the windowif ((int)wParam == GlobalHotkey.HotKeyId){AutoShowOrHide();}// ....其他消息的处理return IntPtr.Zero;
}

三、无标题栏/边框窗体的窗体移动

无界面下,没有标题栏了,那么窗体的移动需要通过鼠标与控件的交互来实现。比如说点击控件后窗体跟着鼠标移动,被鼠标拖拽等。可能大家会觉得这个实现很难,需要计算各种鼠标与窗口位置,控制边界等...
Wait wait... 如果不亲自试一试的话永远也不会知道真正做起来有多简单。

3.1 Winform的欺骗

在Winform下的实现只需在某个控件的mouseDown事件中加入2行代码即可。他的原理其实是欺骗Windows,告诉操作系统你鼠标点击的是程序的标题栏,然后程序就可以像拖拽标题栏一样随鼠标移动了

      public const int WM_SYSCOMMAND = 0x0112;public const int SC_MOVE = 0xF010;public const int HTCAPTION = 0x0002;    //标题栏, 其他对应的功能取值可参考 https://learn.microsoft.com/zh-cn/windows/win32/inputdev/wm-nchittest[DllImport("user32.dll")]public static extern bool ReleaseCapture();[DllImport("user32.dll")]public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);private void Keywords_MouseDown(object sender, MouseEventArgs e) //某个控件的鼠标按下事件{//移动窗体ReleaseCapture();SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);}
3.2 Avalonia实现

可能是为了适配触控操作,Avalonia无界面移动实现更简单,在控件的PointerPressedEvent事件下直接调用自带方法this.BeginMoveDrag, 将PointerPressedEventArgs传入即可完成与Winform一样的效果。

 private void Keywords_MouseDown(object sender, PointerPressedEventArgs e){this.BeginMoveDrag(e);}

四、无标题栏/边框下的窗体尺寸改变

这个实现主要是考虑Winform窗体,设置FormBorderStyle为None,当标题栏消失时,往往边框也消失了,边框移动也没有了。

4.1 Winform的再次欺骗

仍然是在操作系统消息的处理循环中,通过改写 WM_NCHITTEST 消息 (0x0084),欺骗系统鼠标在窗体的哪个区域,并触发操作系统默认的机制。

// 下面的常量是为了模拟有标题栏窗体时,触发调整尺寸的上下左右四条边和四个角的状态标识const int HTLEFT = 10;const int HTRIGHT = 11;const int HTTOP = 12;const int HTTOPLEFT = 13;const int HTTOPRIGHT = 14;const int HTBOTTOM = 15;const int HTBOTTOMLEFT = 0x10;const int HTBOTTOMRIGHT = 17;protected override void WndProc(ref Message m){switch (m.Msg){case 0x0084:  // WM_NCHITTESTbase.WndProc(ref m);  // 默认消息不干扰Point vPoint = new Point((int)m.LParam & 0xFFFF,(int)m.LParam >> 16 & 0xFFFF);vPoint = PointToClient(vPoint);if (vPoint.X <= 5)      //计算容差然后触发,后面类似...if (vPoint.Y <= 5)m.Result = (IntPtr)HTTOPLEFT;else if (vPoint.Y >= ClientSize.Height - 5)m.Result = (IntPtr)HTBOTTOMLEFT;elsem.Result = (IntPtr)HTLEFT;else if (vPoint.X >= ClientSize.Width - 5)if (vPoint.Y <= 5)m.Result = (IntPtr)HTTOPRIGHT;else if (vPoint.Y >= ClientSize.Height - 5)m.Result = (IntPtr)HTBOTTOMRIGHT;elsem.Result = (IntPtr)HTRIGHT;else if (vPoint.Y <= 5)m.Result = (IntPtr)HTTOP;else if (vPoint.Y >= ClientSize.Height - 5)m.Result = (IntPtr)HTBOTTOM;break;default:base.WndProc(ref m);break;}}
4.2 Avalonia实现

直接在xml中配置,将以下三个参数添加到已有的配置中即可。

<Window ExtendClientAreaToDecorationsHint="True"ExtendClientAreaChromeHints="NoChrome"ExtendClientAreaTitleBarHeightHint="-1"
>

五、最后

其实Winform也挺好的,那种开箱即用(急用)的感觉,拖几个按钮双击进去直接开干的痛快,毕竟陪伴了我们这么久,也忘不了刚学习编程时看到自己的界面出现后那种激动人心的感受。

感谢您的耐心阅读,希望各位从零开始的新朋友和老朋友有所收获!如果你对这篇文章的内容有任何建议或想法,欢迎随时交流!本文中TDS文件搜索工具的Winform版本已在仓库完全开源了!点个 Star ⭐️支持一下!代码仓库地址 不清楚的请关注微信公众号“萤火初芒",发送消息 “TDS”即可查看!

QR

下期预告:

“TDS文件搜索_Winform版本与avalonia开发差异比较:(二)列表虚拟化以及系统文件图标ico动态获取与绑定”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/918942.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

台州网站制作维护规范门户网站的建设和管理办法

说明&#xff1a; 1&#xff09;访问应用业务&#xff0c;读取不到数据&#xff0c;show databases;查看数据库报错 2&#xff09;重启docker服务&#xff0c;服务启动失败&#xff0c;查看日志报错如下图所示 3&#xff09;报错信息&#xff1a;chmod /data/docker: read-only…

宜昌做网站优化万网ip查询

一、 在终端输入 sudo apt-get install openssh-server 二、 执行如下命令 sudo apt-get install ssh 三、 开启 ssh-server&#xff0c;输入密码 service ssh start 四、 验证&#xff0c;输入 ps -e|grep ssh&#xff0c;看到sshd成功 ps -e|grep ssh五、 连接

手机版网站开发网站运行时错误如何做

1、代码如下&#xff1a; close all;clear all;clc; %关闭所有图形窗口&#xff0c;清除工作空间所有变量&#xff0c;清空命令行 Iimread(pout.tif); Jimadjust(I,[0.2 0.5],[0 1]);%将0.2-0.5之间的灰度扩展到整个0-1范围&#xff0c;这种处理 对于强调感兴趣灰度区非常有用…

wordpress 站标不显示wordpress 手机登陆

返回目录&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV 环境变量参考 下一篇&#xff1a;将OpenCV与gcc和CMake结合使用 引言&#xff1a; OpenCV是一个开源的计算机视觉库&#xff0c;由英特尔公司所赞助。它是一个跨…

学做彩票网站win7 iis 默认网站

​​​​​​ 与存储标量数据(如整数、字符串等)的传统数据库不同,矢量数据库旨在有效地存储和检索矢量数据——表示多维空间中的点的数值集合。 本文将探讨如何在 Rust 中实现基本的向量数据库。 让我们开始吧!🦀 什么是矢量数据库? 矢量数据库是一种针对存储和查询…

单人网站制作关键词搜索站长工具

PHP 做网页后端还是很优秀的&#xff0c;PHP 表单提交&#xff0c;不外乎两种方法&#xff0c;即 GET 和 POST 方法&#xff1b;PHP后台使用全局变量$_POST;$_GET;来获取提交数据。代码&#xff1a;<!DOCTYPE HTML> <html> <head><meta charset"utf-…

梦织网站如何用wordpress快速建站

使用 fake-as 可以将本地真实的 AS 编号隐藏&#xff0c;其他 AS 内的对等体在指定本端对等体所在的AS 编号时&#xff0c;应该设置成这个伪AS 编号。 这是实验拓扑&#xff0c;IBGP EBGP 邻居都使用物理接口来建立 基本配置&#xff1a; R1: sys sysname R1 int loo0 ip add…

js源码下载从哪个网站能下载建设部门户网站条例免费下载

【stm32】I2C通信协议 概念及原理 如果我们想要读写寄存器来控制硬件电路&#xff0c;就至少需要定义两个字节数据 一个字节是我们要读写哪个寄存器&#xff0c;也就是指定寄存器的地址 另一个字节就是这个地址下存储寄存器的内容 写入内容就是控制电路&#xff0c;读出内容就…

网站更新前知道内容岳阳网站平台设计

文章目录 前言SMTPPOP3IMAP4区别与联系 前言 常见的邮件协议包括SMTP、POP3和IMAP4。这些协议都隶属于TCP/IP协议簇&#xff0c;属于应用层&#xff0c;分别通过TCP端口25、110和143建立连接。电子邮件的发送和接收过程依赖于这些协议。 SMTP &#xff08;Simple Mail Trans…

东莞seo网站优化方式深圳网站快速备案

关于类似的帖子好像很多&#xff0c;但是没有找到具体能帮我解决问题的办法。还是自己深究了好久才基本知道app上面的xpath定位和web上的不同点&#xff1a; 先放一个图&#xff1a; A&#xff0c;先说说不用xpath的场景&#xff0c;一般是用于存在id或者name。可能没有看到na…

网站开发是先做前段还是后台简单电子商务网站建设

大家好&#xff0c;我是专注家居和装修知识分享的家居杂坛。喜欢的就点击一下关注吧&#xff01;对于在地面上所浇筑的混凝土&#xff0c;常规有两种做法。例如&#xff0c;在混凝土中铺设钢筋&#xff0c;打成钢筋混凝土的地面&#xff0c;又或者还有一些朋友在钢混凝土中放入…

php网站开发作业网站中高端建设

1、hibernate 要求实体类里面有一个属性作为唯一值&#xff0c;对应的表字段是主键&#xff0c;主键可以不同的生成策略 2、hibernate 主键生成策略有很多的值 <generator class"native"></generator> 3、在class属性里面有很多值 &#xff08;1&#xf…

docker复制文件到宿主机

要将 Nacos 容器内的文件复制到宿主机,可以使用 docker cp 命令,该命令支持在容器和宿主机之间复制文件或目录。以下是具体操作步骤: 一、基本语法 # 将容器内的文件/目录复制到宿主机 docker cp <容器名或容器I…

【SimpleFOC】SimpleFOC的运动规划器(Motion Planner)和梯形速度规划

SimpleFOC 在位置(角度)模式时,达到目标位置过程中,是默认开启平滑转动的效果的。 SimpleFOC 的平滑转动是通过运动规划器(Motion Planner)实现的,而不是瞬间跳到目标位置。 运动规划器的工作原理 1. 默认的梯形速…

南昌企业做网站产品单页营销型网站模板

指系统能按某种顺序如&#xff08;P1&#xff0c;P2&#xff0c;...&#xff0c;Pn&#xff09;&#xff0c;来为每个进程分配所需要的资源&#xff0c;直至最大需求&#xff0c;使每个进程都可以顺序完成。若系统不存在这样一个安全序列&#xff0c;则称系统处于不安全状态。

深圳入户申请网站官网永春网站设计

如果你准备发NLP方向的论文&#xff0c;或准备从事科研工作或已在企业中担任NLP算法岗的工作。那么我真诚的向大家推荐&#xff0c;贪心学院《自然语言处理高阶研修班》&#xff0c;目前全网上应该找不到类似体系化的课程。课程精选了四大主题进行深入的剖析讲解&#xff0c;四…

网站建设的线框图叫什么dw网页制作教程视频简单第三期

前言 小羊近期已经将C语言初阶学习内容与铁汁们分享完成&#xff0c;接下来小羊会继续追更C语言进阶相关知识&#xff0c;小伙伴们坐好板凳&#xff0c;拿起笔开始上课啦~ 一、数据类型的介绍 我们目前已经学了基本的内置类型&#xff1a; char //字符数据类型 short …

Day22多态详解

多态是面向对象的重要特性,在java中表现为父类引用指向子类对象 Father f1 = new Son(); 多态是方法的多态,与属性无关 父类与子类之间需要有联系,否则类型转换异常,即ClassCastException 多态的存在条件是两个类之…

rad/s RPM之间的换算

SimpleFOC中,经常用到如下代码motor.velocity_limit = 1.0; // 限制最大速度其中 ,velocity_limit单位为 rad/s, 其与 rpm换算关系是什么呢?// 速度单位换算参考: // 1 rad/s = 9.55 RPM // 2 rad/s ≈ 19 RPM //…

四川建设行业数据共享平台网站问题旅游网页设计论文5000字

接地作为一种应用最为广泛的电气安全措施&#xff0c;是指电力系统和电气装置的中性点、电气设备的外露导电部分和装置外导电部分经由导体与大地相连。接地的作用主要是防止人身遭受电击、设备和线路遭受损坏、预防火灾和防止雷击、防止静电损害和保障电力系统正常运行。按其功…