3

我在一个项目中使用了 ATL 和 WTL 的组合,并从 派生了我自己的类CWindowImpl,它看起来像这样:

class CMyControl : public CWindowImpl<CMyControl>
{
public:
    DECLARE_WND_CLASS(_T("MyClassName"))
    ...
    BEGIN_MSG_MAP(CMyControl)
        ...
    END_MSG_MAP()
};

这一切都很好,如果我CMyControl::Create用来创建控件的实例,那么它在后台运行良好,该CWindowImpl::Create函数将注册 Win32 类(在本例中称为MyClassName)。

然而,正是这种行为——在创建实例时注册了 Win32 类——让我很头疼。我希望能够预先注册类,以便我可以将类名与另一个 3rd 方库一起使用,该库将使用 Win32CreateWindowEx调用创建窗口,但我找不到一个简单的方法来做到这一点。目前我通过使用static作为CreateWindowEx类名来解决这个问题,然后使用CMyWindow::SubclassWindow将我的类附加到它,但这是一个杂项。

有谁知道如何在CWindowImpl不实际创建窗口的情况下注册派生类,以便我可以CreateWindowEx成功传递类名?我认为有一种标准方法可以使用 ATL 窗口来执行此操作,因为我不是第一个遇到此问题的人。

4

3 回答 3

2

你试图做的事情是行不通的。这是因为 ATL/WTL Window 的创建必须经过 ATL 类。该类使用窗口thunk注册其this ptr 。此 thunk 成为 WNDPROC 并用对象实例的this ptr 替换 WNDPROC 的 HWND 参数。

所以简而言之,如果您知道 ATL 窗口化是如何在幕后工作的,您就不会尝试这样做。如果您能够注册窗口类,则 CreateWindowEx 调用将成功创建窗口。但是,不会创建 WNDPROC thunk,并且不会有对象实例可以关联您的窗口,也不会调用任何消息处理程序。相反,看看您是否可以使用 CWindowImpl::Create 创建窗口,并在创建后将 ATL 控件的 hwnd 传递给您的第 3 方库。

于 2009-02-24T06:03:58.900 回答
0

您可以直接调用 Win32 API RegisterClassEx函数。

于 2009-02-22T19:52:20.377 回答
0

您可以使用:

WNDPROC pUnusedWndSuperProc; 
pUnusedWndSuperProc = NULL;
CMyControl::GetWndClassInfo().Register(&pUnusedWndSuperProc);

虽然......我不确定你为什么不只是创建一个窗口实例并将其隐藏。它有点开销,但它避免了与窗口逻辑的胆量混淆(这是非常复杂的东西......你想要的最后一件事是“thunking”的一些意外或不寻常的问题)。

于 2009-02-22T21:38:45.707 回答