1 (изменено: Malcev, 2024-02-16 09:42:03)

Тема: AHK: Установить поверх всех окон в Windows 10 с помощью SetWindowBand

Вот ссылка на этот api, работа очень хорошего реверс-инженера ADeltaX.
https://blog.adeltax.com/window-z-order-in-windows-10/
Чтобы вызвать SetWindowBand, нам нужно заинжектить dll в explorer.exe и либо установить хук на SetWindowBand и показать стартовое меню, либо установить хук на NtUserEnableIAMAccess и перехватить iam ключ.
https://blog.adeltax.com/how-to-call-setwindowband/
Вот скрипт, который инжектит autohotkey.dll и устанавливает хук с помощью minhook.dll
Нужно скачать minhook враппер от tmplinshi.
https://github.com/tmplinshi/MinHook-AHK
И запустить следующий код из папки с примерами.
Нажатие f11 установит самый высокий window band в активное окно, равный osk или окну лупы.

SetWorkingDir %A_ScriptDir%
#NoEnv
#Persistent
#SingleInstance Force
if (A_Is64bitOS && A_PtrSize = 4)
{
   Run, %A_AhkPath%\..\AutoHotkeyU64.exe "%A_ScriptFullPath%", %A_ScriptDir%
   ExitApp
}

f11::
ourHwnd := WinExist("A")
ourBand := 2   ; ZBID_UIACCESS

code =
(LTrim
   SetWorkingDir, %A_ScriptDir%
   #Include %A_ScriptDir%\Lib\MinHook.ahk
   address_SetWindowBand := DllCall("GetProcAddress", Ptr, DllCall("GetModuleHandle", Str, "user32", "Ptr"), AStr, "SetWindowBand", "Ptr")
   hook1 := New MinHook("", address_SetWindowBand, "SetWindowBand_Hook")
   hook1.Enable()
   return

   SetWindowBand_Hook(hWnd, hwndInsertAfter, dwBand)
   {
      global hook1
      return DllCall(hook1.original, "ptr", %ourHwnd%, "ptr", 0, "uint", %ourBand%)
   }
)
codeUnhook =
(LTrim
   hook1.Disable()
   hook1 := ""
)

shellHwnd := DllCall("GetShellWindow", "ptr")
WinGet, pid, PID, ahk_id %shellHwnd%
dllFile := FileExist("AutoHotkeyMini.dll") ? A_ScriptDir "\AutoHotkeyMini.dll"
          : (A_PtrSize = 8)                  ? A_ScriptDir "\ahkDll\x64\AutoHotkeyMini.dll"
          : A_ScriptDir "\ahkDll\x32\AutoHotkeyMini.dll"
rThread := InjectAhkDll(pid, dllFile, "")
rThread.Exec(code)
AppVisibility := ComObjCreate(CLSID_AppVisibility := "{7E5FE3D9-985F-4908-91F9-EE19F9FD1514}", IID_IAppVisibility := "{2246EA2D-CAEA-4444-A3C4-6DE827E44313}")
loop 2
{
   if (A_Index = 1)
      visible := 1
   else
      visible := 0
   loop
   {
      send {LWin down}
      sleep 50
      send {LWin up}
      loop 200   ; wait no more than 2 seconds
      {
         if (DllCall(NumGet(NumGet(AppVisibility+0)+4*A_PtrSize), "Ptr", AppVisibility, "Int*", fVisible) = 0)
         {
            if (fVisible = visible)
               break 2
            sleep 10
         }
      }
   }
}
ObjRelease(AppVisibility)
rThread.Exec(codeUnhook)
rThread:=""
return

Пример c перехватом iam ключа.
После запуска скрипта следует дождаться сообщения iam key received.
После чего понажимать f11, f12, которые меняют band активного окна:

