☰
RGF_CJ 手势触控通知事件参数 EvGestureNotify 详解:从 WM_GESTURENOTIFY 消息到手势配置
2026/10/15 15:45:20 网站建设 项目流程
  • 图形学
  • 桌面应用

【免费下载链接】RGF_CJ

RGF是仓颉Windows系统下的通用渲染框架(兼应用开发框架)。RGF仓颉版(后续简称"RGF")基于RGF(C/C++版)封装优化而来。RGF为开发者提供轻量化、安全、高性能以及高度一致性的2D渲染能力以及常用的桌面应用开发工具,并且提供对接Direct3D的相关接口,以满足开发者对3D画面渲染的需求。在Windows开发方面,RGF在子包内也提供开箱即用的Windows API,确保熟悉Win32的开发者快速上手。此外,RGF还提供一些常用功能的封装(如XAudio2、MF),以辅助开发者实现音频、摄像头等扩展功能的管理。

项目地址:https://gitcode.com/Cangjie-SIG/RGF_CJ
点击查看免费下载

导读

EvGestureNotify是仓颉版通用渲染框架 RGF(RGF_CJ)在rgf_core子包中提供的手势触控通知事件参数类,对应 Windows 消息WM_GESTURENOTIFY(0x011A)。本文围绕 EvGestureNotify 文档 展开,结合 rgf_proc.cj 中该类 59 行的完整实现,剖析其从 Win32 结构体GESTURENOTIFYSTRUCT到仓颉事件对象的解析映射过程、可写回的手势配置字段,以及继承式与绑定式两种事件接入方式。读完本文,你将能在 RGF 窗口中接收手势通知、读取触控目标与位置信息,并通过postProcess()回写手势配置。

EvGestureNotify 的定位:手势发生前的配置通知

在 RGF 的窗口消息事件体系中,EvGestureNotify与EvGesture成对出现,分别对应两条相邻的 Windows 消息:

事件参数类Windows 消息消息值语义
EvGestureWM_GESTURE0x0119手势触发,实际的手势动作发生
EvGestureNotifyWM_GESTURENOTIFY0x011A手势触控通知,在手势处理前通知窗口,可借此设置手势配置

该对应关系在 rgf_proc.cj 的消息分发表中可直接验证。两条分支的注释分别为"手势触发"与"本消息可设置手势配置",后者正是EvGestureNotify的核心用途。在 rgf_core 的 readme 的事件参数类索引中,两者同样被相邻列出。

public open class EvGestureNotify <: EvCore

EvGestureNotify继承自 EvCore(核心事件参数基类),因此自动拥有message、wParam、lParam三个只读字段,分别保存原始消息号、消息参数与扩展参数,可用于与原始 Win32 消息对照调试。

五个可读可写成员:与 GESTURENOTIFYSTRUCT 的一一映射

EvGestureNotify公开了 5 个var(可变)成员,完整覆盖了 Win32 结构体tagGESTURENOTIFYSTRUCT的全部字段。结构体定义位于 hwinuser.cj,对应的文档见 tagGESTURENOTIFYSTRUCT:

EvGestureNotify 成员类型对应结构体字段Win32 类型含义(基于源码注释与字段命名)
cbSizeUInt32cbSizeUINT结构体大小,用于标识结构版本
dwFlagsUInt32dwFlagsDWORD手势标志,可写回以控制手势行为
hwndTargetRgfHwndhwndTargetHWND手势目标窗口句柄
ptsLocationPointptsLocationPOINTS手势发生位置(RGF 以Point封装)
dwInstanceIDUInt32dwInstanceIDDWORD手势实例标识,用于关联连续的手势

其中hwndTarget使用了 RGF 的窗口句柄类型RgfHwnd,而ptsLocation使用 Point 位置类封装,这两个类型均是 RGF 对 Win32 原生类型的统一包装,体现了"开箱即用的 Windows API"设计思路:开发者操作的是仓颉类型,底层则直接对接系统结构体。

init(wParam, lParam):底层结构体的解析过程

@OverflowWrapping public init(wParam: UInt64, lParam: Int64)

构造函数接收与消息一起到达的wParam、lParam两个原生参数。@OverflowWrapping标注表明其内部涉及整型与指针之间的位宽换算,采用回绕语义避免溢出检查的开销。

从 rgf_proc.cj 的实现可以看到完整的三步解析:

  1. 基类初始化:调用super(0x011A /*WM_GESTURENOTIFY*/, wParam, lParam),把消息号、原始参数存入EvCore;
  2. 指针转换:ptr = CPointer<GESTURENOTIFYSTRUCT>(ruUllToPtr(ruInt64SafeToUIntNative(lParam)))——将lParam安全转换为无符号原生整数,再转为指向GESTURENOTIFYSTRUCT的指针。在 Win32 中,WM_GESTURENOTIFY的lParam正是指向该结构体的指针;
  3. 内存读取与字段拷贝:Obj = unsafe{ ptr.read() }一次性读取结构体,随后逐字段赋值,其中位置坐标ptsLocation从原生POINTS(Int16坐标)转换为Point(Int32(...), Int32(...))。

