- 图形学
- 桌面应用
【免费下载链接】RGF_CJ
RGF是仓颉Windows系统下的通用渲染框架(兼应用开发框架)。RGF仓颉版(后续简称"RGF")基于RGF(C/C++版)封装优化而来。RGF为开发者提供轻量化、安全、高性能以及高度一致性的2D渲染能力以及常用的桌面应用开发工具,并且提供对接Direct3D的相关接口,以满足开发者对3D画面渲染的需求。在Windows开发方面,RGF在子包内也提供开箱即用的Windows API,确保熟悉Win32的开发者快速上手。此外,RGF还提供一些常用功能的封装(如XAudio2、MF),以辅助开发者实现音频、摄像头等扩展功能的管理。
导读
本文围绕 RGF(仓颉 Windows 通用渲染框架)事件体系中的EvDropFiles事件参数类展开,深入解析它如何将 Win32 的WM_DROPFILES原始消息包装为类型安全的事件参数,让开发者以面向对象的方式接收"窗口拖放文件"事件。读完本文,你将掌握EvDropFiles的类结构、hDropInfo句柄字段的底层含义,以及它在 RGF 传统事件接口与绑定式事件接口中的两条完整分发链路,并能够写出可直接运行的拖放文件接收窗口代码。
一、事件参数类在 RGF 中的地位
RGF(RGF_CJ)是仓颉系统下的通用渲染框架,其窗口部分在继承 Win32 消息机制的基础上,将每个 Windows 消息封装为独立的"事件参数类"(以Ev前缀命名),并统一定义在rgf.rgf_core包中。EvDropFiles正是这一体系中专用于"窗口拖放文件"场景的参数载体,对应的原始消息为WM_DROPFILES(0x0233)。
在 RGF 中,事件参数类承担两件事:
- 固化消息语义:把
WM_DROPFILES的wParam、lParam原始数值翻译为具有明确含义的字段; - 承载消息上下文:继承自
EvCore,保留原始消息号与参数,供上层事件处理函数安全访问。
二、类定义与继承关系
EvDropFiles的定义位于 src/rgf_core/rgf_proc.cj,源码如下:
/** @brief 窗口拖放文件 - 事件参数 */ public open class EvDropFiles <: EvCore{ public let hDropInfo:CPointer<Unit> public init (wParam:UInt64, lParam:Int64){ super(0x0233/*WM_DROPFILES*/,wParam,lParam) hDropInfo = ruUllToPtr(UIntNative(wParam)) } }- 类名与修饰符:
public open class,说明该参数类对外开放且允许被继承扩展; - 父类:
EvCore(核心事件参数类,见 EvCore.md)。EvCore提供三个只读成员:message: UInt32——窗口消息号;wParam: UInt64——消息附加参数;lParam: Int64——消息附加参数。
- 构造调用链:
EvDropFiles构造函数以0x0233作为uMsg调用super,从而把message字段固化为WM_DROPFILES,同时透传wParam与lParam。
这一设计在源码中大量重复出现:所有Ev*事件参数类在构造时都会携带对应的消息常量(例如EvMDISetMenu对应0x0230、EvMDIDistributed对应0x0226等),保证事件对象"自述身份"。
三、构造函数与参数说明
EvDropFiles公开的构造函数签名与文档一致:
public init(wParam: UInt64, lParam: Int64)| 名称 | 类型 | 描述(来源:Win32 WM_DROPFILES 消息语义 + RGF 源码实现) |
|---|---|---|
| wParam | UInt64 | 指向内部文件列表结构的句柄(HDROP),存放被拖放文件的信息 |
| lParam | Int64 | Win32 规范中保留未使用(源码中未参与任何计算,仅透传给EvCore) |
依据 Win32 的
WM_DROPFILES消息规范:wParam携带一个HDROP句柄,指向描述被拖放文件的结构;lParam保留未用。RGF 源码仅对wParam做了解释,与之一致。
构造函数内部的关键转换是:
hDropInfo = ruUllToPtr(UIntNative(wParam))ruUllToPtr是 RGF 提供的指针工具函数,定义于 src/rgf_core/rgf_api.cj:
public func ruUllToPtr(ptrVal:UIntNative):CPointer<Unit>{ unsafe{ rApiUll2Ptr(ptrVal) } }它的作用是把一个"以无符号整数形式传递的地址值"重新还原为 C 侧指针。这正是窗口过程(WndProc)收到原始消息时参数的表现形式——句柄以整数形式存放于wParam,需要显式还原才能当作指针使用。
四、hDropInfo 字段:HDROP 句柄的封装
EvDropFiles唯一的功能字段是:
public let hDropInfo: CPointer<Unit>- 类型:
CPointer<Unit>,即不透明指针。在 RGF 的 Win32 封装层中,拖放句柄类型被定义为HDROP = CPointer<UNUSED>(见 src/win_def/hshellapi.cj),两者在语义上是同一实体——指向拖放数据结构的不透明句柄; - 用途:
hDropInfo就是 Win32 拖放 API(如DragQueryFile、DragFinish等 Shell API)所要求传入的HDROP句柄。开发者在事件回调中拿到它之后,即可枚举被拖入窗口的文件清单; - 不可变性:字段以
public let声明,事件参数对象一经构造便不可修改,保证回调中读到的是与原始消息一致的快照。
说明:当前仓库的
win_def子包中尚未封装DragQueryFile/DragFinish等 Shell 拖放 API(相关函数在 hshellapi.cj 中暂未提供)。因此从源码结构看,取回具体文件路径需要开发者自行通过外部 FFI 调用 Win32 Shell API,hDropInfo恰好提供了调用所需的句柄。
五、事件分发链路:从 WM_DROPFILES 到 onDropFiles / bindDropFiles
EvDropFiles并不是被开发者直接构造的——它由 RGF 的消息处理管线在收到WM_DROPFILES时自动创建并传入事件回调。仓库中存在两条并行的分发链路:
5.1 传统事件接口:onDropFiles
传统接口IEvent声明了事件方法onDropFiles(e: EvDropFiles): Unit(见 IEvent.md)。其消息分支由宏在编译期自动生成,模板位于 src/rgf_core/macros/rgf_proc_utils.cj:
case ("onDropFiles","EvDropFiles","Unit") => ##" case 0x0233 /*WM_DROPFILES*/ =>{=> let eObj:EvDropFiles = EvDropFiles(wParam,lParam) onDropFiles(eObj) return 0 }"##宏展开后落在窗口过程(WndProc)中,对应 src/rgf_core/rgf_proc.cj:
case 0x0233 /*WM_DROPFILES*/ =>{=> let eObj:EvDropFiles = EvDropFiles(wParam,lParam) onDropFiles(eObj) return (0,eObj.isOverride) }窗口基类提供了onDropFiles的默认空实现(src/rgf_core/rgf_proc.cj),子类按需重写即可。
5.2 绑定式接口:bindDropFiles
绑定式接口IBindEvent则以属性形式暴露回调,声明为mut prop bindDropFiles: Option<(EvDropFiles)->Unit>(见 IBindEvent.md)。对应的消息分支同样由宏生成,见 src/rgf_core/macros/rgf_proc_utils.cj:
case ("bindDropFiles","EvDropFiles","Unit") => ##" case 0x0233 /*WM_DROPFILES*/ =>{=> let eObj:EvDropFiles = EvDropFiles(wParam,lParam) bindDropFiles?(eObj) return 0 }"##展开后位于绑定式分发器中(src/rgf_core/rgf_proc.cj):
case 0x0233 /*WM_DROPFILES*/ =>{=> let eObj:EvDropFiles = EvDropFiles(wParam,lParam) return if(let Some(v) <- bindDropFiles?(eObj)){ 0 }else{ Option<Int64>.None } }其中bindDropFiles属性在 src/rgf_core/rgf_proc.cj 中定义,默认get()返回None(未绑定时忽略该消息),set()抛NoneValueException(rgfFunctionWillIgnored)——即未实现绑定式事件时,传入的函数将被忽略(对应常量说明见 变量与常量.md)。
5.3 完整调用链小结
Shell 拖放文件 → 系统向窗口发送 WM_DROPFILES (0x0233) → RGF WndProc 消息分发表命中 case 0x0233 → 构造 EvDropFiles(wParam, lParam),hDropInfo = wParam 还原为 HDROP → 调用 onDropFiles(e)(传统)或 bindDropFiles?(e)(绑定式) → 回调中通过 e.hDropInfo 枚举被拖放的文件六、实战:在 RGF 窗口中接收文件拖放
下面给出基于绑定式接口的完整使用模式(伪代码风格,展示 API 组合方式,需配合 RGF 窗口创建流程使用):
// 创建窗口后,为窗口绑定文件拖放事件 win.bindDropFiles = Some(|e: EvDropFiles| { // e.hDropInfo 即 HDROP 句柄,可传入外部 FFI 的 // DragQueryFileW / DragFinish 等 Shell API 枚举文件 let hDrop: CPointer<Unit> = e.hDropInfo // 自行通过 win_def 提供的类型(HDROP、CF_HDROP 等)完成文件清单读取 }) // 传统接口方式:在窗口子类中重写事件方法 public open class MyWin <: WinCore { // ...窗口初始化、渲染等代码... override func onDropFiles(e: EvDropFiles): Unit { // 在这里处理拖放进来的文件 let hDrop: CPointer<Unit> = e.hDropInfo } }要真正"接住"拖放,还需要满足两个 Win32 前置条件(均由 RGF 的win_def子包提供常量支持):
- 窗口类样式:注册窗口类时设置
CS_DROPFILES(窗口类样式枚举WinClassStyle中对应项),使窗口具备接收文件拖放的能力; - 扩展窗口样式:为窗口设置
WS_EX_ACCEPTFILES = 0x00000010(常量定义见 src/win_def/hwinuser.cj),声明窗口接受拖放文件。
满足上述条件后,用户在资源管理器中拖拽文件到窗口上释放鼠标左键时,系统即向窗口投递WM_DROPFILES,进而触发 RGF 事件回调。
七、配套的 Win32 常量与类型封装
RGF 在rgf.win_def子包中为文件拖放提供了开箱即用的底层支撑,均可从仓库源码中确认:
| 符号 | 值/类型 | 定义位置 | 用途 |
|---|---|---|---|
WM_DROPFILES | 0x0233 | src/win_def/hwinuser.cj | 拖放文件消息号,EvDropFiles的message字段值 |
WS_EX_ACCEPTFILES | 0x00000010 | src/win_def/hwinuser.cj | 窗口扩展样式,声明接收文件拖放 |
CF_HDROP | 15 | src/win_def/hwinuser.cj | 剪贴板/拖放数据的 HDROP 格式标识 |
HDROP | CPointer<UNUSED> | src/win_def/hshellapi.cj | 拖放句柄类型,与EvDropFiles.hDropInfo语义对应 |
这些封装保证了熟悉 Win32 的开发者可以无缝衔接:拿到hDropInfo后,无论是继续使用 RGF 事件体系,还是直接结合原生 Shell API 处理拖放数据,都有统一的类型基础。
八、使用注意事项
- lParam 不参与业务:
EvDropFiles构造时仅使用wParam生成hDropInfo,lParam只透传给父类EvCore。不要期望从lParam中解析任何拖放信息; - 句柄释放:Win32 规范要求拖放处理结束后调用
DragFinish释放HDROP结构。当前仓库尚未封装该函数,开发者通过外部 FFI 调用时需自行管理释放时机,避免句柄泄漏; - 事件分发二选一:传统
onDropFiles与绑定式bindDropFiles分属IEvent/IBindEvent两套接口体系,实际项目按窗口实现方式选择其一即可,避免重复消费同一消息; - 默认行为:若既不重写
onDropFiles也不绑定bindDropFiles,RGF 对该消息返回0(消息被消费但无任何动作),窗口表现与未接收拖放一致; - 消息语义固化:
EvDropFiles的message恒为0x0233,在多分支消息处理中可直接用于二次校验事件来源。
结语
EvDropFiles是 RGF 将 Win32 原始消息"对象化"的典型样本:短短十几行源码,完成了消息常量固化、参数类型转换与句柄还原,并通过宏驱动的方式接入传统事件与绑定式事件两套分发体系。理解它,也就理解了 RGF 中所有Ev*事件参数类的设计范式——这正是深入使用 RGF 窗口事件体系的关键入口。后续如需扩展拖放能力(如枚举文件、拖放坐标等),只需在hDropInfo基础上对接 Shell 拖放 API 即可。
- 图形学
- 桌面应用
【免费下载链接】RGF_CJ
RGF是仓颉Windows系统下的通用渲染框架(兼应用开发框架)。RGF仓颉版(后续简称"RGF")基于RGF(C/C++版)封装优化而来。RGF为开发者提供轻量化、安全、高性能以及高度一致性的2D渲染能力以及常用的桌面应用开发工具,并且提供对接Direct3D的相关接口,以满足开发者对3D画面渲染的需求。在Windows开发方面,RGF在子包内也提供开箱即用的Windows API,确保熟悉Win32的开发者快速上手。此外,RGF还提供一些常用功能的封装(如XAudio2、MF),以辅助开发者实现音频、摄像头等扩展功能的管理。
相关推荐
RGF 仓颉版窗口点位激活事件:EvPointerActivate 事件参数类深度解析
RGF 仓颉版窗口点位激活事件:EvPointerActivate 事件参数类深度解析 本篇技术指南聚焦 RGF(仓颉版通用渲染框架)核心事件体系中代表 WM_
图形学桌面应用RGF 仓颉版窗口焦点事件:EvSetFocus 事件参数类的源码级解析
RGF 仓颉版窗口焦点事件:EvSetFocus 事件参数类的源码级解析 EvSetFocus 是 RGF 仓颉版(RGF_CJ)中封装 Win32 WM_SE
图形学桌面应用RGF 仓颉版窗口事件详解:EvSetCursor 事件参数类与 WM_SETCURSOR 光标处理机制
RGF 仓颉版窗口事件详解:EvSetCursor 事件参数类与 WM_SETCURSOR 光标处理机制 本文围绕 RGF 仓颉版(RGF_CJ) rgf.rg
图形学桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考