AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

TitleButton 0.31
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Tue May 22, 2007 3:41 pm    Post subject: TitleButton 0.31 Reply with quote

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
View user's profile Send private message MSN Messenger
Rajat



Joined: 28 Mar 2004
Posts: 1718

PostPosted: Tue May 22, 2007 4:58 pm    Post subject: Reply with quote

pretty neat! thanks for sharing.
_________________
Back to top
View user's profile Send private message
mosaic



Joined: 25 Apr 2007
Posts: 20

PostPosted: Wed May 23, 2007 1:17 am    Post subject: A Little Glitch on the TitleButton Reply with quote

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
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Wed May 23, 2007 9:13 am    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
JGR



Joined: 15 Jun 2006
Posts: 52
Location: Unavailable until ~30th August

PostPosted: Wed May 23, 2007 9:31 am    Post subject: Reply with quote

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
View user's profile Send private message
majkinetor!
Guest





PostPosted: Wed May 23, 2007 11:10 am    Post subject: Reply with quote

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

PostPosted: Wed May 23, 2007 11:33 am    Post subject: Reply with quote

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
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Wed May 23, 2007 11:57 am    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Wed May 23, 2007 12:25 pm    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
JGR



Joined: 15 Jun 2006
Posts: 52
Location: Unavailable until ~30th August

PostPosted: Wed May 23, 2007 5:32 pm    Post subject: Reply with quote

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
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Wed May 23, 2007 10:15 pm    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Wed May 23, 2007 10:33 pm    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
JGR



Joined: 15 Jun 2006
Posts: 52
Location: Unavailable until ~30th August

PostPosted: Thu May 24, 2007 12:37 am    Post subject: Reply with quote

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
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Thu May 24, 2007 12:47 am    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
JGR



Joined: 15 Jun 2006
Posts: 52
Location: Unavailable until ~30th August

PostPosted: Thu May 24, 2007 9:51 am    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group