 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10716
|
Posted: Fri May 25, 2007 9:43 pm Post subject: |
|
|
Nice demo and encapsulation. I noticed one tiny typo:
| Code: | OnMessage(com_msg)
; ...should probably be:
OnMessage(com_msg, "") ; Specify an empty string ("") or an empty variable to turn off the monitoring of MsgNumber. | My tentative priorities now are to work on the mechanisms to support the standard library, and then work on v2. Therefore, it's probably best that this docking feature either: 1) Be made a part of the standard library; or
2) Be incorporated into the code by some other developer.
Thanks. |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Sun May 27, 2007 9:17 am Post subject: |
|
|
2 JGR
For what reason we monitor EVENT_OBJECT_STATECHANGE ? _________________
 |
|
| Back to top |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 59 Location: Oriel College
|
Posted: Sun May 27, 2007 9:39 am Post subject: |
|
|
It seems to be sent during minimise, maximise and restore operations, but so is EVENT_OBJECT_LOCATIONCHANGE is suppose, have you tested it without monitoring that message? The name suggests that it would be sent during window enable/disables as well (but I haven't tested or researched this).
If it makes no difference you can just exclude it...
JGR |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Sun May 27, 2007 10:16 am Post subject: |
|
|
Well, I am having pretty good time here tryint to make TitleButton work in every case
Laszlo did well when he replaced Dock_HostClass with DOck_HostID. THis filters many things as you can only do
| Code: | | if Dock_hwnd != Dock_HostId |
I don't have this in TitleButton as it must catch every window.
| Quote: | | If it makes no difference you can just exclude it... |
I excluded it, seems to make no difference. Anyway, you can't enable/desable top level window, only child control.
This is the latest TitleButton script. Button is now on the left. Tray, start menu and such are now in
| Code: | | Dock_exclude=Shell_TrayWnd,32768,Progman,DV2ControlHost |
Remember that depending on additional make-up things you might have, like me (DesktopX, ObjectDock etc...) you may get star sometimes on funny position. Just right click it to exclude this win. This is not remebered accross sesions for now.
| Code: | #SingleInstance, force
SetWinDelay, -1
SetBatchLines, -1
DetectHiddenWindows, On
Gui, +LastFound -Caption +ToolWindow +AlwaysOnTop
hGui := WinExist()
Gui, Font,s8 , Webdings
Gui, Add, Picture, x0 y0 +0x8000 gOnClick, enable.ico
WinSet ExStyle, 0x08000008, ahk_id %hGui%
Gui, Color, 0
WinSet, TransColor, 0
Dock_exclude=Shell_TrayWnd,32768,Progman,DV2ControlHost
Dock_ClientId := hGui
Dock("L","T", 25, 5) ;left
; Dock("R","T",-90, 5) ;right
Gui, Show, -1500 AutoSize
Gui, Hide
return
GuiContextMenu:
hwnd := WinExist("A")
WinGetClass class, ahk_id %hwnd%
msgbox 36, FM3, Exclude class:`n`n%class%
ifMsgBox, No
return
Dock_exclude .= "," class
return
OnClick:
FMA_SHOW = 3
WM_FAVMENU = 0x399
PostMessage, WM_FAVMENU, FMA_SHOW,,,ahk_id 0xFFFF
return
Dock(H="R",V="T", dx=0, dy=0 ) {
local hwnd, msg
hwnd := WinExist("ahk_pid " . DllCall("GetCurrentProcessId","Uint"))
Dock_msg := 0x550
HookDll = wineventhookq.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_hHook2 := Hook(hwnd, Dock_msg, 2) ;alert
Dock_hHook0 := Hook(hwnd, Dock_msg, 3) ;EVENT_SYSTEM_FOREGROUND
; Dock_hHook1 := Hook(hwnd, Dock_msg, 22, 23) ;EVENT_SYSTEM_MINIMIZEEND
Dock_hHook3 := Hook(hwnd, Dock_msg, 0x800B, 0x800B, "Dock_HookHandler") ;EVENT_OBJECT_STATECHANGE ,EVENT_OBJECT_LOCATIONCHANGE
return Dock_hHook & Dock_hHookDll
}
Dock_Update:
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_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
; OutputDebug %Dock_Event%, %Dock_ClientId%, %Dock_X%, %Dock_Y%
WinMove, ahk_id %Dock_ClientId%, ,%Dock_X%, %Dock_Y%, %Dock_W%, %Dock_H%
;WinSet, Top,, ahk_id %Dock_ClientId%
; API_ShowWindow(Dock_ClientId, 4)
WinShow, ahk_id %Dock_ClientId%
return
Undock(){
goSub Dock_Update
Unhook(Dock_hHook, Dock_msg)
API_FreeLibrary(HookDll)
}
Dock_HookHandler(wParam, lParam, msg, hwnd) {
local e, cls, title
static alert
GetHookParams(lparam, Dock_event, Dock_HookHwnd)
WinGetClass, Dock_cls, ahk_id %Dock_HookHwnd%
WinGetTitle, title, ahk_id %Dock_HookHwnd%
WinGet, style, Style, ahk_id %Dock_HookHwnd%
; OutputDebug AHK-Dock: ENTER %dock_event% %title% %dock_cls%
if Dock_cls in %Dock_exclude% ;skip excluded
{
; OutputDebug AHK-Dock: exclusion %dock_event% %title% %dock_cls%
if (Dock_event != 0x800B)
WinHide, ahk_id %Dock_ClientId%
return
}
if (title = "") or !(style & 0xC00000) or !(style & 0x10000000) or (style & 0x40000000) { ; WS_CAPTION = C00000 , WS_VISIBLE = 0x10000000, WS_CHILD = 0x40000000
return
}
if (Dock_event = 2) {
; OutputDebug AHK-Dock: %dock_event% %title% %dock_cls%
alert := Dock_HookHwnd ; remember alert win
return
}
if (alert = Dock_HookHwnd) ; skip alert windows
return
if (Dock_event = 3) { ; Foreground
; OutputDebug AHK-Dock: %dock_event% %title% %dock_cls%
gosub Dock_Update
return
}
if (Dock_event=0x800B) ;or (Dock_event=0x800A) or (Dock_event = 23)
{
; OutputDebug AHK-Dock: %dock_event% %title% %dock_cls%
gosub Dock_Update
return
}
}
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)
}
API_ShowWindow(hwnd, flag){
return DllCall("ShowWindow", "UInt", hwnd, "int", flag)
}
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)
}
|
_________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Sun May 27, 2007 5:33 pm Post subject: |
|
|
Another version.
2Laszlo
I did some more optimisation as we are aproaching v1.0. As script is like 50 lines, those will be easy to spot. I also removed 3 hook types as they seem to be non important once EVENT_OBJECT_LOCATIONCHANGE is introduced.
One last thing is still missing. User handler on host death. I am not sure how do to this without monitoring additional events which I don't like as EVENT_OBJECT_LOCATIONCHANGE already spam like crazy. _________________
 |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4710 Location: Boulder, CO
