窗口子类化如何防止冲突
子类化是用GetWindowLong和SetWindowLong这两个API来对已经创建的窗口的窗口过程地址进行修改,用自己的窗口过程的新地址代替原来的,然后在自己写的新地址里过滤掉自己感兴趣的消息,一般我们是把自己不处理的消息再用原来的窗口函数调用,以实现我们对某一个窗口的特性的小修改要求,一般把子类化用在控件上,但也可以用在任意类型的窗口上.
以VB代码为例:
1、首先在form_load事件中拦截发送到所有form的消息,发送到自编回调函数NewWindowProc的地址。注意不同API函数及常量均要进行申明。
OldWindowProc = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf NewWindowProc)
RegisterHotKey Me.hwnd, 1, MOD_ALT, vbKeyN '装载时注册热键
2、在自编回调函数NewWindowProc中对感兴趣的消息进行相关处理。
这里建议拦截句柄为hwnd控件的所有消息建议放在一个回调函数中,根据消息编号msg和消息附带的高位参数wparam的不同进行相关处理。
如果放在不同的回调函数中,就有可能会引起冲突。
Public Function NewWindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim mx As Integer
If Msg = TRAY_CALLBACK Then '如果用户点击了托盘中的图标,则进行判断是点击了左键还是右键
If lParam = WM_LBUTTONUP Then '如果点击了托盘左键
TheForm.Visible = Not TheForm.Visible '单击一次就隐藏
ElseIf lParam = WM_RBUTTONUP Then '如果点击了托盘右键
TheForm.PopupMenu TheMenu '则弹出右键菜单
Exit Function
End If
End If
If Msg = WM_HOTKEY Then '如果是热键消息
If wParam = 1 Then
'如果是本程序定义的(系统消息中的wParam参数在热键消息中代表热键标示符,是在RegisterHotKey注册热键的时候定义的一个整数,如果热键是系统定义的,则标示符取值为-1或-2,详见开头
frm_Main.Visible = Not frm_Main.Visible ' 热键对应上了之后就调用指定的过程
'这样,运行之后,反复按Alt + N 就可以实现窗口的隐藏与显示
Exit Function '消息已处理,不需要发回窗口
End If
End If
NewWindowProc = CallWindowProc(OldWindowProc, hwnd, Msg, wParam, lParam) '如果是其他类型的消息则传递给原有默认的窗口函数
End Function
3、Form_Unload事件中释放资源。
SetWindowLong Me.hwnd, GWL_WNDPROC, OldWindowProc '将窗口过程地址还原
UnregisterHotKey Me.hwnd, 1 '释放热键供其它应用程序使用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