2

我正在编写一个(非托管)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);
}

现在的问题是,因为回调是静态的,所以它不能访问包装类。如果这是一个普通窗口,使用 aWindowProc而不是 a ,我可以使用inPropSheetProc将一些额外的数据附加到窗口,我可以在其中存储一个指向包装器的指针,就像在这篇文章中一样。但属性表不提供此功能。cbWndExtraWNDCLASS

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

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

有谁知道如何解决这个问题?

4

5 回答 5

1

当您以模态方式显示属性表时,您应该能够使用属性表的父窗口(即其句柄)映射到实例::GetParent()hwndDlg使用PropSheetProc().

于 2009-12-14T21:10:26.323 回答
0

太棒了,又一个 Win32 API 使用没有用户定义的上下文参数的回调。唉,这不是唯一的。例如 CreateWindow 很糟糕(它为您提供用户定义的上下文,但该上下文不适用于前几个窗口消息), SetWindowsHookEx 更糟糕(根本没有上下文)。

唯一通用且有效的“解决方案”是使用硬编码的“this”指针发出一小段可执行代码。像这样的东西:http ://episteme.arstechnica.com/eve/forums/a/tpc/f/6330927813/m/848000817831?r=848000817831#848000817831

这太糟糕了。

于 2009-12-14T21:54:39.593 回答
0

PROPSHEETPAGE 结构有一个可用于回调的 lParam 字段。在您的 PROPSHEETHEADER 中,您可以包含 PSH_PROPSHEETPAGE 标志以传递描述您的页面的 PROPSHEETPAGE 项数组,或者省略该标志以传递预先分配的 HPROPSHEETPAGE 句柄数组(这意味着使用 CreatePropertySheetPage(),因此无论如何都使用 PROPSHEETPAGE)。

于 2009-12-15T02:10:23.737 回答
0

您已经承认“我无法在实际窗口的创建和销毁之间执行任何代码”。似乎全局变量不会是一个可怕的黑客攻击。

于 2009-12-15T02:46:36.190 回答
0

我找到了另一种选择:使用SetProp添加一个存储指向包装器的指针的属性。只需要全局变量一次,就可以SetProp从属性表回调中调用。

于 2009-12-22T19:09:13.020 回答