|
Posted: Mon May 28, 2007 12:14 am Post subject: |
|
|
- Version 0.96 still works OK.
- In the function Hook_Shutdown, the "" are missing in OnMessage(com_msg,""), as Chris noted.
- I wonder, if you want to get rid of Globals, all together. One way to do this to introduce a function DockGlobals, with a lot of ByRef parameters, and another one GETorSET. The globals can be then replaced by Static variables in DockGlobals. This is slow and clumsy, but requires little change in the code. The best was to pass everything in function parameters, which may not be possible, for example with Dock_HostID in the function Dock_HookHandler. This function could be called with a special parameter, indicating that Dock_HostID is given in another parameter, which has to be stored in a Static variable. The ultimate goal can be supporting multiple client windows, dynamically dock/undock them.
- (Host death) Location change messages might be numerous, but if there is a message sent when a window is closed, catching it does not add much overhead. How many windows can you close in a second? |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Mon May 28, 2007 7:22 am Post subject: |
|
|
| Quote: | | - In the function Hook_Shutdown, the "" are missing in OnMessage(com_msg,""), as Chris noted. |
yeh...forgot about that
| Quote: | | I wonder, if you want to get rid of Globals, all together. |
Well, I think its fine now. You already know that update routine must be as fast as possible due to the large number of messages dock hanlder can receive. So, the only reasonable solution is to set statics in Dock_Update() function.
Globals are also problematic for "multiple dock instances" but that is some other story. I noticed many ppl impose a limit on number of instances by using globals. For instance, initial version of IE control by Sean had this limitation cuz of globals. As soon you instantiate second web control you fuked up previous .
| Quote: | | The ultimate goal can be supporting multiple client windows, dynamically dock/undock them. |
Yeah, multidock. I was thinking about this, can be easily done by specifying dock number and remembering globals like Dock_%num%_XXX then iterating over names and dock clients in update routine. Sounds trivial. Something like:
| Code: | Dock_ClientID1 := ...
Dock_ClientID2 := ...
Dock_ClientID3 := ...
Dock_HostId := ...
Dock(.... , 1)
Dock(....., 2)
Dock(......,3) |
| Quote: | | How many windows can you close in a second? |
Like 100 windows in millisecond. Everything is window. Application having 50 buttons (common) when dies will produce Dock_Update work like crazy. The very same happens now with LOCATION_CHANGE. The MSDN states that LOCATION_CHANGE is not called for child windows UNLESS parent is resizing them .... Seems that Anchor produces this kind of effect (message spam). In title button I am checking style to filter out everything that has WM_CHILD, !WM_CAPTION and even !WM_VISIBLE (it seams that even invisible windows get "activated" when you click on the tray icon, for instance hidden ahk debuger)
I solved this easy for TitleButton.
In TB, I used this mechanism: when host dies another application receives focus. Something like:
| Code: | if event=3 and Dock_HostID != HookHwnd and !died and !WinExist("ahk_id " Dock_hostID) {
died := 1
GoSub Dock_UserDeathHandler
return
} |
Well, i think this works fine now, perhaps we should check what we can do with real hoook (SetWindowHookEx). There we have much better control of events IIRC. WinEvent group single events into clases. _________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Mon May 28, 2007 10:03 am Post subject: |
|
|
2 Laszlo
We can add aditional param to the Dock function. The one that will NOT create the hook . U probably now think I am crazy, but Update routine in last version can be used as a general positioning goodie.
The effect would be the same as this:
| Code: | Dock(0,-1,-10, 0,0,0, 0,100, 0,180) ; left, top
Dock_ShutDown() ; :D
Dock_Update(Dock_HostId) ; :D |
After this, the one can manualy call Dock_Update whenever it wants to update docking to certain host but still keep familiar Dock interface
What do you think ? _________________
 |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4710 Location: Boulder, CO
