Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does CreateWindow() take a hInstance as an argument if was already provided when the window class was registered?

Tags:

c

winapi

When registering a window class, it's necessary to fill in the WNDCLASSstruct, which has a hInstance field:

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

Then, the window is created using CreateWindow() which takes in these parameters:

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

  • If the hInstance was provided with WNDCLASS when the class was registered, why is it necessary to provide a hInstance to CreateWindow()?

  • Is the hInstance provided to WNDCLASS supposed to be same as the hInstance provided to CreateWindow()?

  • If the WNDCLASS hInstance and the CreateWindow() hInstance are different, what do they mean?


Here is a sample program demonstrating class registration / window creation:

#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);
}
like image 415
sadjezz Avatar asked Jan 12 '23 20:01

sadjezz


1 Answers

When a window class is registered it can be global (the CS_GLOBALCLASS style is set) or local to the module that registers it. For global classes the class names must be unique but for module-local classes the class names can clash - there's nothing stopping two DLLs registering window classes of the same name, and an executable could load both of those DLLs.

You therefore you need to tell the CreateWindow function which module's instance of the named class you want to use to create the window.

like image 72
Jonathan Potter Avatar answered Jan 14 '23 10:01

Jonathan Potter