有一个简单的WinAPI应用程序.目前所做的一切都是这样的: 注册一个窗口类 使用菜单注册托盘图标 在注册表中创建一个值以自动启动 最后,它使用互斥锁检查它是否是唯一的 由于我习惯
>注册一个窗口类
>使用菜单注册托盘图标
>在注册表中创建一个值以自动启动
>最后,它使用互斥锁检查它是否是唯一的
由于我习惯于主要在C中编写代码,并且不允许使用MFC,因此我不得不以某种方式将其封装到C类中.到目前为止,我已经提出了这样的设计:
>有一个代表应用程序的类
>它保存所有wndclass,hinstance等变量,其中hinstance作为构造函数参数以及icmdshow和其他参数传递(参见WinMain原型)
>它具有注册窗口类,托盘图标,reigstry信息的功能
>它将消息循环封装在一个函数中
在WinMain中,完成以下操作:
Application app(hInstance, szCmdLIne, iCmdShow); return app.exec();
并且构造函数执行以下操作:
registerClass(); registerTray(); registerAutostart();
到现在为止还挺好.现在的问题是:如何创建窗口过程(必须是静态的,因为它是指向函数的c样式指针)并跟踪应用程序对象是什么,即保持指向应用程序的指针.
主要问题是:这通常是怎么做的?我太复杂了吗?将hInstance作为参数传递给Application构造函数是否可以? WndProc在哪里?
也许WndProc应该在课外,应用程序指针应该是全局的?然后WndProc调用Application方法来响应各种事件.
还有一个可能的解决方案:使应用程序类成为单例.然后从WndProc获取该对象的句柄是微不足道的.
答案是SetWindowLongPtr.它允许您将void *与给定的hWnd相关联.然后,在WndProc中,您只需提取所述void *,强制转换并调用成员方法.问题解决方案.使用SetWindowLongPtr有一些起伏,您必须调用其他函数来查看效果或某些BS,并且Windows在CreateWindowEx返回之前发送消息,因此您必须为GetWindowLongPtr(hWnd,GWL_USERDATA)返回NULL做好准备.这当然意味着对于给定的WindowProc,使用它的所有实例都必须具有公共接口,因为使用void *可以做的事情并不多.
并且,是的,将HINSTANCE传递给App构造函数是可以的.我见过的样本做了一些奇怪的事情来避免这种情况,但我从来没有让它成功.
编辑:不要将Get / SetWindowLong与Get / SetWindowLongPtr混淆. Get / SetWindowLong已弃用且不安全.