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 Previous  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: Thu May 24, 2007 11:41 am    Post subject: Reply with quote

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.

Yes, this is even documented

Quote:
I have verified that messages are dropped at this point when executing the script (with OllyDbg).

Can you xplain how did you do this ? I use OllyDbg too, but I am not so hard in reverse eng. If you have time ofc.

Quote:
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.

This complicates somewhat as U must buffer messages.

This is the reason i droped Overdrawn MMenu which was much much kewler - it supported fonts and color per item, named separators etc, but because handler for WM_DRAWITEM was much more complicated blank menus are very frequent. So I had to minimise code in message handlers which leaded to current MMenu that is light variant of my original work

Messages are very problematic aspect of AHK when this kind of low level thingie is in question. I xperienced lot of problems with dropped messages when I was creating MMenu. One of the updates of AHK was related to this:

Quote:
Changed Critical to check messages less often (20 vs. 10ms), which improves the reliability of frequently-called OnMessage functions. [thanks Majkinetor]


Perhaps it can help here, but Chris determined that in MMenu case higher value doesn't do any good (I didn't check this on my own). Previously it was 10ms so you had to return from message handler in 10ms or else you are screwed. I realised that 10ms is so small value that even some single API calls in message handlers like DrawText doesn't return sometimes in that time. Making value to be 20ms this was much better, but sometimes even today MMenu doesn't show icons when you call it, and this is because of that - WM_DRAWITEM messages are droped in some cases and MMenu never receive them. You can see this if you connect MMenu_Show to an hotkey, like F1 and fastly repeat F1 ESC. If you do this long enough, with larger menus you will see that menu don't display icons sometimes (vary rarely with 20ms, like once in 20 fast calls)


This is original MMenu ( I call it SWMenu Smile ). I had to drop it as message droping was very frequent:



_________________


Last edited by majkinetor on Thu May 24, 2007 11:54 am; edited 3 times in total
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 11:43 am    Post subject: Reply with quote

The buffering method was successful:
A wineventhook dll which uses queued input for messages is available here: http://www.autohotkey.net/~JGR/wineventhookq.rar, note that this is a different dll (wineventhookq.dll).
The bug was being caused by recursively triggered hook events, which are now sent to AHK immediately after the causing message handler completes and returns to via sendmessage, such that only one message is sent to AHK at a time. Max number of queued events is 256 in a pre-allocated (BSS-section) circular buffer.

You will have to change the "HookDll = wineventhook.dll" line on line 52, to "HookDll = wineventhookq.dll"

Note that there are still some issues with the start menu...

JGR
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Thu May 24, 2007 11:48 am    Post subject: Reply with quote

I updated previous post.
Thx for the hook update. I will check how it works.
_________________
Back to top
View user's profile Send private message MSN Messenger
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Thu May 24, 2007 12:04 pm    Post subject: Reply with quote

I tried it and it works much better Very Happy

Start menu isn't that much of a problem.

Sometimes icon stays on weird positions. When I call start menu via keyboard, icon is sometimes drawn on it (wihout transparency ?!) when I right click I get

Code:
Exclude DV2ControlHost ?


When I click start menu icon usualy stays in the background, clicking on it gets

Code:
Exclude Shell_TrayWnd ?


So, this sounds like a trivial problem to solve. We can just filter those classes out, and for others Exclude will do the job
_________________
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:10 pm    Post subject: Reply with quote

Here is the full script:
I added a few more things to correct some odd behaviour with bad window coordinates, start menu and desktop.

Code:
#SingleInstance, force
CoordMode, mouse, screen
SetWinDelay, -1
SetBatchLines, -1
CoordMode, tooltip, screen
DetectHiddenWindows, On
SetWorkingDir %A_ScriptDir%


   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 = 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_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%
OutputDebug %nummsg%, %Dock_HookHwnd%, %Dock_hX%, %Dock_hY%, %Dock_hW%, %Dock_hH%, %Dock_ClientId%, %Dock_cX%, %Dock_cY%, %Dock_cW%, %Dock_cH%, %Dock_sizeX%, %Dock_sizeY%, %Dock_Event%
   if(Dock_hX=-32000)
   {
      outputDebug AHK_Hiding_-32000
        WinHide, ahk_id %Dock_ClientId%
   return
   }
   if(Dock_cls="Shell_TrayWnd") {
      OutputDebug AHK_Hiding-Shell_TrayWnd
      WinHide, ahk_id %Dock_ClientId%
      return
   }
   if(Dock_cls="ProgMan") {
      OutputDebug AHK_Hiding-ProgMan
      WinHide, ahk_id %Dock_ClientId%
      return
   }
   if(Dock_hooked_title="Start Menu") {
      OutputDebug AHK_Hiding-Start Menu
      WinHide, ahk_id %Dock_ClientId%
      return
   }
   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
   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
   Critical
   static alert
   
   nummsg:=wParam
   
   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
   Dock_hooked_title:=title

   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
      {
      outputDebug AHK_Hiding
      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)
}