可以看到,EvGestureNotify本质上是一个"内存视图 + 安全包装":原始结构体同时以内部指针ptr和值副本Obj保留,公开成员只是这些内部状态的投影。

postProcess():把修改写回系统,完成手势配置

@OverflowWrapping public func postProcess()

postProcess()是EvGestureNotify区别于大多数只读事件参数类的关键方法,其实现位于 rgf_proc.cj。它执行init的逆过程:

  1. 将 5 个公开成员逐一写回内部副本Obj(hwndTarget通过ruToHwnd从RgfHwnd还原为HWND,ptsLocation的Int32坐标截断回Int16写入POINTS);
  2. unsafe{ ptr.write(Obj) }将修改后的结构体整体写回lParam指向的原生内存。

也就是说,开发者可以在回调中修改dwFlags、hwndTarget、ptsLocation、dwInstanceID等字段,再调用postProcess(),让修改真正作用于系统手势管线——这正是源码注释"本消息可设置手势配置"的具体实现方式。

两种接入方式:继承回调与事件绑定

与 RGF 所有窗口事件一致,EvGestureNotify支持两种接入范式,两者的消息分发代码均由宏在 rgf_proc_utils.cj 中生成(继承式生成点、绑定式生成点)。

方式一:继承窗口类并覆写 onGestureNotify

在 rgf_proc.cj 中定义了默认实现,覆写它即可接收通知:

// @brief 本消息可设置手势配置 func onGestureNotify(e: EvGestureNotify): Unit { e.isOverride = false }

消息到达时,分发逻辑构造EvGestureNotify(wParam, lParam)后调用onGestureNotify(eObj),随后以return (0, false)结束——源码在此处特别注释"本消息始终应该从 DefWindowProc 返回值",即不覆写系统对该消息的默认处理结果。

方式二:通过 bindGestureNotify 绑定事件函数

IBindEvent事件绑定式分发接口在 IBindEvent.md 中声明了该属性,其实现位于 rgf_proc.cj:

// @brief 本消息可设置手势配置 mut prop bindGestureNotify: Option<(EvGestureNotify) -> Unit> { get() { None } set(v) { throw NoneValueException(rgfFunctionWillIgnored) } }
case 0x011A /*WM_GESTURENOTIFY*/ => { let eObj: EvGestureNotify = EvGestureNotify(wParam, lParam) bindGestureNotify?(eObj) return Option<Int64>.None // 本消息始终应该从 DefWindowProc 返回值 }

绑定方式下,回调被调用后分发器直接返回None,同样将最终处理权交还DefWindowProc。两种方式都遵循"手势通知不拦截、仅配置"的原则。

与 EvGesture 协同:一次完整的手势处理流程

结合两条消息的分发代码(rgf_proc.cj),一次典型的手势交互在 RGF 中会经历两个阶段:

  1. 通知阶段(WM_GESTURENOTIFY / 0x011A):系统在识别手势前先通知窗口。此时EvGestureNotify携带目标窗口hwndTarget、手势位置ptsLocation与实例标识dwInstanceID,应用可修改字段并调用postProcess()调整后续手势识别行为;
  2. 触发阶段(WM_GESTURE / 0x0119):手势正式发生,EvGesture事件参数携带原始参数arguments与信息句柄handle(见 EvGesture 文档),应用在此完成手势的实际响应与绘制。

应用可以同时覆写onGestureNotify与onGesture(或同时绑定bindGestureNotify与bindGesture),在通知阶段做配置、在触发阶段做响应,形成完整的手势交互闭环。

实践要点小结

  • 消息号识别:EvGestureNotify.message固定为0x011A,可据此在通用事件处理中区分手势通知;
  • 坐标注意:ptsLocation在内部经过POINTS(Int16)到Point(Int32)的转换,读取时无需再处理原生坐标类型;写回时超出Int16范围的坐标会被截断,配置坐标时应注意窗口尺寸限制;
  • 写回时机:只有在postProcess()被调用后,对成员字段的修改才会写入系统结构体,只读观察场景不必调用;
  • 返回值约定:无论继承式还是绑定式,WM_GESTURENOTIFY都应放行给DefWindowProc处理,不要返回自定义值拦截消息。

如需继续深入,可对比阅读 EvGesture.md 了解手势触发阶段的事件参数,或查阅 IBindEvent.md 查看全部绑定式事件属性。

  • 图形学
  • 桌面应用

【免费下载链接】RGF_CJ

RGF是仓颉Windows系统下的通用渲染框架(兼应用开发框架)。RGF仓颉版(后续简称"RGF")基于RGF(C/C++版)封装优化而来。RGF为开发者提供轻量化、安全、高性能以及高度一致性的2D渲染能力以及常用的桌面应用开发工具,并且提供对接Direct3D的相关接口,以满足开发者对3D画面渲染的需求。在Windows开发方面,RGF在子包内也提供开箱即用的Windows API,确保熟悉Win32的开发者快速上手。此外,RGF还提供一些常用功能的封装(如XAudio2、MF),以辅助开发者实现音频、摄像头等扩展功能的管理。

项目地址:https://gitcode.com/Cangjie-SIG/RGF_CJ
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询