为什么需要传递HINSTANCE给CreateWindow?

为什么需要传递HINSTANCE给CreateWindow?

作者:BlogUpdater |  时间:2022-08-29 |  浏览:995 |  评论已关闭 条评论

Win32中有两个API函数,CreateWindow和RegisterClass。它们有一个HINSTANCE参数,很多人对这个参数不是很理解,今天就来讲一讲。

窗口类的名称还不足以唯一地确定这个窗口类。每一个进程都会拥有它自己的窗口类列表,而在这个列表中的每个条目都会包含一个实例句柄和一个窗口类名称。
举个例子,如果一个程序有两个 DLL,这两个 DLL 都注册了一个类名“MyClass”,并将 DLL 的句柄作为 HINSTANCE 传递,则窗口类列表可能如下所示。

在创建窗口的时候,每个模块在创建窗口时都会传递自己的HINSTANCE,窗口管理器使用实例句柄和类名的组合来查找窗口类,代码如下:
CreateWindow(“MyClass”, …, hinstA, …); // 使用A.DLL中的窗口类创建窗口
CreateWindow(“MyClass”, …, hinstB, …); // 使用B.DLL中的窗口类创建窗口
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 注册类所带来的后果。Do you?

总结
理解一个应用程序的骨架:注册窗口类,创建窗口,显示和更新窗口,启动消息循环。
是一名Win32写手的基本要求。
它是桌面应用的基石,很难改变,我们生命中所应该追求的,就是那些很难改变的东西。

最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《What is the HINSTANCE passed to CreateWindow and RegisterClass used for?》

最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。

标签:

评论已关闭。