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

时间:2014-01-24 07:23:51

标签: c++ winapi hwnd

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

3 个答案:

答案 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是未定义的行为:如果您幸运,程序崩溃(从而揭示错误)否则它将访问随机数据。