13

定義WinMainは次のとおりです。

int CALLBACK WinMain(
    _In_ HINSTANCE hInstance,
    _In_ HINSTANCE hPrevInstance,
    _In_ LPSTR     lpCmdLine,
    _In_ int       nCmdShow
);

私が理解していることは次のとおりです。

ただし、1990 年代後半の本でさえ、の使用法に出くわしたことはありません。では、あるとすれば の用途は何であり、正確に何なのでしょうか?hPrevInstancehPrevInstance

4

1 に答える 1

19

それは遺産のことです。Raymond Chen は、 The Old New Thing (2004 年 6 月 15 日付)について適切な説明を提供しています。ここにあります(修正されたリンク付き):

平均的な GUI プログラムが軌道に乗ると、 WinMain 関数で制御が開始されます。2 番目のパラメーター hPrevInstance は、Win32 プログラムでは常にゼロです。確かにそれはある時点で意味がありましたか?

もちろんそうでした。

16 ビット Windows には、GetInstanceData という関数がありました。この関数は、HINSTANCE、ポインター、および長さを取り、そのインスタンスから現在のインスタンスにメモリをコピーしました。(これはReadProcessMemoryに相当する 16 ビットのようなものですが、2 番目と 3 番目のパラメーターは同じでなければならないという制限があります。)

(16 ビット Windows には共通のアドレス空間があったため、GetInstanceData 関数は実際には hmemcpy に過ぎず、多くのプログラムはこれに依存し、文書化された API を使用する代わりに生の hmemcpy を使用していました。将来のバージョンではアドレス空間を分離します - GMEM_SHARED のようなフラグを観察してください - しかし、以前のインスタンスを hmemcpy するようなトリックの普及により、この可能性は未実現の夢にまで減少しました。)

これが、WinMain への hPrevInstance パラメータの理由です。hPrevInstance が NULL でない場合、それは既に実行されているプログラムのコピーのインスタンス ハンドルです。GetInstanceData を使用してそこからデータをコピーすると、すぐに立ち上がることができます。たとえば、メイン ウィンドウ ハンドルを前のインスタンスからコピーして、それと通信できるようにすることができます。

hPrevInstance が NULL であるかどうかによって、プログラムの最初のコピーであるかどうかがわかります。16 ビット Windows では、プログラムの最初のインスタンスのみがそのクラスを登録しました。2 番目以降のインスタンスは、最初のインスタンスによって登録されたクラスを引き続き使用します。(実際、試みたとしても、クラスが既に存在するため、登録は失敗します。) したがって、hPrevInstance が NULL でない場合、すべての 16 ビット Windows プログラムはクラスの登録をスキップしました。

Win32 を設計した人々は、WinMain を移植する段階になったとき、ちょっとした問題に直面しました。hPrevInstance に何を渡すか? 結局のところ、モジュール/インスタンス全体は Win32 には存在しませんでした。別のアドレス空間は、2 番目のインスタンスで再初期化をスキップしたプログラムが機能しなくなることを意味していました。そのため、Win32 は常に NULL を渡し、すべてのプログラムが最初のものであると信じ込ませます。

そして驚くべきことに、それは実際に機能しました。

于 2012-04-25T11:23:34.303 に答える