|
Posted: Mon May 28, 2007 3:56 pm Post subject: |
|
|
Sounds to be useful.
Non-permanent docking applications can be in explorer, when the user wants his favorite folders shown for fast navigation (so they never cover important info), just until he makes a selection. Similarly with open/save dialogs. In editors you can pop up a window with the number of characters, words, etc., always on the side. In a browser, when the address bar is selected, a list of favorites could be shown, and so on.
The main advantage of a window position tool like this is that it can be relative to another window in position and/or size, and the programmer does not need to figure the math: it is already done for him in the Dock function. |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Mon May 28, 2007 4:21 pm Post subject: |
|
|
Exactly.
This makes my previous note that we need to keep original WIndow GUI size in case user didn't specify them, even more needed.
Perhaps we can do this if whw & whd are zero (as it is miningless), and the same for height. _________________
 |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4710 Location: Boulder, CO
|
Posted: Mon May 28, 2007 4:37 pm Post subject: |
|
|
| majkinetor wrote: | | we need to keep original WIndow GUI size in case user didn't specify them, even more needed... if whw & whd are zero (as it is miningless), and the same for height. | it is an alternative. I don't know if a non-numeric parameter ("W" as in my last posted code) or a pair of 0's is more intuitive. You can certainly save typing the quotes  |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Mon May 28, 2007 5:00 pm Post subject: |
|
|
Well, I beleive that only I like your syntax
After all, we are both ex-math proffesors
In previous syntax this was trivial and already implemented as such.
Perhaps we can devise something more user friendly  _________________
 |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4710 Location: Boulder, CO
|
Posted: Tue May 29, 2007 2:48 pm Post subject: |
|
|
A couple of more typos:
- API_FreeLibrary() should have parameter Dock_hHookDll, not HookDll, in two places
- In the Dock function Dock_hHook2 is not defined any more, so the statement "If !(Dock_hHook1 && Dock_hHook2 && Dock_hHook3)" is always true (need to remove Dock_hHook2). It does not free the library, though, because of the bug above. |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Tue May 29, 2007 4:07 pm Post subject: |
|
|
Thx... now its good time to polish the script.
I always leave that for v1.0.
Anyway, Laszlo feel free to do updates on your own from the current version. If you find something, why don't u correct it imediately and post modified script here so I can update the first post. _________________
 |
|
| Back to top |
|
 |
aaron
Joined: 07 Oct 2005 Posts: 13
|
Posted: Fri Jun 01, 2007 4:20 pm Post subject: |
|
|
Great script everyone- I have been using it often.
There is an inconsistancy that occurs with the docked window when the dock host is minimized. Sometimes the window will go to the bottom left of the screen (can only see a small edge of it), or it will not move at all. I have made the following change to the Dock_Update function, which fixes the problem for me.
| Code: |
If (hX="") or (hX=0 and hW=160)
WinMove ahk_id %Dock_ClientId%,,-32000,-32000
else
WinMove ahk_id %Dock_ClientId%,,X,Y,W,H
|
Feel free to add it or modify it.
Thanks for all the work! |
|
| 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
|