Я хочу создать свой собственный класс для обработки окон создания и оконной процедуры, но я заметил, что оконная процедура должна быть статичной! Я теперь задаюсь вопросом ли ее возможное для создания оконной процедуры объектно-ориентированной? Я прочитал некоторые учебные руководства на объектно-ориентированных окнах, но они всегда делают процедуру, статические-.-что проку в этом?:/
Любые ссылки или информация о том, как обойти эту проблему, ценились бы,
спасибо
Вы можете обойти это, заставив статический WndProc делегировать все членам:
// Forward declarations
class MyWindowClass;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
std::map<HWND, MyWindowClass *> windowMap;
// Your class
class MyWindowClass {
private:
HWND m_handle;
// The member WndProc
LRESULT MyWndProc(UINT message, WPARAM wParam, LPARAM lParam) { /* ... */ }
public:
MyWindowClass()
{
/* TODO: Create the window here and assign its handle to m_handle */
/* Pass &WndProc as the pointer to the Window procedure */
// Register the window
windowMap[m_handle] = this;
}
};
// The delegating WndProc
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
std::map<HWND, MyWindowClass *>::iterator it = windowMap.find(hWnd);
if (it != windowMap.end())
return it->second->MyWndProc(message, wParam, lParam);
return 0;
}
Вы можете использовать дескриптор окна, переданный WindowProc, чтобы захватить объект, который вы создали для этого конкретного окна, и делегировать обработку событий этому объекту.
например.
IMyWindowInterface* pWnd = getMyWindowObject(hWnd);
pWnd->ProcessMessage(uMsg, wParam, lParam);
Общий метод разрешения экземпляра окна быть представлен в виде экземпляра класса: используйте SetWindowLongPtr и GetWindowLongPtr, чтобы связать указатель экземпляра класса с дескриптором окна. Ниже приведен пример кода для начала. Он может не скомпилироваться без некоторых настроек. Он предназначен только для справки.
Лично я перестал откатывать свои собственные классы окон назад несколько лет назад, когда обнаружил классы шаблонов ATL CWindow и CWindowImpl. Они позаботятся о выполнении всего этого обыденного кодирования за вас, поэтому вы можете сосредоточиться только на написании методов, обрабатывающих оконные сообщения. См. Пример кода, который я написал здесь .
Надеюсь, это поможет.
class CYourWindowClass
{
private:
HWND m_hwnd;
public:
LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE: return OnCreate(wParam, lParam);
case wM_PAINT: return OnPaint(wParam, lParam);
case WM_DESTROY:
{
SetWindowLongPtr(m_hwnd, GWLP_USERDATA, NULL);
m_hwnd = NULL;
return 0;
}
}
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
CYourWindowClass()
{
m_hwnd = NULL;
}
~CYourWindowClass()
{
ASSERT(m_hwnd == NULL && "You forgot to destroy your window!");
if (m_hwnd)
{
SetWindowLong(m_hwnd, GWLP_USERDATA, 0);
}
}
bool Create(...) // add whatever parameters you want
{
HWND hwnd = CreateWindow("Your Window Class Name", "Your Window title", dwStyle, x, y, width, height, NULL, hMenu, g_hInstance, (LPARAM)this);
if (hwnd == NULL)
return false;
ASSERT(m_hwnd == hwnd);
return true;
}
static LRESULT __stdcall StaticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CYourWindowClass* pWindow = (CYourWindowClass*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (uMsg == WM_CREATE)
{
pWindow = ((CREATESTRUCT*)lParam)->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (void*)pWindow);
m_hWnd = hwnd;
}
if (pWindow != NULL)
{
return pWindow->WndProc(uMsg, wParam, lParam);
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
};
};