我正在使用以下代码获取HWND->i
,但是当我启动程序时,它会终止对话框“Program.exe遇到问题并需要关闭”:
#include <windows.h>
#include <sstream>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("Program") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("Error"), szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName,
TEXT ("Program"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL) ;
ShowWindow (hwnd, iCmdShow) ;
std::ostringstream oss;
oss << hwnd->i;
//MessageBox(NULL, oss.str().c_str(), TEXT("message"), MB_OK);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
当我发表评论时
oss << hwnd->i;
程序正常运行。
那么,有没有办法在hwnd->i
中显示MessageBox()
?
答案 0 :(得分:1)
正如MSDN here中所述:
Windows是对象 - 它们既有代码又有数据 - 但它们不是 C ++类。相反,程序通过使用值引用窗口 称为句柄。手柄是不透明的类型。从本质上讲,它只是一个 操作系统用于标识对象的编号。您可以 Windows Windows拥有所有窗口的大表 已创建。它使用此表通过其句柄查找窗口。 (这究竟是如何在内部工作并不重要。) 窗口句柄的数据类型是HWND,通常是发音 “aitch风。”窗口句柄由创建的函数返回 windows: CreateWindow 和 CreateWindowEx 。
至关重要的是,这条评论:
请记住,句柄不是指针。如果hwnd是一个变量 包含一个句柄,试图通过写入取消引用句柄 * hwnd是一个错误。
重点是HWND
只是你传递给处理windows的API调用的东西。它的内部实现是隐藏的,开发人员无需担心。通过调用HWND->i
,您试图将其取消引用,就好像它是一个指针,它不是。因此你崩溃了。
答案 1 :(得分:1)
其他人已经解释了为什么解除引用HWND
崩溃(它没有指向应用程序拥有的内存),但没有人解释为什么编译器会接受HWND->...
语法。
在编译时促进STRICT
type checking:
定义
STRICT
时,数据类型定义 改变如下:
- 特定句柄类型被定义为相互关联 独家;例如,你将无法通过
HWND
HDC
类型参数 需要。如果没有STRICT
,则定义所有句柄 作为整数,所以编译器不会阻止你 从使用一种类型的句柄,其他类型 预期。
未定义STRICT
时,HWND
被定义为无类型指针:
typedef void *HANDLE;
typedef HANDLE HWND;
因此HWND->...
在编译时无效,因为void
没有成员。但是,在定义STRICT
时,HWND
被定义为指向struct
的指针:
struct HWND__ { int unused; };
typedef struct HWND__ *HWND;
因此,HWND->...
在编译时被接受,因为HWND__
有成员,但在运行时失败,因为HWND
实际上没有指向有效的HWND__
实例
至于->i
专门编译的原因,您的Windows SDK标头副本可能会将unused
成员定义为i
(例如,显然MinGW会这样做)。否则,您应该收到有关i
是未知成员的编译器错误。
答案 2 :(得分:0)
HWND本身会重复一个窗口,它看起来引用的内部结构只作为占位符。
实际上,它是Windows API用来映射留在窗口管理器中的数据的索引,这些数据在您的进程外部甚至对您不可见。
它显然指向的地址不属于您的程序(甚至可能不是地址),因此访问hwnd->i
是未定义的行为:如果您幸运,程序崩溃(从而揭示错误)否则它将访问随机数据。