 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
majkinetor
Joined: 24 May 2006 Posts: 3615 Location: Belgrade
|
Posted: Tue May 22, 2007 3:41 pm Post subject: TitleButton 0.31 |
|
|
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 _________________

Last edited by majkinetor on Fri Nov 09, 2007 7:20 pm; edited 9 times in total |
|
| Back to top |
|
 |
Rajat
Joined: 28 Mar 2004 Posts: 1717
|
Posted: Tue May 22, 2007 4:58 pm Post subject: |
|
|
pretty neat! thanks for sharing. _________________
 |
|
| Back to top |
|
 |
mosaic
Joined: 25 Apr 2007 Posts: 20
|
Posted: Wed May 23, 2007 1:17 am Post subject: A Little Glitch on the TitleButton |
|
|
| 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. |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3615 Location: Belgrade
|
Posted: Wed May 23, 2007 9:13 am Post subject: |
|
|
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. _________________
 |
|
| Back to top |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Wed May 23, 2007 9:31 am Post subject: |
|
|
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 |
|
| Back to top |
|
 |
majkinetor! Guest
|
Posted: Wed May 23, 2007 11:10 am Post subject: |
|
|
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. |
|
| Back to top |
|
 |
Thalon
Joined: 12 Jul 2005 Posts: 640
|
Posted: Wed May 23, 2007 11:33 am Post subject: |
|
|
The button does also disappear if window loses focus.
But this is a very usefull feature (if maximize-code is added).
Thx!
Thalon _________________ AHK-Icon-Changer
AHK-IRC
deutsches Forum
SacredVault |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3615 Location: Belgrade
|
Posted: Wed May 23, 2007 11:57 am Post subject: |
|
|
| Quote: | | The button does also disappear if window loses focus. |
I know about this but this is not something very important.
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.
| Quote: | | But this is a very usefull feature (if maximize-code is added). |
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...
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... _________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3615 Location: Belgrade
|
Posted: Wed May 23, 2007 12:25 pm Post subject: |
|
|
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).
| Code: | #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)
}
|
_________________
 |
|
| Back to top |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Wed May 23, 2007 5:32 pm Post subject: |
|
|
Maximise is fixed already:
See here, changes are added into the dock script.
Event 0x800A EVENT_OBJECT_STATECHANGE, for maximise/restore and event 0x800B EVENT_OBJECT_LOCATIONCHANGE, for window movement (no timer necessary). |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3615 Location: Belgrade
|
Posted: Wed May 23, 2007 10:15 pm Post subject: |
|
|
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
| Code: | 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. _________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3615 Location: Belgrade
|
Posted: Wed May 23, 2007 10:33 pm Post subject: |
|
|
Well, check it out yourself here:
| Code: | #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. _________________
 |
|
| Back to top |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Thu May 24, 2007 12:37 am Post subject: |
|
|
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.
| Code: | #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
currentforeground:=Dock_HookHwnd
gosub Dock_Timer
}
if(currentforeground<>Dock_HookHwnd)
return
if (Dock_event = 23) or (Dock_event=0x800B) or (Dock_event=0x800A) ;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)
} |
|
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3615 Location: Belgrade
|
Posted: Thu May 24, 2007 12:47 am Post subject: |
|
|
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
| Code: | | PostMessage, WM_FAVMENU, FMA_SHOW,,,ahk_id 0xFFFF |
_________________
 |
|
| Back to top |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Thu May 24, 2007 9:51 am Post subject: |
|
|
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. |
|
| 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
|