Re: Как создать объект, наследованный от CWnd?
От: Alex Fedotov США  
Дата: 04.11.01 20:09
Оценка:
Здравствуйте KaSA, Вы писали:

KSA>Требуется создать сабж. Полностью, с регистрацией имени

KSA>класса в системе (RegisterClass(...)). Так же, как MFC создает
KSA>класс "MDIFrame", например. Также необходимо, чтобы правильно
KSA>работала MessageMap. Как это сделать? Понятно, что функция окна
KSA>не может быть методом класса, но в MFC это реализовано???
KSA>Не при помощи ли GetSuperWndProcAddr() ?

1. Пишется класс, наследованный от CWnd, c message map и всеми делами.

class CMyWnd : public CWnd { ... };

2. Создается объект класса и создается окно:

CMyWnd * pWnd = new CMyWnd();
pWnd->Create(...);

В этом случае окно будет иметь имя класса, сгенерированное MFC, что-то вроде "Afx:400000:8:10011:0:19800411".

3. Если хочется, чтобы окно имело конкретный предопределенный класс, то нужно зарегистрировать этот класс в PreCreateWindow:

BOOL 
CMyWnd::PreCreateWindow(
    CREATESTRUCT& cs
    )
{
    if (!CWnd::PreCreateWindow(cs) )
        return FALSE;

    cs.lpszClass = _T("MyWndClass");

    WNDCLASSEX wcex;
    memset(&wcex, 0, sizeof(wcex));
    wcex.cbSize = sizeof(wcex);

    HINSTANCE hInstance = AfxGetInstanceHandle();

    if (!GetClassInfoEx(hInstance, _T("MyWndClass"), &wcex))
    {
        wcex.hInstance = hInstance;
        wcex.lpszClassName = _T("MyWndClass");
        wcex.lpfnWndProc = AfxWndProc;

        // more initialization here

        VERIFY(RegisterClassEx(&wcex));
    }

    return TRUE;
}


4. Все перечисленные методы требуют, чтобы сначала был создан объект C++, а только потом создавалось окно. Если хочется зарегистрировать класс окна, так чтобы кто-то вызывал ::CreateWindow(_T("MyWndClass"), ...), возможно, даже не подозревая о том, что окно реализовано на MFC, нужно действовать по другому.

4.а Рериструруем класс окна и указываем там свою функцию окна (она может быть статическим членом класса):

    WNDCLASSEX wcex;
    memset(&wcex, 0, sizeof(wcex));

    HINSTANCE hInstance = AfxGetInstanceHandle();

    wcex.cbSize = sizeof(wcex);
    wcex.hInstance = hInstance;
    wcex.lpszClassName = _T("MyWndClass");
    wcex.lpfnWndProc = MyWndProc;

    // more initialization here

     VERIFY(RegisterClassEx(&wcex));


4.б В функции окна создаем объект С++ и субклассируем уже созданное окно:

LRESULT CALLBACK 
CMyWnd::MyWndProc(
    HWND hWnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
    )
{
    // первым делом отсоединяем эту функцию от окна, чтобы она никогда 
    // больше не вызывалась и назначаем DefWindowProc в качестве функции
    // окна
    SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)DefWindowProc);

    // создаем объект C++
    CMyWnd * pWnd = new CMyWnd();

    // субклассируем окно
    pWnd->SubclassWindow(hWnd);

    // теперь все новые сообщения, которые идут в это окно будут попадать
    // в AfxWndProc, которая по идентификатору окна найдет нужный объект
    // CMyWnd и передаст сообщение ему. Все необработанные сообщения она
    // будет передавать предыдущей функции окна, которую мы только что
    // установили в DefWindowProc.

    // Однако, самое первое сообщение, которое мы в данный момент обрабатываем,
    // уже не будет получено через стандартные механизмы, поэтому мы вызываем
    // AfxWndProc явно, чтобы дать возможность окну обработать это сообщение

    return AfxWndProc(hWnd, uMsg, wParam, lParam);
}


Примерно так. Я мог напутать чего-нибудь, проверишь — расскажешь.
-- Alex Fedotov
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.