是否可以在 MessageBox() 中显示 HWND->i?

Is it possible to show HWND->i in MessageBox()?

本文关键字:HWND- gt 显示 MessageBox 是否      更新时间:2023-10-16

我正在使用以下代码获取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;

程序正常运行。

那么,有没有办法在MessageBox()中显示hwnd->i

在此处的MSDN中所说:

Windows是对象 - 它们既有代码又有数据 - 但它们不是 C 类。相反,程序通过使用值引用窗口 称为手柄。手柄是不透明的类型。本质上,这只是一个 操作系统用来识别对象的数字。你可以 图片窗口是所有具有的窗口的大桌子 已创建。它使用此表通过其手柄查找窗户。 (这是否完全是内部工作的方式并不重要。) 窗口手柄的数据类型是HWND,通常是发音的 " aitch-wind。"窗口手柄由创建的函数返回 Windows: createWindow createwIndowex

至关重要的是,此评论:

请记住,手柄不是指针。如果HWND是一个变量 包含一个句柄,试图通过写作来解除手柄 *hwnd是一个错误。

要点是,HWND只是您传递给与Windows的API调用的东西。它的内部实施是隐藏的,并且不关心开发人员。通过调用HWND->i,您正在尝试将其解释,就好像它是指针一样,不是。因此,您崩溃了。

其他人已经解释了为什么删除HWND崩溃(它没有指向应用程序拥有的内存),但是没有人解释了为什么编译器会接受HWND->...语法以与。

是在编译时促进STRICT类型检查:

定义STRICT时,数据类型定义 更改如下:

  • 特定的手柄类型定义为相互的 独家的;例如,您将无法通过 HWND HDC类型参数为 必需的。没有STRICT,所有手柄均已定义 作为整数,因此编译器不会阻止您 从使用另一种类型的一种手柄 预期。

未定义STRICT时,HWND被定义为未型指针:

typedef void *HANDLE;
typedef HANDLE HWND;

因此,由于void没有成员,因此HWND->...在编译时间时无效。但是,当定义STRICT时,HWND被定义为指向struct的指针:

struct HWND__ { int unused; };
typedef struct HWND__ *HWND;

因此,HWND->...在编译时被接受,因为HWND__具有成员,但是在运行时失败,因为HWND实际上并未指向有效的HWND__实例。

至于->i专门编译的原因,您的Windows SDK标头的副本可能将unused成员定义为i(例如,Mingw确实如此)。否则,您应该对i成为未知成员的编译器错误。

hwnd本身可以修复一个窗口,而它所引用的内部结构仅是占位符。

实际上,它是Windows API使用的索引,用于映射留在窗口管理器的数据外,您的流程外,甚至对您都看不到。

地址显然指向您的程序不属于您的程序(甚至可能不是地址),因此访问hwnd->i是未定义的行为:如果您幸运的话,程序崩溃(因此揭示了错误),否则它将访问随机的随机访问数据。