gpt4 book ai didi

c++ - 为什么不调用虚拟 WndProc?

转载 作者:搜寻专家 更新时间:2023-10-31 00:34:06 25 4
gpt4 key购买 nike

这是我目前所拥有的...即使我实例化了一个 Window(WindowBase 的子类),我还是收到了一个错误,即试图调用一个纯虚函数。基本上,我的程序试图调用 WindowBase::WndProc 而不是 Window::WndProc。

WINDOWBASE.H

#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_ */

WINDOWBASE.CPP

#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
}

窗口.H

#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_ */

最佳答案

如果您在 WindowBase 构造函数中调用 CreateWindow,您将开始从那里接收消息。

如果您创建Window 对象,它自己的构造函数必须调用WindowBase 构造函数。在此期间,Window 对象尚未存在,因此它的虚函数尚不可用(它们将引用一个尚未构造的 Window ...)。

您的设计还有许多其他陷阱:考虑每个组件的范围和生命周期:其中一些在构建之前使用,其他在仍然需要时销毁。

将 OOP C API(如 WIn32)包装到另一种具有“对象”和“范围”概念的 OOP 语言(如 C++)中并不容易,它们与 WIN32 所考虑的不匹配。兼顾两者,否则您可以轻松获得看起来正常工作的 cod,但在更广泛的上下文(更多窗口而不是一个窗口)中使用可能会出现不符合预期的行为。

关于c++ - 为什么不调用虚拟 WndProc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26960022/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com