I played around with this docking, using the latest dll JGR posted. Both the original script and JGR's version suffers from the problem in my PC that sometimes the docked window does not show up; sometimes it appears, but after Alt-Tab-ing to another window and back the docked window is not shown. Even if the docked window is visible, when I click on it, it gets to a funny state: after the next change of applications, it is not shown.
If I activate the docked window with WinActivate, it becomes visible, but stays in the limbo state, that is, it disappears again at task change. I found that the commands in subroutine F12 makes the docked window to work correctly (until I click on it again). You can do it manually, too: open the script's main window (double click on its tray icon) and close it. Activating Notepad will show the docked window correctly, again.
You can call this subroutine periodically, but we ought to find the cause of the problem. Any guesses?
Code:
#SingleInstance Force
#NoEnv
SetBatchLines -1
SetWinDelay -1
OnExit Close
HookDll = wineventhook.dll
Run notepad,,,nPID
WinWait ahk_pid %nPID%
WinGet Dock_HostID, ID, ahk_pid %nPID%
Gui +LastFound -Caption +ToolWindow +Border
Dock_ClientID := WinExist()
Gui Add, Text,,Docked Window
Gui Show
Dock("L","B", "A_DockHostWidth", 0)
GoSub F12
Return
F12::
WinActivate ahk_id %Dock_HostID%
GoSub Dock_Update
Sleep 0
ListVars
Sleep 0
WinHide %A_ScriptFullPath% - AutoHotkey
Return
Close:
WinClose ahk_id %Dock_HostID%
ExitApp
Dock(H="R",V="T", sizeX="", sizeY="", dx=0, dy=0) {
Local hwnd, msg
hwnd := WinExist("ahk_pid " . DllCall("GetCurrentProcessId"))
Dock_msg := 0x550
Dock_pH := H
Dock_pV := V
Dock_dx := dx
Dock_dy := dy
Dock_sizeX := sizeX
Dock_sizeY := sizeY
Dock_hHookDll := API_LoadLibrary(HookDll)
Dock_hHook0 := Hook(hwnd, Dock_msg, 3) ; EVENT_SYSTEM_FOREGROUND
Dock_hHook2 := Hook(hwnd, Dock_msg, 10, 11) ; EVENT_SYSTEM_MOVESIZESTART 10 EVENT_SYSTEM_MOVESIZEEND 11
Dock_hHook3 := Hook(hwnd, Dock_msg, 0x800A, 0x800B, "Dock_HookHandler") ;EVENT_OBJECT_STATECHANGE 0x0000800a, EVENT_OBJECT_LOCATIONCHANGE 0x0000800b
Return Dock_hHook & Dock_hHookDll
}
API_ShowWindow(hwnd, flag){
return DllCall("ShowWindow", "UInt", hwnd, "int", flag)
}
Dock_Update:
If (Dock_HookHwnd != Dock_HostID)
Return
API_ShowWindow(Dock_ClientId, 8)
WinGetPos, Dock_hX, Dock_hY, Dock_hW, Dock_hH, ahk_id %Dock_HookHwnd%
WinGetPos, Dock_cX, Dock_cY, Dock_cW, Dock_cH, ahk_id %Dock_ClientId%
Dock_H := Dock_cH
Dock_W := Dock_cW
If (Dock_sizeX)
StringReplace, Dock_W, Dock_sizeX, A_DockHostWidth, %Dock_hW%
If (Dock_sizeY)
StringReplace, Dock_H, Dock_sizeY, A_DockHostHeight, %Dock_hH%
Dock_x := Dock_hX
If (Dock_pH = "R")
Dock_x := Dock_hX + Dock_hW
Else If (Dock_pH = "M")
Dock_x := Dock_hX + (Dock_hW//2) - (Dock_cW//2)
Dock_y := Dock_hY
If (Dock_pV = "B")
Dock_y := Dock_hY + Dock_hH
Else If (Dock_pV = "M")
Dock_y := Dock_hY + (Dock_hH//2) - (Dock_cH//2)
Dock_x += Dock_dx, Dock_y += Dock_dy
WinMove ahk_id %Dock_ClientId%,,%Dock_X%, %Dock_Y%, %Dock_W%, %Dock_H%
Return
Undock() {
GoSub Dock_Update
Unhook(Dock_hHook, Dock_msg)
API_FreeLibrary(HookDll)
}
Dock_HookHandler(wParam, lParam, msg, hwnd) {
Global
GetHookParams(lparam, Dock_event, Dock_HookHwnd)
GoSub Dock_Update
}
GetHookParams(lparam, ByRef event, ByRef hwnd="", ByRef idObject="", ByRef idChild="", ByRef dwEventThread="", ByRef dwmsEventTime="") {
DllCall("RtlMoveMemory", UIntP,event , UInt,lParam+ 4, UInt, 4)
DllCall("RtlMoveMemory", UIntP,hwnd , UInt,lParam+ 8, UInt, 4)
DllCall("RtlMoveMemory", UIntP,idObject , UInt,lParam+12, UInt, 4)
DllCall("RtlMoveMemory", UIntP,idChild , UInt,lParam+16, UInt, 4)
DllCall("RtlMoveMemory", UIntP,dwEventThread, UInt,lParam+20, UInt, 4)
DllCall("RtlMoveMemory", UIntP,dwmsEventTime, UInt,lParam+24, UInt, 4)
}
Hook(comm_hwnd, comm_msg, s_event, e_event="", function="", wparam=0) {
Global HookDll
r := DllCall(HookDll "\reghook", UInt,comm_hwnd, UInt,COMM_MSG, UInt,s_event, UInt,e_event ? e_event : s_event, UInt,wparam)
If (function)
OnMessage(COMM_MSG, function)
Return r
}
Unhook(handle, com_msg) {
OnMessage(com_msg)
Return DllCall("UnhookWinEvent", "UInt", handle)
}
API_LoadLibrary( dll ) {
Return DllCall("LoadLibrary", "str", dll)
}
API_FreeLibrary( h ) {
Return DllCall("FreeLibrary", "uint", h)
}
I checked (with TrayTip) that the hook is correctly called, only the docked window is not shown. I guess, the following command does not work well:
Code:
API_ShowWindow(Dock_ClientId, 8)
Flag values other than 8 don't work, either.