Code: Select all
cadmaticWindow := UIA.ElementFromHandle("Project ahk_exe UIManager.exe")
cadmaticWindow.WaitElement({Type:"Button",Name:buttonName},timeOut := 1000)
UnFreeze(NextStuff, 200)
cadmaticWindow.FindElement({Type:"Button",Name:buttonName}).Click()
return
NextStuff() {
MsgBox("This line is never reached")
DetectSaveWindow
return succes := true
}
UnFreeze(userFunc, timeOut) {
static SYNCHRONIZE := 0x100000, hGui, oInfo := {}
OnMessage( msg := DllCall("RegisterWindowMessage", "Str", "WM_INFO"), WM_INFO.Bind(oInfo) )
if !IsSet(hGui)
hGui := Gui()
hProc := DllCall("OpenProcess", "UInt", SYNCHRONIZE, "UInt", 0, "UInt", DllCall("GetCurrentProcessId"), "Ptr")
pPtr := GetProcAddr(hProc, hGui.Hwnd, msg, timeOut)
oInfo.func := userFunc, oInfo.hProc := hProc
DllCall("CreateThread", "Ptr", 0, "Ptr", 0, "Ptr", pPtr, "Ptr", 0, "UInt", 0, "Ptr", 0)
}
WM_INFO(oInfo, *) {
DllCall("CloseHandle", "Ptr", oInfo.hProc)
oInfo.func.Call()
}
GetProcAddr(Handle, hWnd, Msg, Timeout:=-1) { ; на основе http://forum.script-coding.com/viewtopic.php?pid=56073#p56073
static MEM_COMMIT := 0x1000, PAGE_EXECUTE_READWRITE := 0x40
ptr := DllCall("VirtualAlloc", "Ptr", 0, "Ptr", A_PtrSize = 4 ? 49 : 85, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
, hModule := DllCall("GetModuleHandle", "Str", "kernel32.dll", "Ptr")
, pWaitForSingleObject := DllCall("GetProcAddress", "Ptr", hModule, "AStr", "WaitForSingleObject", "Ptr")
, hModule := DllCall("GetModuleHandle", "Str", "user32.dll", "Ptr")
, pSendMessageW := DllCall("GetProcAddress", "Ptr", hModule, "AStr", "SendMessageW", "Ptr")
, NumPut("ptr", pWaitForSingleObject, ptr*1)
, NumPut("ptr", pSendMessageW, ptr + A_PtrSize)
if (A_PtrSize = 4) {
NumPut("UChar", 0x68, ptr + 8)
, NumPut("Uint", Timeout, ptr + 9), NumPut("UChar", 0x68, ptr + 13)
, NumPut("ptr", Handle, ptr + 14), NumPut("UShort", 0x15FF, ptr + 18)
, NumPut("ptr", ptr, ptr + 20), NumPut("UShort", 0x6850, ptr + 24)
, NumPut("ptr", Handle, ptr + 26), NumPut("UChar", 0x68, ptr + 30)
, NumPut("UInt", Msg, ptr + 31), NumPut("UChar", 0x68, ptr + 35)
, NumPut("ptr", hWnd, ptr + 36), NumPut("UShort", 0x15FF, ptr + 40)
, NumPut("ptr", ptr+4, ptr + 42), NumPut("UChar", 0xC2, ptr + 46), NumPut("UShort", 4, ptr + 47)
} else {
NumPut("UChar", 0x53, ptr + 16)
, NumPut("UInt", 0x20EC8348, ptr + 17), NumPut("UInt", 0xBACB8948, ptr + 21)
, NumPut("UInt", Timeout, ptr + 25), NumPut("UShort", 0xB948, ptr + 29)
, NumPut("UPtr", Handle, ptr + 31), NumPut("UShort", 0x15FF, ptr + 39)
, NumPut("UInt", -45, ptr + 41), NumPut("UShort", 0xB849, ptr + 45)
, NumPut("UPtr", Handle, ptr + 47), NumPut("UChar", 0xBA, ptr + 55)
, NumPut("UInt", Msg, ptr + 56), NumPut("UShort", 0xB948, ptr + 60)
, NumPut("UPtr", hWnd, ptr + 62), NumPut("UInt", 0xC18941, ptr + 70)
, NumPut("UShort", 0x15FF, ptr + 73), NumPut("UInt", -71, ptr + 75)
, NumPut("UInt", 0x20C48348, ptr + 79), NumPut("UShort", 0xC35B, ptr + 83)
}
return ptr + A_PtrSize*2
}
to figure out whether UnFreeze is necessary at all.
EDIT: you could also try running Invoke in an actually new thread. Something like this:
Code: Select all
cadmaticWindow := UIA.ElementFromHandle("Project ahk_exe UIManager.exe")
el := cadmaticWindow.WaitElement({Type:"Button",Name:buttonName},timeOut := 1000)
hProc := DllCall("OpenProcess", "UInt", 0x100000, "UInt", 0, "UInt", DllCall("GetCurrentProcessId"), "Ptr")
hThread := DllCall("CreateThread", "Ptr", 0, "Ptr", 0, "Ptr", NumGet(NumGet(el.InvokePattern.ptr, "Ptr"), 3*A_PtrSize, "ptr"), "Ptr", el.InvokePattern.ptr, "UInt", 0, "Ptr", 0) ; Run Invoke in a new thread
timeOut := A_TickCount+3000
While (DllCall("WaitForSingleObject", "Ptr", hThread, "Int", 200) != 0 && A_TickCount < timeOut) ; Wait maximum three seconds for thread to terminate
Sleep 40
DllCall("CloseHandle", "Ptr", hProc) ; Maybe should terminate thread beforehand?