为什么CreateWindow()在注册窗口类时已经提供了hInstance作为参数?

问题描述 投票:4回答:4

注册窗口类时,有必要填写WNDCLASSstruct,它有一个hInstance字段:

typedef struct {
    UINT style;
    WNDPROC lpfnWndProc;
    int cbClsExtra;
    int cbWndExtra;
    HINSTANCE hInstance;
    HICON hIcon;
    HCURSOR hCursor;
    HBRUSH hbrBackground;
    LPCTSTR lpszMenuName;
    LPCTSTR lpszClassName;
} WNDCLASS

然后,使用CreateWindow()创建窗口,其中包含以下参数:

HWND CreateWindow(          
    LPCTSTR lpClassName,
    LPCTSTR lpWindowName,
    DWORD dwStyle,
    int x,
    int y,
    int nWidth,
    int nHeight,
    HWND hWndParent,
    HMENU hMenu,
    HINSTANCE hInstance,
    LPVOID lpParam
);

  • 如果hInstance在课程注册时提供了WNDCLASS,为什么有必要向hInstance提供CreateWindow()
  • 提供给hInstanceWNDCLASS是否应该与hInstance提供的CreateWindow()相同?
  • 如果WNDCLASS hInstanceCreateWindow() hInstance不同,它们是什么意思?

这是一个演示类注册/窗口创建的示例程序:

#include <windows.h>

LPSTR szClassName = "MyClass";
HINSTANCE hInstance;
LRESULT CALLBACK MyWndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
{
   WNDCLASS wnd;
   MSG msg;
   HWND hwnd;

   hInstance = hInst;

   wnd.style = CS_HREDRAW | CS_VREDRAW; //we will explain this later
   wnd.lpfnWndProc = MyWndProc;
   wnd.cbClsExtra = 0;
   wnd.cbWndExtra = 0;
   wnd.hInstance = hInstance;
   wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION); //default icon
   wnd.hCursor = LoadCursor(NULL, IDC_ARROW);   //default arrow mouse cursor
   wnd.hbrBackground = (HBRUSH)(COLOR_BACKGROUND+1);
   wnd.lpszMenuName = NULL;                     //no menu
   wnd.lpszClassName = szClassName;

   if(!RegisterClass(&wnd))                     //register the WNDCLASS
   {
       MessageBox(NULL, "This Program Requires Windows NT", 
                        "Error", MB_OK);
       return 0;
   }

   hwnd = CreateWindow(szClassName,
                       "Window Title",
                       WS_OVERLAPPEDWINDOW, //basic window style
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,       //set starting point to default value
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,       //set all the dimensions to default value
                       NULL,                //no parent window
                       NULL,                //no menu
                       hInstance,
                       NULL);               //no parameters to pass
   ShowWindow(hwnd, iCmdShow);              //display the window on the screen
   UpdateWindow(hwnd);             //make sure the window is updated correctly

   while(GetMessage(&msg, NULL, 0, 0))      //message loop
   {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
   }
   return msg.wParam;
}

LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
   switch(msg)
   {
       case WM_DESTROY:
           PostQuitMessage(0);
           return 0;
   }
   return DefWindowProc(hwnd, msg, wParam, lParam);
}
c winapi
4个回答
7
投票

注册窗口类时,它可以是全局的(设置为CS_GLOBALCLASS样式),也可以是注册它的模块的本地。对于全局类,类名必须是唯一的,但对于模块本地类,类名可以冲突 - 没有什么能阻止两个DLL注册同名的窗口类,并且可执行文件可以加载这两个DLL。

因此,您需要告诉CreateWindow函数您要使用哪个模块的命名类实例来创建窗口。


3
投票

对于32位(和64位)Windows,hInstance可用于标识窗口类所属的DLL。这对全球课程很有用(参见Jonathan Potter的答案)。

在这种情况下,hInstance必须是DLL的句柄,而不是WinMain()函数的hInstance参数。

见这里:http://blogs.msdn.com/b/oldnewthing/archive/2005/04/18/409205.aspx

但是我确信这个论点存在的第二个原因是:

在16位Windows中,这个论点肯定是必需的。当从16位更改为32位Windows时,Microsoft希望尽可能少地更改以保持源代码兼容性。因此,hInstance参数尚未删除。


1
投票

结构中的HINSTANCE hInstance;WNDCLASS结构的一个元素。可以通过创建结构WNDCLASS的对象来启动或分配结构的该元素。虽然CreateWindow是一个函数调用,你已经通过HINSTANCE hInstance作为参数,如果不是NULL,函数将使用此参数来执行某项任务。

要了解HINSTANCE的作用,请点击此Link


-1
投票

hInstance-struct(WNDCLASS)中的link是根据MSDN

包含该类的窗口过程的实例的句柄。

而对于CreateWindowlink)称之为

要与窗口关联的模块实例的句柄。

正如@IInspectable在评论中提到的,这与应用本地类的class lookup相关:

  1. 在应用程序本地类的列表中搜索具有指定名称的类,该实例句柄与模块的实例句柄匹配。 (几个模块可以使用相同的名称在同一个进程中注册本地类。)[...]

所以基本上本地类查找只有在你将它设置为相同的值时才有效。

© www.soinside.com 2019 - 2024. All rights reserved.