Autoit 問題解決

Autoit|解決!管理者として実行するとドラッグ&ドロップができない

Autoit で作成したプログラムの実行時に、管理者として実行をするとドラッグ&ドロップができなくて困ったことがありませんか?

原因は、Windows Vista/Windows Server 2008から追加されたユーザーインターフェイス特権の分離(UIPI)です。

現在実行しているユーザーより権限が上の管理者で実行すると、メッセージが阻止されてしまいます。

今回は、これを回避するコードを紹介します。

サンプルコード

If IsAdmin() Then _ChangeWindowMessageFilterEx($Gui, $WM_DROPFILES, 1) _ChangeWindowMessageFilterEx($Gui, $WM_COPYDATA, 1) _ChangeWindowMessageFilterEx($Gui, $WM_COPYGLOBALDATA, 1) EndIf Func _ChangeWindowMessageFilterEx($hwnd, $iMsg, $iAction) Local $aCall = DllCall("user32.dll", "bool", "ChangeWindowMessageFilterEx", _ "hwnd", $hwnd, _ "dword", $iMsg, _ "dword", $iAction, _ "ptr", 0) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) Return 1 EndFunc ;==>_ChangeWindowMessageFilterEx

コードの解説

If IsAdmin() Then; もしも管理者として実行したなら _ChangeWindowMessageFilterEx($Gui, $WM_DROPFILES, 1); WM_DROPFILESのメッセージ受信を許可します。 ;<WindowsConstants.au3>をインクルードする必要があります。 _ChangeWindowMessageFilterEx($Gui, $WM_COPYDATA, 1); WM_COPYDATAのメッセージ受信を許可します。 _ChangeWindowMessageFilterEx($Gui, $WM_COPYGLOBALDATA, 1); WM_COPYGLOBALDATAのメッセージ受信を許可します。 EndIf

$Gui の部分はメインウィンドウのハンドルを指定します。

ユーザー定義関数

ユーザー定義関数 「_ChangeWindowMessageFilterEx」を作成します。

関数とは、引数と呼ばれるデータを受け取り、定められた通りの処理を実行して結果を返す一連の命令群を言います。

詳しくはAutoit の基礎 – 関数をご覧ください。

Func _ChangeWindowMessageFilterEx($hwnd, $iMsg, $iAction); ユーザー定義関数はここから Local $aCall = DllCall("user32.dll", "bool", "ChangeWindowMessageFilterEx", "hwnd", $hwnd, _ "dword", $iMsg, _ "dword", $iAction, _ "ptr", 0); DLL内の関数を呼び出して実行します。 If @error Or Not $aCall[0] Then Return SetError(1, 0, 0); もしもエラーフラグ、または$aCall[0]がTRUEならば(@error、@extended、戻り値に)指定した値を設定します。 Return 1; 返し値「1」を返します。 EndFunc; ユーザー定義関数はここまで

注意事項

  1. プログラムを初めから管理者として実行する場合、コードの初めにキーワード「#RequireAdmin」を追加する必要があります。
  2. GUISetState() でウィンドウを表示した後にメッセージ許可のコードを記述します。
#RequireAdmin #include <Misc.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiListView.au3> If _Singleton("WRCMenu", 1) = 0 Then MsgBox(0, "WRCMenu", "既に起動しています") Exit EndIf;==>ここまで Opt("TrayIconHide", 1) $Gui = GUICreate("WRCMenu", 430, 100, -1, -1, -1, $WS_EX_ACCEPTFILES) $Input_1 = GUICtrlCreateInput("", 10, 5, 340, 20) GUICtrlSetState($Input_1, $GUI_DROPACCEPTED) $Input_2 = GUICtrlCreateInput("", 10, 35, 340, 20) $btn = GUICtrlCreateButton("開く", 360, 5, 60, 20) $btn2 = GUICtrlCreateButton("追加", 360, 35, 60, 20) $btn3 = GUICtrlCreateButton("メニューリスト", 10, 65, 410, 20) GUISetState() If IsAdmin() Then ; 管理者として実行した場合にメッセージの受信を許可します _ChangeWindowMessageFilterEx($Gui, $WM_DROPFILES, 1) _ChangeWindowMessageFilterEx($Gui, $WM_COPYDATA, 1) _ChangeWindowMessageFilterEx($Gui, $WM_COPYGLOBALDATA, 1) EndIf While 1 $msg = GUIGetMsg() Select Case $msg = $GUI_EVENT_CLOSE Exit Case $msg = $btn3 $Form1 = GUICreate("メニューリスト", 300, 300, -1, -1, -1, -1, $Gui) $ListView1 = GUICtrlCreateListView("追加されているメニュー", 10, 10, 280, 250) _GUICtrlListView_SetColumnWidth($ListView1, 0, 280) $btn4 = GUICtrlCreateButton("削除", 10, 265, 280, 25) GUISetState(@SW_SHOW) While 1 $msgg = GUIGetMsg() Select Case $msgg = $GUI_EVENT_CLOSE GUIDelete($Form1) ExitLoop EndSelect WEnd EndSelect WEnd Func _ChangeWindowMessageFilterEx($hwnd, $iMsg, $iAction) Local $aCall = DllCall("user32.dll", "bool", "ChangeWindowMessageFilterEx", _ "hwnd", $hwnd, _ "dword", $iMsg, _ "dword", $iAction, _ "ptr", 0) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) Return 1 EndFunc

メッセージ許可のコードを記述した場合と、記述しない場合の違いを確認してみてください。

コメント