What is the HINSTANCE passed to CreateWindow and RegisterClass used for?

Date:April 18, 2005 / year-entry #96
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20050418-59/?p=35873
Comments:    10
Summary:One of the less-understood parameters to the CreateWindow function and the RegisterClass function is the HINSTANCE (either passed as a parameter or as part of the WNDCLASS structure). The window class name is not sufficient to identify the class uniquely. Each process has its own window class list, and each entry in the window class...

One of the less-understood parameters to the CreateWindow function and the RegisterClass function is the HINSTANCE (either passed as a parameter or as part of the WNDCLASS structure).

The window class name is not sufficient to identify the class uniquely. Each process has its own window class list, and each entry in the window class list consists of an instance handle and a class name. For example, here's what the window class list might look like if a program has two DLLs, both of which register a class name "MyClass", passing the DLL's handle as the HINSTANCE.

HINSTANCE Class name
1. USER32.DLL Static
2. USER32.DLL Button
3. USER32.DLL Listbox
4. USER32.DLL Combobox
5. USER32.DLL Edit
6. A.DLL MyClass
7. B.DLL MyClass

When it comes time to create a window, each module then passes its own HINSTANCE when creating the window, and the window manager uses the combination of the instance handle and the class name to look up the class.

CreateWindow("MyClass", ..., hinstA, ...); // creates class 6
CreateWindow("MyClass", ..., hinstB, ...); // creates class 7
CreateWindow("MyClass", ..., hinstC, ...); // fails

This is why it is okay if multiple DLLs all register a class called "MyClass"; the instance handle is used to tell them apart.

There is an exception to the above rule, however. If you pass the CS_GLOBALCLASS flag when registering the class, then the window manager will ignore the instance handle when looking for your class. All of the USER32 classes are registered as global. Consequently, all of the following calls create the USER32 edit control:

CreateWindow("edit", ..., hinstA, ...);
CreateWindow("edit", ..., hinstB, ...);
CreateWindow("edit", ..., hinstC, ...);

If you are registering a class for other modules to use in dialog boxes, you need to register as CS_GLOBALCLASS, because as we saw earlier the internal CreateWindow call performed during dialog box creation to create the controls passes the dialog's HINSTANCE as the HINSTANCE parameter. Since the dialog instance handle is typically the DLL that is creating the dialog (since that same HINSTANCE is used to look up the template), failing to register with the CS_GLOBALCLASS flag means that the window class lookup will not find the class since it's registered under the instance handle of the DLL that provided the class, not the one that is using it.

In 16-bit Windows, the instance handle did other things, too, but they are no longer relevant to Win32.

A common mistake is to pass the HINSTANCE of some other module (typically, the primary executable) when registering a window class. Now that you understand what the HINSTANCE is used for, you should be able to explain the consequences of registering a class with the wrong HINSTANCE.


Comments (10)
  1. waleri says:

    MSDN says otherwise:

    ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/createwindow.asp

    In your own scratch program you pass HINSTANCE received as an argument in WinMain for both registering and creating class.

    ref: http://blogs.msdn.com/oldnewthing/archive/2003/07/23/54576.aspx

    Am I missing something?

  2. waleri says:

    errata:

    "…for both registering and creating class" should read "..for both registering class and creating window"

  3. david says:

    On a related note, what should I pass as the class name if I want to use CreateWindowEx to create a dialog box? For various reasons I don’t want to use the default functions but I can’t seem to find a class name it’s happy with!

    Very helpful series of articles though :-) Thanks!

  4. CornedBee says:

    MSDN says:

    hInstance

    [in] Windows 95/98/Me: Handle to the instance of the module to be associated with the window.

    Windows NT/2000/XP: This value is ignored.

    So for 9x this hold true. For NT, then, I wonder how classes get separated there. What happens in NT if two modules register the same class name?

    And as for the scratch program, that’s OK. What Raymond meant with the common mistake is that you should always pass the HINSTANCE of the code you’re in. The scratch program is always in the main EXE, so it should pass the HINSTANCE of the main EXE as well.

  5. CornedBee: That’s a doc bug; I’ve submitted a correction. All versions of Windows have always used the HINSTANCE to identify the class.

  6. Mike Dimmick says:

    David: IIRC, IsDialogMessage is perfectly happy with windows that are not created via CreateDialog. The answer is therefore ‘any class you like.’

    Raymond has made many, many posts on the behaviour of the dialog manager and modal loops; if you read those posts you should be able to work out how to emulate the dialog’s window procedure.

  7. Robert says:

    "Windows NT/2000/XP: This value is ignored."

    The MSDN doc for CreateWindow also incorrectly states that if the x parameter is set to CW_USEDEFAULT, the system ignores the y parameter. What really happens is described here:

    http://msdn.microsoft.com/library/en-us/dnwui/html/msdn_styles32.asp

  8. Ben Cooke says:

    I one wrote a program — a quick and dirty one, of course — that created a window class and a window in an awkward place where a HINSTANCE wasn’t readily available. I passed them in as zero, and it appeared to work. Of course, I only ever ran this program on my Windows 2000 machine, so who knows what it would do elsewhere.

  9. Chris Becke says:

    Passing NULL or 0 as an HINSTANCE on Windows NT usually is interpreted to mean GetModuleHandle() – i.e. NT uses the apps HINSTANCE.

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index