我正在编写一个(非托管的)C ++类来包装Windows PropertySheet
。基本上,这样的事情:
class PropSheet {
PROPSHEETHEADER d_header;
public:
PropSheet(/* parameters */);
INT_PTR show();
private:
static int CALLBACK *propSheetProc(HWND hwnd, UINT msg, LPARAM lParam);
};
构造函数只是初始化d_header
成员:
PropSheet::PropSheet(/* parameters */) {
d_header.dwSize = sizeof(PROPSHEETHEADER);
d_header.dwFlags = PSH_USECALLBACK;
// ...
d_header.pfnCallback = &propSheetProc;
// ...
}
之后我可以用模式显示它:
INT_PTR PropSheet::show() {
return PropertySheet(&d_header);
}
现在的问题是,因为回调是静态的,所以它无法访问包装类。如果这是一个普通窗口,使用WindowProc
而不是PropSheetProc
,我可以使用WNDCLASS
中的cbWndExtra
将一些额外数据附加到窗口中,我可以在其中存储返回包装器的指针,如this article中所示。但是属性表不提供此功能。
此外,因为属性表是以模态显示的,所以我不能在创建和销毁实际窗口之间执行任何代码,除非通过回调或其中一个工作表的窗口过程执行该代码。
到目前为止,我提出的最佳解决方案是在显示属性表之前,在全局变量中存储指向包装类的指针。但这假设我一次只会展示一张属性表,而且无论如何都非常难看。
有没有人更好地了解如何解决这个问题?
答案 0 :(得分:1)
当您以模态方式显示属性表时,您应该能够使用::GetParent()
参数上的hwndDlg
将属性表的父窗口(即其句柄)映射到实例PropSheetProc()
。
答案 1 :(得分:0)
非常棒,另一个使用回调而没有用户定义的上下文参数的Win32 API。它不是唯一的,唉。例如CreateWindow很糟糕(它为您提供了用户定义的上下文,但前几个窗口消息不能使用该上下文),SetWindowsHookEx更糟糕(根本没有上下文)。
通用且有效的唯一“解决方案”是使用硬编码的“this”指针发出一小段可执行代码。这样的事情:http://episteme.arstechnica.com/eve/forums/a/tpc/f/6330927813/m/848000817831?r=848000817831#848000817831
太可怕了。
答案 2 :(得分:0)
PROPSHEETPAGE结构有一个可用于回调的lParam字段。在PROPSHEETHEADER中,您可以包含PSH_PROPSHEETPAGE标志以传递描述您的页面的PROPSHEETPAGE项目数组,或者省略该标志以传递一组预分配的HPROPSHEETPAGE句柄(这意味着使用CreatePropertySheetPage(),因此无论如何都使用PROPSHEETPAGE)。 / p>
答案 3 :(得分:0)
您已经承认“我可以在创建和销毁实际窗口之间不执行任何代码”。似乎全局变量不会是一个可怕的黑客。
答案 4 :(得分:0)
我找到了另一个选项:使用SetProp
添加一个存储指向包装器的指针的属性。只需要一次全局变量,就可以从属性表回调中调用SetProp
。