Здравствуйте 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);
}
Примерно так. Я мог напутать чего-нибудь, проверишь — расскажешь.