这是我到目前为止所做的...即使我实例化一个Window(WindowBase的子类),我也会收到一个错误,即尝试调用纯虚函数。基本上,我的程序试图调用WindowBase :: WndProc而不是Window :: WndProc。
#ifndef WINDOWBASE_H_
#define WINDOWBASE_H_
#include <Windows.h>
class WindowBase {
public:
WindowBase(HINSTANCE hInstance, int nCmdShow);
~WindowBase();
void Show();
protected:
virtual LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam) = 0;
private:
static LRESULT CALLBACK WndRouter(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
HWND hWnd;
int nCmdShow;
};
#endif /* WINDOWBASE_H_ */
#include <Windows.h>
#include "WindowBase.h"
#include <tchar.h>
WindowBase::WindowBase(HINSTANCE hInstance, int nCmdShow) {
this->nCmdShow = nCmdShow;
WNDCLASS wcex;
//wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndRouter;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = _T("TestMenu");
wcex.lpszClassName = _T("TestWindow");
//wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClass(&wcex)) {
MessageBox(NULL,
"Call to RegisterClassEx failed!",
"Win32 Guided Tour",
NULL);
}
hWnd = CreateWindow(_T("TestWindow"), _T("TestWindow"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 500, 100, NULL, NULL, NULL, (void*)this);
if (!hWnd){
MessageBox(NULL,
"Call to CreateWindow failed!",
"Win32 Guided Tour",
NULL);
}
}
WindowBase::~WindowBase() {
}
void WindowBase::Show() {
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
}
LRESULT CALLBACK WindowBase::WndRouter(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam) {
WindowBase* base = NULL;
if (uMsg == WM_NCCREATE) {
base = reinterpret_cast<WindowBase*>(((LPCREATESTRUCT)lParam)->lpCreateParams);
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)base);
} else {
base = reinterpret_cast<WindowBase*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
}
if (!base)
return DefWindowProc(hWnd, uMsg, wParam, lParam);
return base->WndProc(hWnd, uMsg, wParam, lParam); // GETS TO HERE, BUT TRIES TO
// CALL WindowBase::WndProc, INSTEAD OF Window::WndProc
}
#ifndef WINDOW_H_
#define WINDOW_H_
#include "windowbase.h"
class Window : public WindowBase {
public:
Window(HINSTANCE hInstance, int nCmdShow);
~Window();
protected:
virtual LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
#endif /* WINDOW_H_ */
答案 0 :(得分:5)
如果您在CreateWindow
构造函数中调用WindowBase
,则会开始从那里接收消息。
如果您创建了Window
对象,那么它自己的构造函数必须调用WindowBase
构造函数。在此期间,Window
对象尚未出现,因此其虚函数尚不可用(它们将引用尚未构造的窗口......)。
你的设计还有许多其他陷阱:想想每个组件的范围和寿命:其中一些在构造之前使用,另一个在需要时被破坏。
将OOP C API(如WIn32)包装成另一种具有&#34; Object&#34;概念的OOP语言(如C ++)并不容易。和&#34;范围&#34;这不符合WIN32的想法。照顾它们,或者你可以轻松地获得看起来有效的鳕鱼,但是在更广泛的环境中使用(更多的窗口而不仅仅是一个)风险表现得不如预期。