Special variant of docking deserved its own space. In latest version this script doesn't hook any specific window, but all windows (except alerts, menus, shelltray etc..). U can acieve single window titlebutton by using Dock function.
Download
Now you can have customizable buttons on titles, as many as you want, so you can create nice looking addons for Windows. Only your imagination is the limit.
What was previously very hard to get working without lot of
programming, you have here to abuse as much as you like.
Latest work here
TitleButton 0.31
Started by
majkinetor
, May 22 2007 02:41 PM
42 replies to this topic
pretty neat! thanks for sharing.
#2
-
Posted 22 May 2007 - 03:58 PM
CleanNews.in : Bite sized latest news headlines from India with zero bloat
It's very nice. However, when one double clicks on the title bar, which usually means Restore/Maximize, the titlebutton does not follow. It seems like Dock_event does not correctly generate an event for Restore/Maxmize. Even if one minimizes the window, then Maximizes the window, there is no Maxmize event (23) generated, only event 3 is generated.
#3
-
Posted 23 May 2007 - 12:17 AM
I discovered that yesterday.
WinEvent doesn't recognise this event (Restore/Maximize).
Maximize/Minimize works nice here.
I was so dissapointed yesterday when I saw that Restore/Maximize doesn't fall into 16,17 or 22,23 category, nor in any other category.
By examining what is happening when I monitor events from 0 to 0xFFFFFF (should be all supported events IMO) I see that lot of strange 3227 or something, events are genererated. Perhpase Restore/Maximize falls into some general category.
Unless somebody can't help, this basicly means that WinEvent isn't good enough for docking as to fix Restore/Maximize, currently I have to set another timer running constatly, which was not the point.
WinEvent doesn't recognise this event (Restore/Maximize).
Maximize/Minimize works nice here.
I was so dissapointed yesterday when I saw that Restore/Maximize doesn't fall into 16,17 or 22,23 category, nor in any other category.
By examining what is happening when I monitor events from 0 to 0xFFFFFF (should be all supported events IMO) I see that lot of strange 3227 or something, events are genererated. Perhpase Restore/Maximize falls into some general category.
Unless somebody can't help, this basicly means that WinEvent isn't good enough for docking as to fix Restore/Maximize, currently I have to set another timer running constatly, which was not the point.
#4
-
Posted 23 May 2007 - 08:13 AM
Actually event 32778, 0x800A EVENT_OBJECT_STATECHANGE, is sent when the window is restored or maximised.
Interestingly event 32779, 0x800B EVENT_OBJECT_LOCATIONCHANGE, is sent DURING a window move, if "Show window contents while dragging" windows option is turned on (I have it off usually).
I am not sure of the frequency/usefulness of this, but I will investigate...
JGR
Interestingly event 32779, 0x800B EVENT_OBJECT_LOCATIONCHANGE, is sent DURING a window move, if "Show window contents while dragging" windows option is turned on (I have it off usually).
I am not sure of the frequency/usefulness of this, but I will investigate...
JGR
#5
-
Posted 23 May 2007 - 08:31 AM
Can you fix this TItleButton to work with Restore/Maximize as you did with Dock (yeah, dock works fine now)
The problem is little different here as in TitleButton DockHostClass basicly doesn't exist as all windows are hooked. 327789 is isued 10-15 times on Restore/Maximize so other messages are problematic.
The solution is probably to determine what is top level window out of event hwnd and to filter all hwnd's not representing top level windows.
The problem is little different here as in TitleButton DockHostClass basicly doesn't exist as all windows are hooked. 327789 is isued 10-15 times on Restore/Maximize so other messages are problematic.
The solution is probably to determine what is top level window out of event hwnd and to filter all hwnd's not representing top level windows.
#6
-
Posted 23 May 2007 - 10:10 AM
The button does also disappear if window loses focus.
But this is a very usefull feature (if maximize-code is added).
Thx!
Thalon
But this is a very usefull feature (if maximize-code is added).
Thx!
Thalon
#7
-
Posted 23 May 2007 - 10:33 AM
I know about this but this is not something very important.The button does also disappear if window loses focus.
I have another version where button stays , but this introduced new problems so it was much easier just to let it be like that. The problem is if you have 2 notepad windows both should have its own 4th button. Now only active one has it. To make both has it is much more complicated and benefits are close to 0.
Yes, its very useful and practical. If JGR can fix maximize I will create more handy wrapper that asks you how many buttons to add, icons for each, offset, handlers for left & right click etc...But this is a very usefull feature (if maximize-code is added).
Anyway, it would be helpful if someone point me to the ahk code that can say if hwnd is top level window or not. I have not much time to create it on my own, have some exames these days...
#8
-
Posted 23 May 2007 - 10:57 AM
AH, I forgot one lil' detail. The script I was talking about is not the same as the one at the first post.
This is the script, that should be fixed. It doesn't use Dock_HostClass at all to filter but will add button on every title except msgbox windows (EVENT_ALERT is filtered).
This is the script, that should be fixed. It doesn't use Dock_HostClass at all to filter but will add button on every title except msgbox windows (EVENT_ALERT is filtered).
#SingleInstance, force CoordMode, mouse, screen SetWinDelay, -1 SetBatchLines, -1 CoordMode, tooltip, screen 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_HostClass := "#32770" Dock_ClientId := hGui Dock("R","T",0,0,-90,5) Gui, Show, -1500 AutoSize Gui, Hide return GuiContextMenu: hwnd := WinExist("A") WinGetClass class, ahk_id %hwnd% msgbox Exclude %class% ? return OnClick: FMA_SHOW = 3 WM_FAVMENU = 0x399 PostMessage, WM_FAVMENU, FMA_SHOW,,,ahk_id 0xFFFF 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_hHook1 := Hook(hwnd, Dock_msg, 22, 23) ; EVENT_SYSTEM_MINIMIZEEND Dock_hHook2 := Hook(hwnd, Dock_msg, 2) Dock_hHook4 := Hook(hwnd, Dock_msg, 10, 11, "Dock_HookHandler") ; EVENT_SYSTEM_MOVESIZESTART := 10 EVENT_SYSTEM_MOVESIZEEND := 11 return Dock_hHook & Dock_hHookDll } Dock_Timer: 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% WinSet, Top,, ahk_id %Dock_ClientId% API_ShowWindow(Dock_ClientId, 4) return Undock(){ goSub Dock_Timer 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% if Dock_event = 2 { alert := Dock_HookHwnd return } if (alert = Dock_HookHwnd) ;skip alert windows return WinGetTitle, title, ahk_id %Dock_HookHwnd% if (title = "") return if StrLen(s)>200 s = s .= Dock_event "`n" if (Dock_HookHwnd = Dock_ClientId) { ; if !WinExist("ahk_class " Dock_HostClass) ; WinHide, ahk_id %Dock_ClientId% return } ; if (Dock_cls != Dock_HostClass){ ; if (Dock_event = 3) ; WinHide, ahk_id %Dock_ClientId% ; return ; } Tooltip %s%, 0, 0 if (Dock_event = 10) { ;movesize start SetTimer, Dock_Timer, 0 return } if (Dock_event = 11) { ;movesize end SetTimer, Dock_Timer, off gosub Dock_Timer return } if (Dock_event = 3) { ;foreground Sleep 100 gosub Dock_Timer } if (Dock_event = 23) or (Dock_event=0x800B) ;maximized gosub Dock_Timer if Dock_event = 22 ;minimized WinHide, ahk_id %Dock_ClientId% } 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) } 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) }
#9
-
Posted 23 May 2007 - 11:25 AM
I know, I said to you that dock is fixed.
BUt this is not like dock. There is no Dock_HostClass as every window should be afected except alerts. So there is no thing like
to filter 10-20 32779 events that you get when you maximize single window.
So, EVENT_OBJECT_LOCATIONCHANGE will be risied bunch of times for single maximize event for any window and handle of that window will be among other handles in the bunch of events. So, dock client will get wrong coordinates as it will check some funny window (maybe child hwnd that rised EVENT_OBJECT_LOCATIONCHANGE after main window is reported). I didn't further investigate this, didn't have time today, the easiest solution would probably be to check the type of handle you recieve and discard everything having WS_CHILD style.
BUt this is not like dock. There is no Dock_HostClass as every window should be afected except alerts. So there is no thing like
WinGetClass cls, ahk_id %EventHWND% if (Dock_HostClass != cls) return
to filter 10-20 32779 events that you get when you maximize single window.
So, EVENT_OBJECT_LOCATIONCHANGE will be risied bunch of times for single maximize event for any window and handle of that window will be among other handles in the bunch of events. So, dock client will get wrong coordinates as it will check some funny window (maybe child hwnd that rised EVENT_OBJECT_LOCATIONCHANGE after main window is reported). I didn't further investigate this, didn't have time today, the easiest solution would probably be to check the type of handle you recieve and discard everything having WS_CHILD style.
#11
-
Posted 23 May 2007 - 09:15 PM
Well, check it out yourself here:
It almost work correctly. No timer.
The star (button) flickers sometimes (I guess because of great number of messages received). Also, most important is this: star is sometimes on weird positions, like in the middle of something, this happens only on event=3 (foreground). Its strange... somehow putting sleep before processing this event produce different frequencies of this bug. The star is returned to right place as soon as I move the window arround. Fast alttabing sometimes makes the star stay on the same place as before.
Notice that you can right click on star. I planned this so you can exclude certain window (for instance ICQ, Miranda, DesktopX etc..) that are not excluded automaticaly. Now it just reports class of window under it. I done it by making gui holding the star having WS_NOACTIVATE flag.
BTW, enable the tooltip to see event. I desabled it as star flickers cuz tooltip is updated fast as of bunch of events.
Interestingly enough timer worked better. Now, when you move window around CPU goes very high. Timer didn't touch CPU more then 1-2% while moving.
#SingleInstance, force CoordMode, mouse, screen SetWinDelay, -1 SetBatchLines, -1 CoordMode, tooltip, screen 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_HostClass := "#32770" Dock_ClientId := hGui Dock("R","T",0,0,-90,5) Gui, Show, -1500 AutoSize Gui, Hide return GuiContextMenu: hwnd := WinExist("A") WinGetClass class, ahk_id %hwnd% msgbox Exclude %class% ? return OnClick: FMA_SHOW = 3 WM_FAVMENU = 0x399 PostMessage, WM_FAVMENU, FMA_SHOW,,,ahk_id 0xFFFF 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_hHook1 := Hook(hwnd, Dock_msg, 22, 23) ; EVENT_SYSTEM_MINIMIZEEND Dock_hHook2 := Hook(hwnd, Dock_msg, 2) Dock_hHook3 := Hook(hwnd, Dock_msg, 0x800A, 0x800B, "Dock_HookHandler") ;EVENT_OBJECT_STATECHANGE 0x0000800a, EVENT_OBJECT_LOCATIONCHANGE 0x0000800b, return Dock_hHook & Dock_hHookDll } Dock_Timer: 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% WinSet, Top,, ahk_id %Dock_ClientId% API_ShowWindow(Dock_ClientId, 4) return Undock(){ goSub Dock_Timer 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% if Dock_event = 2 { alert := Dock_HookHwnd return } if (alert = Dock_HookHwnd) ;skip alert windows return WinGetTitle, title, ahk_id %Dock_HookHwnd% if (title = "") return if StrLen(s)>200 s = s .= Dock_event "`n" if (Dock_HookHwnd = Dock_ClientId) { ; if !WinExist("ahk_class " Dock_HostClass) ; WinHide, ahk_id %Dock_ClientId% return } ; if (Dock_cls != Dock_HostClass){ ; if (Dock_event = 3) ; WinHide, ahk_id %Dock_ClientId% ; return ; } ; Tooltip %s%, 0, 0 if (Dock_event = 3) { ;foreground gosub Dock_Timer } if (Dock_event = 23) or (Dock_event=0x800B) ;maximized gosub Dock_Timer if Dock_event = 22 ;minimized WinHide, ahk_id %Dock_ClientId% } 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) } 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) }
It almost work correctly. No timer.
The star (button) flickers sometimes (I guess because of great number of messages received). Also, most important is this: star is sometimes on weird positions, like in the middle of something, this happens only on event=3 (foreground). Its strange... somehow putting sleep before processing this event produce different frequencies of this bug. The star is returned to right place as soon as I move the window arround. Fast alttabing sometimes makes the star stay on the same place as before.
Notice that you can right click on star. I planned this so you can exclude certain window (for instance ICQ, Miranda, DesktopX etc..) that are not excluded automaticaly. Now it just reports class of window under it. I done it by making gui holding the star having WS_NOACTIVATE flag.
BTW, enable the tooltip to see event. I desabled it as star flickers cuz tooltip is updated fast as of bunch of events.
Interestingly enough timer worked better. Now, when you move window around CPU goes very high. Timer didn't touch CPU more then 1-2% while moving.
#12
-
Posted 23 May 2007 - 09:33 PM
Solved by adding some lines, as after foreground change, some messages are still received from old foreground window...
Note that you cannot seem to left click on the icon, but right click works... I have not checked to find out why yet.
Note that you cannot seem to left click on the icon, but right click works... I have not checked to find out why yet.
#SingleInstance, force CoordMode, mouse, screen SetWinDelay, -1 SetBatchLines, -1 CoordMode, tooltip, screen 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_HostClass := "#32270" Dock_ClientId := hGui Dock("R","T",0,0,-90,5) Gui, Show, -1500 AutoSize Gui, Hide return GuiContextMenu: hwnd := WinExist("A") WinGetClass class, ahk_id %hwnd% msgbox Exclude %class% ? return OnClick: FMA_SHOW = 3 WM_FAVMENU = 0x399 PostMessage, WM_FAVMENU, FMA_SHOW,,,ahk_id 0xFFFF 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_hHook1 := Hook(hwnd, Dock_msg, 22, 23) ; EVENT_SYSTEM_MINIMIZEEND Dock_hHook2 := Hook(hwnd, Dock_msg, 2) Dock_hHook3 := Hook(hwnd, Dock_msg, 0x800A, 0x800B, "Dock_HookHandler") ;EVENT_OBJECT_STATECHANGE 0x0000800a, EVENT_OBJECT_LOCATIONCHANGE 0x0000800b, return Dock_hHook & Dock_hHookDll } Dock_Timer: Dock_hW:=0 Dock_hH:=0 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 OutputDebug %Dock_HookHwnd%, %Dock_hX%, %Dock_hY%, %Dock_hW%, %Dock_hH%, %Dock_ClientId%, %Dock_cX%, %Dock_cY%, %Dock_cW%, %Dock_cH%, %Dock_sizeX%, %Dock_sizeY%, %count% 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 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) return Undock(){ goSub Dock_Timer 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% if Dock_event = 2 { alert := Dock_HookHwnd return } if (alert = Dock_HookHwnd) ;skip alert windows return WinGetTitle, title, ahk_id %Dock_HookHwnd% if (title = "") return if StrLen(s)>200 s = s .= Dock_event "`n" if (Dock_HookHwnd = Dock_ClientId) { ; if !WinExist("ahk_class " Dock_HostClass) ; WinHide, ahk_id %Dock_ClientId% return } ; if (Dock_cls != Dock_HostClass){ ; if (Dock_event = 3) ; WinHide, ahk_id %Dock_ClientId% ; return ; } ; Tooltip %s%, 0, 0 if (Dock_event = 3) { ;foreground [color=red]currentforeground:=Dock_HookHwnd[/color] gosub Dock_Timer } [color=red] if(currentforeground<>Dock_HookHwnd) return[/color] if (Dock_event = 23) or (Dock_event=0x800B) [color=red]or (Dock_event=0x800A)[/color] ;maximized gosub Dock_Timer if Dock_event = 22 ;minimized WinHide, ahk_id %Dock_ClientId% } 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) } 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) }
#13
-
Posted 23 May 2007 - 11:37 PM
Great.
Works almost like a charm.
Almost is really a small problem. Sometimes, the star doesn't jump to next window. In my situation this: #R (open run) . Repeat: ALT B then ESC fast. In my scenario, once Browse dialog will not get the icon but it will stay at Run.
Other then that, seems to work fine. Thx.
O yeah, button click opens favmenu if it is active among processes
Works almost like a charm.
Almost is really a small problem. Sometimes, the star doesn't jump to next window. In my situation this: #R (open run) . Repeat: ALT B then ESC fast. In my scenario, once Browse dialog will not get the icon but it will stay at Run.
Other then that, seems to work fine. Thx.
O yeah, button click opens favmenu if it is active among processes
PostMessage, WM_FAVMENU, FMA_SHOW,,,ahk_id 0xFFFF
#14
-
Posted 23 May 2007 - 11:47 PM
Poking through autohotkey's code, line 1785 of MsgMonitor in application.cpp suggests that if the message handler is already running, the message is simply discarded rather than being queued, or waiting for the message handler function to finish.
I have verified that messages are dropped at this point when executing the script (with OllyDbg).
It might be easier to simply use a synchronisation object within the hook dll, to prevent multiple messages being sent concurrently...
I will try this next.
JGR
Edit:
Occasionally I get this (after adding some debugging to AHK)
[916] AHK -- Message Dropped -- 0x550 -- event: 0x3 -- window 918460
This is with using critical on the message handler, and using a critical section object around sendmessage in the dll.
I suspect that somehow, the message handler is triggering these early, so that they are subsequently lost, and the OS thinks that they are sent, and does not send them again...
I may try buffering in the dll, instead.
I have verified that messages are dropped at this point when executing the script (with OllyDbg).
It might be easier to simply use a synchronisation object within the hook dll, to prevent multiple messages being sent concurrently...
I will try this next.
JGR
Edit:
Occasionally I get this (after adding some debugging to AHK)
[916] AHK -- Message Dropped -- 0x550 -- event: 0x3 -- window 918460
This is with using critical on the message handler, and using a critical section object around sendmessage in the dll.
I suspect that somehow, the message handler is triggering these early, so that they are subsequently lost, and the OS thinks that they are sent, and does not send them again...
I may try buffering in the dll, instead.
#15
-
Posted 24 May 2007 - 08:51 AM