學習Windows程序設計時,看見CreateWindows中有參數HINSTANCE,但不知道其用途,因而上網搜得兩資料,而且,得出結果是,用於區分不一樣的應用實例。html
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).windows
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
.less
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 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.ide
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'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.ui
In 16-bit Windows, the instance handle did other things, too, but they are no longer relevant to Win32.spa
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
.翻譯
來自: 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 註冊窗口類的後果了。