Предварительная регистрация класса окна ATL

Я использую комбинацию 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, поскольку я не могу быть первым, кто столкнулся с этой проблемой.


person Rob    schedule 22.02.2009    source источник


Ответы (3)


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

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

person m-sharp    schedule 24.02.2009

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

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

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

person user53794    schedule 22.02.2009

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

person Yigang Wu    schedule 22.02.2009