As for debugging with OllyDbg, I originally decided to just find that line and put a breakpoint on it, but that was too much hassle, so I just compiled AHK with map file and assembly with source dump turned on, and put a breakpoint on that return false instruction.
I then just compiled AHK with a call to OutputDebugString API call at the appropriate point, as that was more convenient.

I am becoming an OllyDbg reversing expert from working on TTDP (Transport Tycoon Deluxe Patch) Smile

JGR
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Thu May 24, 2007 1:07 pm    Post subject: Reply with quote

It seems it works great now.

I will update it soon to handle excludes and part

Code:
 if(Dock_cls="Shell_TrayWnd") {
      OutputDebug AHK_Hiding-Shell_TrayWnd
      WinHide, ahk_id %Dock_ClientId%
      return
   }
   if(Dock_cls="ProgMan") {
      OutputDebug AHK_Hiding-ProgMan
      WinHide, ahk_id %Dock_ClientId%
      return
   }
   if(Dock_hooked_title="Start Menu") {
      OutputDebug AHK_Hiding-Start Menu
      WinHide, ahk_id %Dock_ClientId%
      return
   }


will be presetns as

Code:
  if Dock_cls in exclusionList
           WinHide, ahk_id %Dock_ClientId%
           return


ExlusionList will by default contain Start Menu, Tray, Progman and you will be able to simply extend it with righ click.

So, once again, the day is saved. It seems this work very nice now. I saw only once star taking wrong position when I launched Opera. This is strange. It appears like script is asking for a window coordinates and get something else (or again, some other message with another handle bumped in somehow). So I still think it should have filter like

Code:
  If !IsTopLevelWindow(Dock_HookHwnd)
         return


I will have to write such function first, unless smb point me to the already written code.

Thx JGR, u improved community exponentionaly with your work.
_________________
Back to top
View user's profile Send private message MSN Messenger
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Thu May 24, 2007 1:14 pm    Post subject: Reply with quote

I updated first page with latest version
_________________
Back to top
View user's profile Send private message MSN Messenger
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Thu May 24, 2007 2:36 pm    Post subject: Reply with quote

One funny thing happens... don't know how to explain that. Not related to docking.

I have Google talk here. So star jumps on it regulary.

So, i whil Gtalk is active I go to tray and right click its tray icon. Its tray menu appears and at the same time Gui loses its transparency so black color is visible under the icon....

This was happenig to Start menu before. I wonder what is that. It seems to happen only to funny windows - those being toolbar's or start menus or something like that...

AHA, I catched the pattern:

Run this script while TitleButton script is active:

Code:
Gui, +ToolWindow
Gui, Show, h100 w100


Then go to the tray and right click the tray icon of this script. Star goes on funny place.

This solves it:
Code:
   if(Dock_cls="32768") {
;      OutputDebug AHK_Hiding-Menu
      WinHide, ahk_id %Dock_ClientId%
      return
   }

_________________
Back to top
View user's profile Send private message MSN Messenger
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Sun May 27, 2007 11:21 am    Post subject: Reply with quote

New version is available. Check it out at first page.

You can tweak icon position with this line:

Code:
   Dock("L","T", 25, 5)      ;left
;   Dock("R","T",-90, 5)      ;right

_________________
Back to top
View user's profile Send private message MSN Messenger
Laszlo



Joined: 14 Feb 2005
Posts: 4016
Location: Pittsburgh

PostPosted: Sun May 27, 2007 4:51 pm    Post subject: Reply with quote

A few points:
- Instead of the special icon file, you could use some Windows icons, like
Code:
Gui, Add, Picture, icon44 x0 y0 +0x8000 gOnClick, %A_WinDir%\system32\shell32.dll

- What is -1500 in the Gui Show command?
- The GuiContextMenu subroutine should remove the title button of the current window
Code:
GuiContextMenu:
   WinGetClass class, A
   MsgBox 36, FM3, Exclude class:`n`n%class%
   IfMsgBox, No
      Return
   Dock_exclude .= "," class
   Gui, Hide
