 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Thu May 24, 2007 11:41 am Post subject: |
|
|
| 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 ). 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 |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Thu May 24, 2007 11:43 am Post subject: |
|
|
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 |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Thu May 24, 2007 11:48 am Post subject: |
|
|
I updated previous post.
Thx for the hook update. I will check how it works. _________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Thu May 24, 2007 12:04 pm Post subject: |
|
|
I tried it and it works much better
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 |
|
 |
JGR
Joined: 15 Jun 2006 Posts: 52 Location: Unavailable until ~30th August
|
Posted: Thu May 24, 2007 12:10 pm Post subject: |
|
|
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)
JGR |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Thu May 24, 2007 1:07 pm Post subject: |
|
|
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 |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Thu May 24, 2007 1:14 pm Post subject: |
|
|
I updated first page with latest version _________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Thu May 24, 2007 2:36 pm Post subject: |
|
|
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 |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Sun May 27, 2007 11:21 am Post subject: |
|
|
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 |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Sun May 27, 2007 4:51 pm Post subject: |
|
|
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 |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Sun May 27, 2007 5:11 pm Post subject: |
|
|
| 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 |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Sun May 27, 2007 5:26 pm Post subject: |
|
|
| 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 |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Sun May 27, 2007 5:54 pm Post subject: |
|
|
| 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 |
|
 |
Ofir
Joined: 27 May 2006 Posts: 121
|
Posted: Mon Jul 30, 2007 10:44 am Post subject: |
|
|
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 |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
|
| 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
|