Предварительная регистрация класса окна ATL - PullRequest
3 голосов
/ 22 февраля 2009

Я использую комбинацию 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, регистрируемый при создании экземпляра, - вызывает у меня головную боль. Я хочу иметь возможность зарегистрировать класс заранее, чтобы я мог использовать имя класса с другой сторонней библиотекой, которая создаст окно с помощью вызова Win32 CreateWindowEx, но я не могу найти простой способ сделать это , В настоящее время я обхожу эту проблему, используя static в качестве имени класса CreateWindowEx, а затем использую CMyWindow::SubclassWindow, чтобы присоединить к нему мой класс, но это клудж.

Кто-нибудь знает, как зарегистрировать производный класс CWindowImpl без фактического создания окна, чтобы я мог успешно передать имя класса в CreateWindowEx? Я бы подумал, что существует стандартный способ сделать это с помощью окон ATL, поскольку я не могу быть первым, кто столкнулся с этой проблемой.

Ответы [ 3 ]

2 голосов
/ 24 февраля 2009

То, что вы пытаетесь сделать, не сработает. Это связано с тем, что создание окна ATL / WTL должно проходить через класс ATL. Класс регистрирует свой this ptr с окном thunk . Этот блок становится WNDPROC и заменяет параметр HWND WNDPROC на this ptr экземпляра объекта.

Короче говоря, если бы вы знали, как работает окно ATL под капотом, вы не попытались бы попробовать это. Если бы вы смогли зарегистрировать класс окна, вызов CreateWindowEx успешно создал бы окно. Однако блок WNDPROC не будет создан, и не будет никакого экземпляра объекта, с которым будет связано ваше окно, и ни один из ваших обработчиков сообщений не будет вызван. Вместо этого посмотрите, можете ли вы создать свое окно с помощью CWindowImpl :: Create и передать своей сторонней библиотеке hwnd элемента управления ATL после его создания.

0 голосов
/ 23 февраля 2009

Вы можете использовать:

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

Хотя ... я не уверен, почему вы не просто создаете экземпляр окна и скрываете его. Это немного накладные расходы, но это позволяет избежать гадости с интуицией оконной логики (что является довольно сложным делом ... последнее, что вам нужно, это какая-то неожиданная или необычная проблема с "thunking").

0 голосов
/ 22 февраля 2009

Вы можете напрямую вызвать Win32 API RegisterClassEx .

...