【发布时间】:2020-07-21 14:09:35
【问题描述】:
用 C++ 编码,大概使用 Visual Studio。
template <class DERIVED_TYPE>
class BaseWindow
{
public:
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DERIVED_TYPE *pThis = NULL;
if (uMsg == WM_NCCREATE)
{
CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
//m_hwnd GETS SET HERE:
pThis->m_hwnd = hwnd;
}
else
{
pThis = (DERIVED_TYPE*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
if (pThis)
{
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
BaseWindow() : m_hwnd(NULL) { }
BOOL Create(
PCWSTR lpWindowName,
DWORD dwStyle,
DWORD dwExStyle = 0,
int x = CW_USEDEFAULT,
int y = CW_USEDEFAULT,
int nWidth = CW_USEDEFAULT,
int nHeight = CW_USEDEFAULT,
HWND hWndParent = 0,
HMENU hMenu = 0
)
{
WNDCLASS wc = {0};
wc.lpfnWndProc = DERIVED_TYPE::WindowProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = ClassName();
RegisterClass(&wc);
//m_hwnd GETS SET HERE:
m_hwnd = CreateWindowEx(
dwExStyle, ClassName(), lpWindowName, dwStyle, x, y,
nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this
);
return (m_hwnd ? TRUE : FALSE);
}
HWND Window() const { return m_hwnd; }
protected:
virtual PCWSTR ClassName() const = 0;
virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
HWND m_hwnd;
};
变量m_hwnd 为同一个实例设置了两次(至少我是这么认为的):
pThis->m_hwnd = hwnd;
这里:
m_hwnd = CreateWindowEx(
dwExStyle, ClassName(), lpWindowName, dwStyle, x, y,
nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this
);
这是有原因的吗? m_hwnd 实际上只设置了一次,我错过了什么吗?
最小可重复示例:
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
MainWindow win;
if (!win.Create(L"Learn to Program Windows", WS_OVERLAPPEDWINDOW))
{
return 0;
}
ShowWindow(win.Window(), nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
网站:https://docs.microsoft.com/en-us/windows/win32/learnwin32/managing-application-state-
【问题讨论】:
-
请提供minimal reproducible example。但是
pThis->m_hwnd和this->m_hwnd不一样。这是两个不同的变量。正因为如此,我不明白你的困惑。 -
可能是疏忽,但更有可能只是防御性编程。如果
CreateWindowEx调用失败,那么m_hwnd将正确地为NULL,即使WM_NCCREATE 可能不会被调用。如果调用成功,那么它会被设置两次,但考虑到在CreateWindowEx函数返回之前将处理多个窗口消息。如果其中一条消息的处理程序调用了一个函数,该函数期望正确设置此成员(现在或在未来的代码修订版中),那么如果您没有在它可用时立即设置它,则可能会出现问题。 -
请注意,它没有设置
this->m_hwnd,而是设置pThis->m_hwnd。您显示的代码中缺少的是MainWindow类,以及它如何使用BaseWindow类和DERIVED_TYPE模板参数。
标签: c++ windows visual-studio