有没有办法创建一个优雅的类成员窗口函数?
Win32 API 中的窗口过程必须是静态\全局函数,因为它不能采用类对象(this
)参数。当然可以使用诸如 hWnd->object 字典之类的解决方法。
我想知道 D 是否有一种方法可以优雅地解决这个问题,例如为每个对象创建一个微小的成员函数副本(以调用对象的真实处理程序)或我可以分配给 WNDCLASS 的匿名函数。 lpfnWndProc (我知道有匿名函数,但我不能在它们上使用 extern(Windows)
属性)?
我可以做这样的事情吗:(
class Window {
extern (Windows)
LRESULT delegate (HWND hWnd, UINT msg, WPARAM w, LPARAM l) MyWinProcDelegate;
this() {
MyWinProcDelegate = &Events;
}
extern (Windows)
LRESULT Events (HWND hWnd, UINT msg, WPARAM w, LPARAM l) {
MessageBoxA(null , "Success!!!" , null ,0);
return DefWindowProcA(hWnd, message, wParam, lParam);
}
}
省略注册\创建\消息循环...)
Events() 似乎没有触发...我错过了什么吗?
The Window-Procedure in the Win32 API must be static \ global function since it cannot take a class-object (the this
) parameter. One can of-course use workarounds like a hWnd->object dictionary and such.
I wonder if D has a way to elegantly solve it, like create a tiny member function copy for each object (to call the object's real handler) or anonymous function that I can assign to WNDCLASS.lpfnWndProc
(I know there are anonymous functions, but I cannot use the extern(Windows)
property on them) ?
Can I do something like this :
class Window {
extern (Windows)
LRESULT delegate (HWND hWnd, UINT msg, WPARAM w, LPARAM l) MyWinProcDelegate;
this() {
MyWinProcDelegate = &Events;
}
extern (Windows)
LRESULT Events (HWND hWnd, UINT msg, WPARAM w, LPARAM l) {
MessageBoxA(null , "Success!!!" , null ,0);
return DefWindowProcA(hWnd, message, wParam, lParam);
}
}
(Omitting the registration\creation\msg-loop...)
The Events() doesn't seem to fire... am I missing something ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我在这里为您做了这个(基于 BCS 的答案):
在 Windows 32 位和 Linux 64 位上测试。
Here I made this for you (based on BCS' answer):
Tested on Windows 32-bit and Linux 64-bit.
如何将
this
存储在窗口本身中,使用 SetWindowLong?How about storing
this
in the window itself, with SetWindowLong?一种非常不可移植的解决方案是动态创建一个包装调用的函数。我会通过编写一个如下所示的函数来做到这一点:
然后您可以将此函数编译为未优化的 PIC,反编译它,找到一个可以混搭成你需要的字节序列。最终结果将是一个类型(可能是一个结构体),它有一个返回函数指针的方法,并且在构造时,用您在上述步骤中找到的字节填充内部
void
数组,并戳出将有问题的对象放入适当的位置。稍微更高级的解决方案将使用对象和方法指针填充委托,以便两者都可以提供给构造函数。更高级的解决方案将模板化类型并利用 C 和 D 调用约定的知识来动态生成参数转发代码。
One very un-portable solution would be to dynamically create a function that wraps the call. I would do this by writing a function that looks like this:
You can then compile this function as un-optimized PIC, de-compile it, and find a byte sequence that can be mashed into what you need. The end result would be a type (likely a struct) that has a methoud returning a function pointer and that, when constructed, populates an internal
void
array with the bytes you found from the above step and pokes the object in question into the appropriate places.A slightly more advanced solution would populate a delegate with both the object and the method pointer so both can be provided to the constructor. An even more advanced solution would template the type and take advantage of knowledge of the C and D calling conventions to dynamically generate the argument forwarding code.