Как создать объект, наследованный от CWnd?
От: KaSA  
Дата: 04.11.01 16:30
Оценка:
Требуется создать сабж. Полностью, с регистрацией имени
класса в системе (RegisterClass(...)). Так же, как MFC создает
класс "MDIFrame", например. Также необходимо, чтобы правильно
работала MessageMap. Как это сделать? Понятно, что функция окна
не может быть методом класса, но в MFC это реализовано???
Не при помощи ли GetSuperWndProcAddr() ?

Помогите, кто может! Совсем зат%?№!"ся :(
Спасибо.
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
Re[2]: Как создать объект, наследованный от CWnd?
От: KaSA  
Дата: 05.11.01 09:13
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

слушай, ты гений :)))
спасибо огромное!
меня интересовал как раз второй вариант, все
отлично работает!
10x!
Re[2]: Как создать объект, наследованный от CWnd?
От: KaSA  
Дата: 05.11.01 14:03
Оценка:
Здравствуйте Alex Fedotov, Вы писали:


AF> // создаем объект C++

AF> CMyWnd * pWnd = new CMyWnd();


М-да, рано радовался :(
Все было бы хорошо, еслиб знать, как эти созданные
С++ объекты удалять. Особенно созданные внутри них
MFC объекты...такая ж%па начинается после закрытия окна,
ужас просто :)
мож я тупой ваще, но не вижу тривиального решения...
есть идеи?

спасибо.
Re[3]: Как создать объект, наследованный от CWnd?
От: Krom Россия  
Дата: 06.11.01 13:10
Оценка:
Здравствуйте KaSA, Вы писали:

KSA>Здравствуйте Alex Fedotov, Вы писали:



AF>> // создаем объект C++

AF>> CMyWnd * pWnd = new CMyWnd();


KSA>М-да, рано радовался :(

KSA>Все было бы хорошо, еслиб знать, как эти созданные
KSA>С++ объекты удалять. Особенно созданные внутри них
KSA>MFC объекты...такая ж%па начинается после закрытия окна,
KSA>ужас просто :)
KSA>есть идеи?

Есть одна идея, к сожалению нет времени сейчас это проверить :(, надо сделать
поддержку динамического создания в класс CMyWnd и использовать его

CRuntimeClass* pRuntimeClass = RUNTIME_CLASS(CMyWnd);
CMyWnd * pWnd = pRuntimeClass->CreateObject();
Best regards
Krom
Re[3]: Как создать объект, наследованный от CWnd?
От: Alex Fedotov США  
Дата: 06.11.01 15:10
Оценка:
Здравствуйте KaSA, Вы писали:

AF>> // создаем объект C++

AF>> CMyWnd * pWnd = new CMyWnd();

KSA>Все было бы хорошо, еслиб знать, как эти созданные

KSA>С++ объекты удалять. Особенно созданные внутри них
KSA>MFC объекты...такая ж%па начинается после закрытия окна,
KSA>ужас просто :)
KSA>мож я тупой ваще, но не вижу тривиального решения...
KSA>есть идеи?

Не хочу тебя расстраивать...

Добавь в свой класс

virtual void PostNcDestroy()
{ delete this; }
-- Alex Fedotov
Re[4]: Как создать объект, наследованный от CWnd?
От: KaSA  
Дата: 06.11.01 15:54
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

Все привыкли, к фразе "цель оправдывает средства",
но в данном контексте усё наоборот :) —
средства вовсе не оправдывают цель...

решил проблему путем встраивания в OnDestroy(...)
строки — delete this; Не лучший вариант, но работает :)
Даже ВС не ругается...

хотя, меня поражает тот факт, что в MFC не предусмотрен
нормальный способ создания собственных контролов...
...чего желать от non OOP OS...


спасибо за советы.
Re[5]: Как создать объект, наследованный от CWnd?
От: Alex Fedotov США  
Дата: 07.11.01 08:49
Оценка:
Здравствуйте KaSA, Вы писали:

KSA>Все привыкли, к фразе "цель оправдывает средства",

KSA>но в данном контексте усё наоборот :) —
KSA>средства вовсе не оправдывают цель...

KSA>решил проблему путем встраивания в OnDestroy(...)

KSA>строки — delete this; Не лучший вариант, но работает :)
KSA>Даже ВС не ругается...

Специально для этого сделана виртуальная функция PostNcDestroy, которая вызывается сразу после обработки сообщения WM_NCDESTROY (последнее сообщение, которое приходит в окно перед его уничтожением). Странно не воспользоваться специально предназначенным для этого средством и изобретать велосипед, хотя и очень похожий.
-- Alex Fedotov
Re[6]: Как создать объект, наследованный от CWnd?
От: KaSA  
Дата: 09.11.01 04:37
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>Специально для этого сделана виртуальная функция PostNcDestroy, которая вызывается сразу после обработки сообщения WM_NCDESTROY (последнее сообщение, которое приходит в окно перед его уничтожением). Странно не воспользоваться специально предназначенным для этого средством и изобретать велосипед, хотя и очень похожий.


Велосипед я не изобретал...просто реализовал это раньше, чем Вы ответили.
А за то, что насчет PostNcDestroy просветили — огромное человеческое спасибо :)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.