 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Laszlo
Joined: 14 Feb 2005 Posts: 4015 Location: Pittsburgh
|
Posted: Tue May 22, 2007 12:20 am Post subject: |
|
|
| majkinetor wrote: | | When I move it, picture becomes garbage. | You should not move it. This is what I said: "prevent moving the docked window, or even remove its title bar". It behaves like a control, which nobody expects to be moved around. You can freely move the parent window. It is true: resizing is more difficult, but can be done.
| majkinetor wrote: | | SetParent can not be made to work generally good… its general usage is equal to 0. | There are many such scripts posted, which work OK. In my main AHK script I have 6 different windows docked with SetParent, another 4 I use occasionally. Just search the Forum and you will find fine working examples. If you failed to make it work, maybe, you did not try hard enough. "Its general usage is" strictly greater than 0.
Here are a few more things you ought to do when using SetParent (disable resize, hide the title bar of Notepad): | Code: | Gui Add, Button, X255 Y348 W90 H24, NOTEPAD
Gui Show, x200 y50 w600 h400
WinGet gID, ID, %A_ScriptName%
WinGetPos X, Y, W, H, ahk_id %gID%
Run notepad,,,nPID
WinWait ahk_pid %nPID%
WinSet Style, -0x40000, ahk_pid %nPID% ; Disable resize
WinMove ahk_pid %nPID%,,0, 400+2-H, 600, 360 ; Client area + Border - Window Height
WinGet nID, ID, ahk_pid %nPID%
DllCall("SetParent", UInt,nID, UInt,gID)
WinActivate ahk_id %gID%
WinActivate ahk_id %nID% |
|
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Tue May 22, 2007 9:52 am Post subject: |
|
|
2Laszlo
Its buggy, like I said. Minimize maximize and menu is lost. You can refresh it ofc, but there will always be some things, generaly.
Laszlo, you obviously miss the point. This thing you speak about has NOTHING TO DO WITH DOCKING. That is NOT docking.
Docking is the way to connect 2 arbitrary windows so they move minimise and maximize together in any setup.
Dock client will also follow various Dock Host instances around which is not possbile with your method as Unseting Parent and Setting it for new window looks like sht.
I have changed the first page with screens to show you the point.
The GUI now has button that you can click to open Notepad. Open Notepad, move it, open it again, move it... Click 3 notpeads. Dock window will jump to them imediately.
This is fundamental feature of docking not available with poor SetParent method, which is even not recomended to be used as such. U didn't notice "MUST NOT" word from MSDN in red quote by JGR. _________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Tue May 22, 2007 9:53 am Post subject: |
|
|
I updated the first post with some nice xamples. _________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Tue May 22, 2007 1:34 pm Post subject: |
|
|
OMG, I just realised that
creates almost instant chacing of dock host to dock client.... Isn't that great. _________________
 |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4015 Location: Pittsburgh
|
Posted: Tue May 22, 2007 2:01 pm Post subject: |
|
|
| majkinetor wrote: | | Minimize maximize and menu is lost. | You cannot maximize it. In my English XP SP2 minimizing and restoring, or moving the window around does not hide the menu. I wonder, what makes your PC so different. Do you have some custom versions of the Windows system files?
| majkinetor wrote: | | Laszlo, you obviously miss the point. This thing you speak about has NOTHING TO DO WITH DOCKING. | I did not say it was docking: | Laszlo wrote: | | you can have similar effects in much simpler way | The SetParent method does everything needed to enhance an application with menus, additional buttons, infos, etc., at least in my laptop. In one of my scripts I have more child windows to a single parent, which move, hide or restore together. If an application needs more features, use real docking, as I said: | Laszlo wrote: | | the real value of the hooks could be seen in more complex examples |
|
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue May 22, 2007 2:33 pm Post subject: |
|
|
Thanks majkinetor for this modul.
It will come handy when SetParent doesn't do the job. _________________ Ciao
toralf  |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Tue May 22, 2007 3:02 pm Post subject: |
|
|
New version of Dock func is availalbe that is much more fluid and handles showing hiding alt tabing etc...
Check it out at first page. Just execute script and enjoy. _________________
 |
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue May 22, 2007 3:25 pm Post subject: |
|
|
The link to download in first post doesn't work. _________________ Ciao
toralf  |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Tue May 22, 2007 3:46 pm Post subject: |
|
|
Sorry, didn't know AutoHotKey.Net is case sensitive. _________________
 |
