天天看點

關于WinMain函數的第二個參數解釋

請牢記:hPrevInstance始終為空

當一個GUI應用程式開始運作時,控制流會從WinMain函數開始。它的第二個參數,hPrevInstance,在Win32應用程式中永遠為0。這個參數有什麼特殊之處嗎?

當然有。

在早期的16位Windows時代,曾經有一個名叫GetInstanceData的API函數。這個函數有一個HINSTANCE參數,一個指針,一個長度參數,以及一塊用于拷貝執行個體到目前執行個體的記憶體塊。(它有點類似16位版本的ReadProcessMemory,隻是會有個第二個和第三個參數必須相同的限制)

因為16位Windows有一個共享的位址空間,GetInstanceData實際上就相當于hmemcpy的操作,許多程式會依賴這個原理,并使用原始的hmemcpy,而不是文檔化的API。

Win16實際上被設計為可以在将來使用獨立的位址空間,你會發現有類似GMEM_SHARED這樣的标志,但是類似使用hmemcpy拷貝之前的執行個體這種方法被大量使用,使這種潛力變成了無法實作的夢想。

這就是為什麼在設計WinMain函數時會添加一個hPrevInstance參數的原因。如果

hPrevInstancehPrevInstance非空,則它表明目前執行個體是從一個已經運作的執行個體中拷貝過來的。

你可以使用GetInstanceData來從中拷貝資料,然後進行快速的啟動。

舉個例子,你可能想從前一個執行個體中拷貝主視窗句柄,這樣就可以和它進行通信了。通過判斷hPrevInstance是否為空,可以知道目前是否運作的是程式的第一個執行個體。在16位Windows中,隻有應用程式的第一個執行個體會注冊視窗類,而後續的執行個體僅僅會使用在第一個執行個體中注冊的視窗類,而不會重新注冊。(當然了,如果後續執行個體還是嘗試注冊,也會失敗,因為目标視窗類已經存在于系統中了)

是以,當hPrevInstance為非空的時候,所有16位Windows應用程式會跳過視窗類的注冊過程。

Win32的設計者在嘗試移植WinMain的時候,碰到這樣一個問題:應該向hPrevInstance參數傳遞什麼值?畢竟,Win32中不存在16位系統中的那些有關子產品,執行個體的概念。而32位系統中,每個應用程式都有獨立的位址空間,是以那些跳過初始化的後續執行個體不會正常工作。

是以,在Win32中,系統始終向hPrevInstance傳遞NULL值,這樣,所有應用程式都會相信自己是第一個執行個體,這樣,所有的初始化操作就不會被跳過了。

總結

最後

繼續閱讀