学习Windows程序设计时,看见CreateWindows中有参数HINSTANCE,但不知道其用途,于是上网搜得两资料,并且,得出结果是,用于区分不同的应用实例。


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


One of the less-understood parameters to the CreateWindow function and theRegisterClass function is the HINSTANCE (either passed as a parameter or as part ofthe 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.


HINSTANCEClass name
1.USER32.DLLStatic
2.USER32.DLLButton
3.USER32.DLLListbox
4.USER32.DLLCombobox
5.USER32.DLLEdit
6.A.DLLMyClass
7.B.DLLMyClass

When it comes time to create a window, each module then passes its ownHINSTANCE 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_GLOBALCLASSflag 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'sHINSTANCE 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.

Published Monday, April 18, 2005 4:47 AM by oldnewthing Filed under: Code


来自: http://zouxiaochuan.bokee.com/6551054.html



译者按:老汉当初学习 Windows 编程的时候就对此问题有过疑惑,后来明白了,却懒得写一篇总结性的东西。这是在 The Old New Thing 的 Blog 上发现的,翻译过来,权且为新手释疑。原文的链接为 http://blogs.msdn.com/oldnewthing/archive/2005/04/18/409205.aspx

CreateWindow 函数和 RegisterClass 函数(译者注:以及这两个函数相应的 Ex 后缀版本)中很少被人理解的一个参数是 HINSTANCE(或者作为参数传递或者作为 WNDCLASS 结构的一部分)。

窗口类名不足以唯一地标志窗口类。每个进程有自己的窗口类列表,窗口类列表中的每一项都由一个实例句柄和一个类名字组成。例如,如果一个程序有两个 DLL,每个都注册了一个名为“MyClass”的窗口类,并且将 DLL 的句柄作为 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 

当要创建窗口时,每个模块传递它自己的 HINSTANCE,窗口管理器使用实例句柄和窗口类的组合来寻找窗口类。


CreateWindow("MyClass", ..., hinstA, ...); // 创建窗口类 6 CreateWindow("MyClass", ..., hinstB, ...); // 创建窗口类 7 CreateWindow("MyClass", ..., hinstC, ...); // 失败 

这就是为什么多个 DLL 都创建名为“MyClass”的类可以成功,实例句柄用来将它们区别开来。

但是上述规则有一个例外。如果在你注册窗口类时指定了 CS_GLOBALCLASS 标志,那么窗口管理器在寻找你的窗口类时将忽略实例句柄。所有的 USER32 窗口类都被注册为全局的。因而,下面所有的调用都会创建 USER32 的编辑框控件:


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

如果你要注册一个用在其他模块的对话框里的窗口类,你就需要注册为 CS_GLOBALCLASS,因为像我们先前看到的,在对话框创建过程中,创建控件执行的内部 CreateWindow 调用会把对话框的 HINSTANCE 用作 HINSTANCE 参数。因为对话框的实例句柄通常是创建该对话框的 DLL(因为相同的 HINSTANCE 要用来寻找对话框模板),不使用 CS_GLOBALCLASS 标志注册意味着寻找窗口类时将不能找到该类,因为它注册于提供该窗口类的 DLL 的实例句柄名下而不是使用它的那个。

在 16 位 Windows 中,实例句柄还要用来做其他事情,但在 Win32 里已经没有关系了。

一个常见的错误是在注册窗口类时传递一些其他的 HINSTANCE 进去(典型地,主执行程序的)。现在了解了 HINSTANCE 的用途,你就应该能够解释用错误的 HINSTANCE 注册窗口类的后果了。


来自:http://blog.sina.com.cn/s/blog_538457490100mhj8.html