最終更新日 :
VB Tips

xxxProp() API

WindowsAPIの中にxxxProp()というProperty系のAPIがあります。 このAPIは、あるウィンドウにキーワードと値(プロパティとデータ)をセットにして埋め込むというAPIです。
この関数を利用すれば、メッセージフックをVB5で簡単にしたり(VB Magazine参照)、またレジストリと組み合わせると、2重起動チェックに応用できたりします。

構文
Declare Function GetProp Lib "user32" Alias "GetPropA" (ByVal hwnd As Long, ByVal lpString As String) As Long
Declare Function SetProp Lib "user32" Alias "SetPropA" (ByVal hwnd As Long, ByVal lpString As String, ByVal hData As Long) As Long
Declare Function RemoveProp Lib "user32" Alias "RemovePropA" (ByVal hwnd As Long, ByVal lpString As String) As Long

Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long

レジストリを利用した2重起動チェック
1.なぜこの方法なのか?
2重起動の方法にもいろいろあります。
例えば、Win3.1で使われていた(Win95で使用不可能な)GetModuleUsage()を使う方法や、現在代表的なFindWindow()を使う方法、 Toolhelp関数を利用する方法、そしてApp.PrevInstanceなどがあります。
しかし、App.PrevInstanceよりも応用がしやすく、簡単な方法を見つけました。それが、「レジストリの利用」です。
2.この方法のシステム
レジストリは、アプリケーションのインスタンスが共通して利用するデータベースです。
VBでは、GetSetting関連のレジストリ関数が存在します。プロパティAPIとレジストリ関数を利用して、アプリケーションの"複数起動制限"を掛けることができます。
3.フォームのロード時(もしくは、Sub Main()実行中)の処理
(先に項目4を読んでおかれることをお勧めします)
フォームをロードする前(ロード中)に、レジストリをチェックします。

Wnd = GetSetting(App.EXEName, DCheck, "PrevWnd", 0)
(レジストリのサブキーは、Const DCheck = "doublecheck"、値はウィンドウハンドル hWnd になっています。)

そして、そのハンドルが利用可能か(ウィンドウとして存在しているか IsWindow()APIで)を調べます。(異常終了などでレジストリにデータが残る場合を考慮して)
存在していれば、GetProp()関数を利用して、「傷があるか」どうか調べます。なければ、現在実行中のコードが第1号であることが決定します。
傷がある場合は、SetForegroundWindow()APIを利用して、そのウィンドウをアクティブにした後、終了処理(もちろんレジストリはいじらない)を実行します。
4.レジストリに起動データを書き込む
レジストリにデータがない場合や、得られたウィンドウに傷がない場合(つまり第1号の場合)は、レジストリにデータを書き込み、ウィンドウに傷を付けます。

Wnd = MainWindow.hwnd
SetProp Wnd, DCheck, Wnd
SaveSetting App.EXEName, DCheck, "PrevWnd", CStr(Wnd)

上の、SetProp()APIでウィンドウに傷(起動チェック対象の証)を付けます。そして、そのウィンドウのウィンドウハンドルをレジストリに書き込みます。
ここでは、チェックしやすいように、ウィンドウハンドルをプロパティ値として利用しています。
この処理を済ませた後、通常の起動処理に入ります。
フォームのアンロード時に、RemoveProp()関数を実行するのを忘れないでください。レジストリの消去は、忘れてもチェックの段階でわかるので忘れてもいいですが。
応用
さらに、レジストリは利用するキーがわかっていれば、どのアプリケーションからでも簡単に見ることができます(Win95では)。
それを利用してVBアプリなら、共通のチェックシステム(レジストリのサブキーの名前などをそろえたりする)を作っておいて、他のアプリケーションの起動チェックに利用したりできます。(VBアプリでなければ、レジストリAPIを利用するしかない)
また、レジストリへの記録方法や、チェックの方法を変えることによって、2重起動だけでなく、起動する数を4つや5つなどの別の数に変えることも可能になります。
レジストリの消去をしなければ起動回数のチェックに、起動制限の代わりに起動数のカウントにも応用できます。

サンプル : VB5-SP3
以下は2重起動チェックのサンプルコードです。貼り付けるなどして利用してください。

Private Function CheckDoubleRun(MainWindow As Form) As Boolean
' 二重起動チェック
Dim Wnd As Long, dat As Long, NotDouble As Boolean

Wnd = GetSetting(App.EXEName, DCheck, "PrevWnd", 0)
If IsWindow(Wnd) Then
' ウィンドウのデータチェック
dat = GetProp(Wnd, DCheck)
NotDouble = Not (dat = Wnd)
Else
NotDouble = True
End If

If NotDouble Then
' ウィンドウのデータを書き込む
Wnd = MainWindow.hwnd
SetProp Wnd, DCheck, Wnd
SaveSetting App.EXEName, DCheck, "PrevWnd", CStr(Wnd)
CheckDoubleRun = True
Else
SetForegroundWindow Wnd
CheckDoubleRun = False
End If

End Function

Copyright (C) 1998 Satoshi Tadaフィードバックはこちら
Home