gpt4 book ai didi

c++ - Win32 窗口创建失败?

转载 作者:可可西里 更新时间:2023-11-01 11:13:05 24 4
gpt4 key购买 nike

我进行了研究,但找不到答案。我找到的最接近的是“Cannot create window”,但它对我没有帮助。所以,就在这里!

基本信息

我有一个静态库和一个使用静态库的应用程序。我正确地将应用程序连接到静态库(包括目录、库目录、实际库依赖项等)。在静态库中,我有 1 个文件:IWindow.h。在应用程序中,我有 3 个文件:Main.cppWindowMain.hWindowMain.cppIWindow.h 定义了一个抽象窗口类:

#ifndef IWINDOW_H
#define IWINDOW_H

#include <Windows.h>

namespace NamespaceName
{
template<class T>
class IWindow
{
public:
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

virtual ~IWindow(){}

virtual LRESULT handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
virtual VOID paint(HDC hDC) = 0;

VOID create(HINSTANCE hI, LPCWSTR title, LPCWSTR className, 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);

HWND getHWND();
BOOL isCreated();
protected:
HWND m_hWnd;
BOOL created;
};

template<class T>
LRESULT CALLBACK IWindow<T>::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
T* pThis = NULL;

if(uMsg == WM_NCCREATE)
{
CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
pThis = (T*)pCreate->lpCreateParams;
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pThis);
}
else
{
pThis = (T*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
}

if(pThis)
{
return pThis->handleMessage(uMsg, wParam, lParam);
}
else
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}

template<class T>
VOID IWindow<T>::create(HINSTANCE hI, LPCWSTR title, LPCWSTR className, 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 windowClass = {0};
windowClass.hInstance = hI;
windowClass.lpszClassName = className;
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.lpfnWndProc = IWindow::windowProc;

RegisterClass(&windowClass);

m_hWnd = CreateWindowEx(dwExStyle, className, title, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this);

created = (m_hWnd ? TRUE : FALSE);
}

template<class T>
HWND IWindow<T>::getHWND()
{
return m_hWnd;
}

template<class T>
BOOL IWindow<T>::isCreated()
{
return created;
}
}

#endif

然后,

WindowMain.h 定义了 IWindow.h

的子类

代码:

#ifndef WINDOWMAIN_H
#define WINDOWMAIN_H

#include <FolderName\Video\GUI\IWindow.h>

class WindowMain : public NamespaceName::IWindow<WindowMain>
{
public:
~WindowMain(){}

LRESULT handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
VOID paint(HDC hDC);
};

#endif

还有,

它是随附的 .cpp 文件

完成它:

#include "WindowMain.h"

LRESULT WindowMain::handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;

switch(uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
hDC = BeginPaint(m_hWnd, &ps);

FillRect(hDC, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
paint(hDC);

EndPaint(m_hWnd, &ps);
}
return 0;
}

return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
}

VOID WindowMain::paint(HDC hDC)
{
}

最后,

Main.cpp

代码:

#include <Windows.h>
#include <tchar.h>
#include <GdiPlus.h>
#include "WindowMain.h"

#pragma comment(lib, "Gdiplus.lib")

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
WindowMain window;
MSG msg;
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;

Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

window.create(hInstance, L"Test Window", L"Test Window Class", WS_OVERLAPPEDWINDOW);

if(!window.isCreated())
return 1;

ShowWindow(window.getHWND(), nCmdShow);
UpdateWindow(window.getHWND());

while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

Gdiplus::GdiplusShutdown(gdiplusToken);

return 0;
}

window.isCreated() 总是返回false,因此Main.cpp 中的if 语句> 将其反转为 true 并始终返回 1 并退出应用程序。如果我从 Main.cpp 中省略了 if 语句,则窗口不会显示,应用程序将永远运行,直到我在 IDE 中强制停止它。

其他问题(如果需要,请在评论中回答,这些是可选的,与前一个问题没有任何关系)

我一点也不喜欢 Visual Studio。我更喜欢使用 NetBeans。我试图将它用于 Windows 编程,但我失败了。我必须使用 Visual Studio for Windows 编程吗?有没有什么神奇的编译器可以用特殊的方式编译Win32程序?还是我只是做错了什么?

这些 Gdiplus 代币和启动输入是什么?指向解释它的地方的链接会很棒。

最后

感谢您花时间阅读本文,并可能试图帮助我。如果您需要更多信息,我很乐意提供。如果问题构造不当,请让我知道如何改进它,我会的。 ;)

编辑#1

找到这个:“Win32 API window won't open”,仅作记录,它对我的​​情况也没有帮助。

编辑 #2

IWindow.h 中,当我创建一个 WNDCLASS 时,对于窗口进程,我尝试使用 T::windowProc IWindow::windowProc,但它也没有帮助。

编辑 #3

找到“WinAPI window doesn't appear”,但也无济于事。

编辑#4

“在注册类之前尝试将 windowClass.cbWndExtra 设置为 sizeof(LONG_PTR)。” - 来自评论的建议。也试过了,也没用。

编辑#5

尝试将 WNDCLASS 替换为 WNDCLASSEX 并将 RegisterClass 替换为 RegisterClassEx 并添加 windowClassEx.cbSize = sizeof (WNDCLASSEX)(我也将变量名从 windowClass 更改为 windowClassEx),但也没有帮助...

最佳答案

我看到至少两个错误。

首先,你注册类(class)

windowClass.hInstance = hI;

但是当你创建窗口时,你传递了一个不同的HINSTANCE:

m_hWnd = CreateWindowEx(dwExStyle, className, title, dwStyle, x, y,
nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this);
// ^^^^^^^^^^^^^^^^^^^^^

HINSTANCE 参数必须匹配才能找到该类。你应该在这两个地方使用 hI

其次,您的代码在初始化之前使用了 m_hWnd 成员。

return DefWindowProc(m_hWnd, uMsg, wParam, lParam);

当窗口收到WM_NCCREATE消息时,m_hWnd还没有初始化。在 CreateWindowEx 返回之前,它不会被初始化。您需要为 DefWindowProc 获取正确的窗口句柄。一种方法是将 hWnd 参数从 windowproc 传递到 handlemessage。另一种是添加

m_hWnd = hWnd;

在你的 if(uMsg == WM_NCCREATE) 中。

请注意,您的代码假定如果 GWLP_USERDATA 不为零,则 m_hWnd 有效。但是,您实际上没有采取任何措施使该假设有效。在收到 WM_NCCREATE 消息和完成 CreateWindowEx 之间,您有一个非零的 GWLP_USREDATAm_hWnd 不是初始化。

调试它的方法是在窗口过程上设置一个断点并单步执行它。在逐步处理 WM_NCCREATE 消息时,您应该注意到 m_hWnd 未初始化。

这段代码中还有第三个错误,一旦您创建了窗口,您最终会偶然发现这个错误:您永远不会在窗口创建时将 m_hWnd 设置回 NULL销毁。

关于c++ - Win32 窗口创建失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18403700/

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