译:传递给 CreateWindow 和 RegisterClass 的 HINSTANCE 有什么用?

译者按:老汉当初学习 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,窗口管理器使用实例句柄和窗口类的组合来寻找窗口类。

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

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

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

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

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

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注