SetWorkingDir %A_ScriptDir%
#NoEnv
#SingleInstance Force
setbatchlines -1
OnExit, ExitSub
if (A_Is64bitOS && A_PtrSize = 4)
{
   Run, %A_AhkPath%\..\AutoHotkeyU64.exe "%A_ScriptFullPath%", %A_ScriptDir%
   ExitApp
}
global g_iam_key, NtUserEnableIAMAccess
MsgNum := DllCall("RegisterWindowMessage", "str", "NewAHKScript")
OnMessage(MsgNum, "dataReceived")
SetWindowBand := DllCall("GetProcAddress", "ptr", DllCall("GetModuleHandle", "str", "user32", "ptr"), "astr", "SetWindowBand", "ptr")
Gui, temp:-Caption +ToolWindow +hwndhTemphwnd
Gui, temp:show, % "x" A_ScreenWidth/2 " y" A_ScreenHeight/2 " w1 h1"
code =
(LTrim
   SetWorkingDir, %A_ScriptDir%
   #Include %A_ScriptDir%\Lib\MinHook.ahk
   address_NtUserEnableIAMAccess := DllCall("GetProcAddress", "ptr", DllCall("GetModuleHandle", "str", "user32", "ptr"), "ptr", 2510, "ptr")
   hook := New MinHook("", address_NtUserEnableIAMAccess, "NtUserEnableIAMAccess_Hook")
   hook.Enable()
   return

   NtUserEnableIAMAccess_Hook(key, enable)
   {
      global hook
      static g_iam_key
      hr := DllCall(hook.original, "uint64", key, "int", enable)
      if hr and !g_iam_key
      {
         g_iam_key := key
         DllCall("PostMessage", "uptr", %A_ScriptHwnd%, "uint", %MsgNum%, "ptr", hook.original, "ptr", g_iam_key)
      }
   }
)
shellHwnd := DllCall("GetShellWindow", "ptr")
WinGet, pid, PID, ahk_id %shellHwnd%
dllFile := FileExist("AutoHotkeyMini.dll") ? A_ScriptDir "\AutoHotkeyMini.dll"
          : (A_PtrSize = 8)                  ? A_ScriptDir "\ahkDll\x64\AutoHotkeyMini.dll"
          : A_ScriptDir "\ahkDll\x32\AutoHotkeyMini.dll"
rThread := InjectAhkDll(pid, dllFile, "")
rThread.Exec(code)
loop
{
   WinActivate, ahk_id %hTemphwnd%
   WinWaitActive, ahk_id %hTemphwnd%,, 1
   WinActivate, ahk_class Shell_TrayWnd
   WinWaitActive, ahk_class Shell_TrayWnd,, 1
   if (g_iam_key != "")
      break
   sleep 10
}
code =
(LTrim
   hook.Disable()
   hook := ""
)
rThread.Exec(code)
OnMessage(MsgNum, "")
Gui, temp:destroy
msgbox iam key received
return

dataReceived(wParam, lParam, msg, hwnd)
{
   NtUserEnableIAMAccess := wParam
   g_iam_key := lParam
}

ExitSub:
if isObject(rThread)
   rThread := ""
ExitApp

f11::
hwnd := WinExist("A")
code = 
(
DllCall(%NtUserEnableIAMAccess%, "uint64", %g_iam_key%, "int", 1)
DllCall(%SetWindowBand%, "uptr", %hwnd%, "ptr", 0, "uint", ZBID_UIACCESS := 2)
DllCall(%NtUserEnableIAMAccess%, "uint64", %g_iam_key%, "int", 0)
)
rThread.Exec(code)
return

f12::
hwnd := WinExist("A")
code = 
(
DllCall(%NtUserEnableIAMAccess%, "uint64", %g_iam_key%, "int", 1)
DllCall(%SetWindowBand%, "uptr", %hwnd%, "ptr", 0, "uint", ZBID_DESKTOP := 1)
DllCall(%NtUserEnableIAMAccess%, "uint64", %g_iam_key%, "int", 0)
)
rThread.Exec(code)
return

Тема для обсуждения