return

- The PostMessage in the OnClick subroutine does not seem to do anything. Do I have to set something, somewhere?
- If I open another window of the same class as the current one (double click on a URL in MSIE), the title button stays in the old window, until I move the new one.
- The return value of the Dock function should be the logical AND of the handles:
Code:
   return Dock_hHook && Dock_hHookDll

- It is faster to use RtlMoveMemory dll calls in GetHookParams
Code:
GetHookParams(lparam, ByRef event, ByRef hwnd="", ByRef idObject="", ByRef idChild="", ByRef dwEventThread="", ByRef dwmsEventTime="") {
   DllCall("RtlMoveMemory", UIntP,event        , UInt,lParam+ 4, UInt, 4)
   DllCall("RtlMoveMemory", UIntP,hwnd         , UInt,lParam+ 8, UInt, 4)
   DllCall("RtlMoveMemory", UIntP,idObject     , UInt,lParam+12, UInt, 4)
   DllCall("RtlMoveMemory", UIntP,idChild      , UInt,lParam+16, UInt, 4)
   DllCall("RtlMoveMemory", UIntP,dwEventThread, UInt,lParam+20, UInt, 4)
   DllCall("RtlMoveMemory", UIntP,dwmsEventTime, UInt,lParam+24, UInt, 4)
}
You can remove the old, slow GetDeRefInteger function.
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Sun May 27, 2007 5:11 pm    Post subject: Reply with quote

Quote:
- What is -1500 in the Gui Show command?

This one is for autosize only. I don't need to see it so it is offscreen.

Quote:
- Instead of the special icon file, you could use some Windows icons, like

Not so important for testing.

Quote:
The GuiContextMenu subroutine should remove the title button of the current window

It does. You don't need to call Gui, Hide as alert will hide the icon

Quote:
The PostMessage in the OnClick subroutine does not seem to do anything. Do I have to set something, somewhere?

Just set your own thing here
Code:
OnClick:
   FMA_SHOW    = 3
   WM_FAVMENU   = 0x399
   PostMessage, WM_FAVMENU, FMA_SHOW,,,ahk_id 0xFFFF 
return
It currently opens Favmenu which you don't have runnin.

Quote:
If I open another window of the same class as the current one (double click on a URL in MSIE), the title button stays in the old window, until I move the new one.

This is strange.. shouldn't happen.

Quote:
The return value of the Dock function should be the logical AND of the handles:

First lets make this thing work correctly. I will deal with "supportive" things after that.

Quote:
It is faster to use RtlMoveMemory dll calls in GetHookParams

Definitely. I wanted to remove this, thx for making solution. Didn't see until now you already did so for Dock script.
_________________
Back to top
View user's profile Send private message MSN Messenger
Laszlo



Joined: 14 Feb 2005
Posts: 4016
Location: Pittsburgh

PostPosted: Sun May 27, 2007 5:26 pm    Post subject: Reply with quote

majkinetor wrote:
Quote:
- What is -1500 in the Gui Show command?
This one is for autosize only. I don't need to see it so it is offscreen.
Did you mean X-1500? But the next command hides the Gui, so it can be anywhere.
majkinetor wrote:
You don't need to call Gui, Hide as alert will hide the icon
It does not hide the Gui in my system. I need the explicit Gui Hide.
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Sun May 27, 2007 5:54 pm    Post subject: Reply with quote

Quote:
But the next command hides the Gui, so it can be anywhere.
Flicker.

Quote:
It does not hide the Gui in my system. I need the explicit Gui Hide.

Its strange. You see when alert window "Exclude:..." is shown Host loses focus. Then when you answer Y, you will put the host in exlusion list. After that , alert window is destoryed and Host gets the focus again (event=3). Then, it will be catched by this line:

Code:
   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
   }
   


It doesn't harm to set additional Hide however.
_________________
Back to top
View user's profile Send private message MSN Messenger
Ofir



Joined: 27 May 2006
Posts: 121

PostPosted: Mon Jul 30, 2007 10:44 am    Post subject: Reply with quote

i downloaded and compiled.
than when i run it i get:
Quote:
Error at line 47.
Line Text: "R"
Error: Bad default value
Back to top
View user's profile Send private message
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10467

PostPosted: Mon Jul 30, 2007 4:38 pm    Post subject: Reply with quote

You probably need a newer version of AutoHotkey, which you can get at http://www.autohotkey.com/download/
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3  Next
Page 2 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