|
| Back to top |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Wed May 23, 2007 9:42 am Post subject: |
|
|
By trapping events 0x800A and 0x800B as well there is no need for a timer at all...
| Code: | SetBatchLines, -1
SetWinDelay -1
CoordMode, tooltip, screen
DetectHiddenWindows, On
Gui, +LastFound +ToolWindow +AlwaysOnTop
hGui := WinExist()
Gui, Add, Text, ,Open Notepad
Gui, Show, AutoSize
Dock_HostClass := "Notepad"
Dock_ClientId := hGui
Dock("L","B", "A_DockHostWidth", 0 )
return
Dock( H="R",V="T", sizeX="", sizeY="", dx=0, dy=0 ) {
local hwnd, msg
hwnd := WinExist("ahk_pid " . DllCall("GetCurrentProcessId","Uint"))
Dock_msg := 0x550
HookDll = wineventhook.dll
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_Timer:
critical
WinGetClass Dock_cls, ahk_id %Dock_HookHwnd%
if (Dock_cls != Dock_HostClass)
return
if (Dock_Event = 3)
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_Timer
Unhook(Dock_hHook, Dock_msg)
API_FreeLibrary(HookDll)
}
Dock_HookHandler(wParam, lParam, msg, hwnd) {
local e
GetHookParams(lparam, Dock_event, Dock_HookHwnd)
;if (Dock_event = 10) ;movesizse start
;SetTimer Dock_Timer, 0
;if (Dock_event = 11) ;movesize end
;Undock()
;if (Dock_event = 3)
GoSub Dock_Timer
}
GetHookParams(lparam, ByRef event, ByRef hwnd="", ByRef idObject="", ByRef idChild="", ByRef dwEventThread="", ByRef dwmsEventTime="") {
event :=GetDeRefInteger(lParam+4)
hwnd :=GetDeRefInteger(lParam+8)
idObject :=GetDeRefInteger(lParam+12)
idChild :=GetDeRefInteger(lParam+16)
dwEventThread :=GetDeRefInteger(lParam+20)
dwmsEventTime :=GetDeRefInteger(lParam+24)
}
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 !r
return 0
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)
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity. To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index-1, UInt, 1, UChar, pInteger >> 8*(A_Index-1) & 0xFF)
}
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
Loop %pSize% ; Build the integer by adding up its bytes.
result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
GetDeRefInteger(pSource, pIsSigned = false, pSize = 4)
; pSource is an integer pointer to a raw/binary integer
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
{
Loop %pSize% ; Build the integer by adding up its bytes.
result += *(pSource + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
SetDeRefInteger(pInteger, pDest, pSize = 4)
; The caller must ensure that *pDest has sufficient capacity and that pDest is a valid dereferencable integer pointer.
; To preserve any existing contents at *pDest, only pSize number of bytes are altered.
{
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
DllCall("RtlFillMemory", UInt, pDest + A_Index-1, UInt, 1, UChar, pInteger >> 8*(A_Index-1) & 0xFF)
} |
|
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Wed May 23, 2007 10:20 am Post subject: |
|
|
I suspected there are some of these but didn't know what to choose on bunhc of them
EVENT_OBJECT_STATECHANGE
EVENT_OBJECT_LOCATIONCHANGE
I will try tomorrow how it behaves in dock script _________________
 |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4015 Location: Pittsburgh
|
Posted: Wed May 23, 2007 8:37 pm Post subject: |
|
|
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. |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 5068 Location: imaginationland
|
Posted: Wed May 23, 2007 10:19 pm Post subject: |
|
|
Great concept, but what can wineventhook.dll do here that a normal SetTimer+WinMove can't? e.g.
| Code: | SetWinDelay, -1
SetBatchLines, -1
Critical
Gui, +LastFound -Caption +Resize +ToolWindow ;+AlwaysOnTop
Gui, Add, Edit, x0 y0 w300 h30, This is docking client
Gui, Add, Button, x+0 yp gOnClick, New Notepad
Gui, Show, x-500 y0 h30
gui := WinExist()
OnClick:
Run, notepad, , , pid
SetTitleMatchMode, 2
WinWait, ahk_pid %pid%
If !hook
SetTimer, CheckMov, 1
hook := WinExist()
CheckMov:
If !WinExist("ahk_id" . hook) {
Gui, Destroy
SetTimer, CheckMov, Off
ExitApp
}
WinGetPos, x, y, w, , ahk_id %hook%
y -= 50
Gui, Show, x%x% y%y% w%w% NA
Return
~*Esc::ExitApp |
_________________
RegExReplace("irc.freenode.net/ahk", "^(?=(.(?=[\0-r\[]*((?<=\.).))))(?:[c-\x73]{2,8}(\S))+((2)|\b[^\2-]){2}\D++$", "$u3$1$3$4$2") |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Wed May 23, 2007 10:57 pm Post subject: |
|
|
2 Titan
Well, the fact that you have 1ms timer which will interupt anything serious script should do besides docking. If you make timer not so fast, the dock will not be dock at all (try 100ms for instance). So, at every milisecond of your any script that should have docked guis will be interuped at every millisecond with 3 commands unless you make all of the thread non interuptable by timers which then introduces new problem with timers U might have that should interupt things.
Well, its not strange many of here don't like extensive use of timers.
Contrary to that, hook is quiet while you do nothing. It reports when something happens in manner "hej, new window is active" or "hej, this one is going to move" so if none of those things happen, you don't do anything. _________________

Last edited by majkinetor on Wed May 23, 2007 10:59 pm; edited 1 time in total |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4015 Location: Pittsburgh
|
Posted: Wed May 23, 2007 10:59 pm Post subject: |
|
|
The last version of the dock script does not use timer but Windows events, therefore the movement is smoother than with AHK timers, and possibly uses less processor power. Otherwise the demos have similar functionality.
However, both versions suffer from the same problem: the client window gets behind others, and disappears. The main advantage of the SetParent method: the children become controls of the parent, and so they move together, none of them gets behind other windows individually. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|