我想创建自己的类来处理创建窗口和窗口过程,但我注意到窗口过程必须是静态的!我现在想知道是否有可能使窗口过程面向对象?我已经阅读了一些关于面向对象窗口的教程,但是它们总是让程序变得静态 - 这是什么用的? :/
任何有关如何解决此问题的链接或信息都将不胜感激,
感谢
答案 0 :(得分:11)
你可以通过让静态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;
}
答案 1 :(得分:6)
允许窗口实例由类实例表示的一般技术是利用SetWindowLongPtr和GetWindowLongPtr将类实例指针与窗口句柄相关联。下面是一些示例代码,可帮助您入门。没有一些调整它可能无法编译。它只是一个参考。
就个人而言,几年前,当我发现ATL的CWindow和CWindowImpl模板类时,我已经停止了自己的窗口类。他们负责为您完成所有这些平凡的编码,因此可以专注于编写处理窗口消息的方法。请参阅我编写的示例代码here。
希望这有帮助。
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);
};
};
答案 2 :(得分:3)
答案 3 :(得分:2)
只是为了增加Brian的答案,但对于一个更加初学者友好的win32框架,请看一下Win32++。与MFC或QT相比,库本身的功能并不全面,但这是设计人员在开始时为保持库易于理解和易于使用而做出的权衡。
如果您仍然对此主题感兴趣,我强烈建议您查看它,因为它使用了另一种技术来利用线程本地存储来保存“this”指针。
答案 4 :(得分:1)
您可以使用传递给WindowProc的窗口句柄来抓取您为该特定窗口创建的对象,并将事件处理委托给该对象。
e.g。
IMyWindowInterface* pWnd = getMyWindowObject(hWnd);
pWnd->ProcessMessage(uMsg, wParam, lParam);