包装PropertySheet;如何处理回调?

时间:2009-12-14 19:51:12

标签: c++ winapi callback wrapper propertysheet

我正在编写一个(非托管的)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中所示。但是属性表不提供此功能。

此外,因为属性表是以模态显示的,所以我不能在创建和销毁实际窗口之间执行任何代码,除非通过回调或其中一个工作表的窗口过程执行该代码。

到目前为止,我提出的最佳解决方案是在显示属性表之前,在全局变量中存储指向包装类的指针。但这假设我一次只会展示一张属性表,而且无论如何都非常难看。

有没有人更好地了解如何解决这个问题?

5 个答案:

答案 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