我的项目是C++ Windows Desktop Wizard又称Win32 API项目。
在函数WinMain(...)中,我正在创建我的窗口。
hWnd = CreateWindowEx(NULL, _T("DesktopApp"), _T("Hi, I'm window"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);
之后由于某种原因,我的窗口出现了 "无法读取内存 "的状态(因此我无法在没有这个问题的情况下创建GUI)。我甚至检查了Google的第二页来寻找解决这个问题的方法。微软的文档也没有帮助。我检查了它的实现,它和我的是一致的. 我很长时间都无法解决这个问题,因为我是个瞎子,而且我之前写错了一些东西,尽管我之前已经创建了两个工作项目(比较没有给出任何结果)。
下面是整个代码。
#include <windows.h>
#include <stdlib.h>
#include <string>
#include <tchar.h>
#include <shellapi.h>
#include <ctime>
HWND hWnd;
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(wcex));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
hInst = hInstance;
hWnd = CreateWindowEx(NULL, _T("DesktopApp"), _T("Hi, I'm window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
先谢谢你的帮助。
当 STRICT Type Checking
在编译过程中启用。HWND
是一个类型定义,用于 HWND__*
,其中 HWND__
是一个结构,有一个 unused
数据成员(只因为 struct
在C语言中不能合法地为空,但在C++中可以),如
winnt.h:
#ifdef STRICT
typedef void *HANDLE;
#if 0 && (_MSC_VER > 1000)
#define DECLARE_HANDLE(name) struct name##__; typedef struct name##__ *name
#else
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
#endif
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif
windef:
DECLARE_HANDLE (HWND);
所以,当 STRICT
被定义为。HWND
的别称。struct HWND__*
的别称,否则就是 PVOID
(void*
). 和其他许多手柄类型一样 (HHOOK
, HEVENT
, HGDIOBJ
, HBITMAP
等)。)
为了让你的调试器向你显示出 unused
成员在查看 HWND
,这意味着你正在用 STRICT
定义的(这是件好事,你应该是)。 调试器看到一个指向类型的指针,并试图显示该类型所包含的数据。
然而,一个 HWND
并不是真正的指向一个 struct HWND__
在记忆中。 其实这只是一个 不透明值 内核提供的。 什么是 HWND
实际上指的是内核的隐私,用户模式的调试器无法知道那到底是什么。
STRICT
句柄只是为了编译时的类型安全而提供的,这样用户代码就不会意外地传递其他句柄类型,而在这些句柄类型中,有一个叫做 HWND
是预期,反之亦然。
在你的情况下,你的 HWND
价值为 0x00170344
这意味着 CreateWindowEx()
没有失败, HWND
本身是有效的。 但是 0x00170344
在你的应用程序的地址空间中不是一个有效的内存地址,所以当调试器试图访问到 unused
该地址的成员,它以 "无法读取内存 "失败。该 unused
成员在用户模式调试器中永远不会有效(这就是为什么它是 "未使用 "的)。 唯一重要的是 价值 的 HWND
本身就是 0
或不。