AutoHotkey Community

It is currently May 25th, 2012, 6:38 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 352 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7 ... 24  Next
Author Message
 Post subject:
PostPosted: May 25th, 2007, 10:43 pm 
Offline

Joined: March 2nd, 2004, 3:36 pm
Posts: 10720
Nice demo and encapsulation. I noticed one tiny typo:
Code:
OnMessage(com_msg)
; ...should probably be:
OnMessage(com_msg, "") ; Specify an empty string ("") or an empty variable to turn off the monitoring of MsgNumber.
My tentative priorities now are to work on the mechanisms to support the standard library, and then work on v2. Therefore, it's probably best that this docking feature either: 1) Be made a part of the standard library; or
2) Be incorporated into the code by some other developer.

Thanks.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 27th, 2007, 10:17 am 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
2 JGR

For what reason we monitor EVENT_OBJECT_STATECHANGE ?

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 27th, 2007, 10:39 am 
Offline

Joined: June 15th, 2006, 6:29 am
Posts: 59
Location: Oriel College
It seems to be sent during minimise, maximise and restore operations, but so is EVENT_OBJECT_LOCATIONCHANGE is suppose, have you tested it without monitoring that message? The name suggests that it would be sent during window enable/disables as well (but I haven't tested or researched this).
If it makes no difference you can just exclude it...

JGR


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 27th, 2007, 11:16 am 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
Well, I am having pretty good time here :roll: tryint to make TitleButton work in every case :D

Laszlo did well when he replaced Dock_HostClass with DOck_HostID. THis filters many things as you can only do
Code:
  if Dock_hwnd != Dock_HostId


I don't have this in TitleButton as it must catch every window.

Quote:
If it makes no difference you can just exclude it...

I excluded it, seems to make no difference. Anyway, you can't enable/desable top level window, only child control.

This is the latest TitleButton script. Button is now on the left. Tray, start menu and such are now in
Code:
   Dock_exclude=Shell_TrayWnd,32768,Progman,DV2ControlHost


Remember that depending on additional make-up things you might have, like me (DesktopX, ObjectDock etc...) you may get star sometimes on funny position. Just right click it to exclude this win. This is not remebered accross sesions for now.


Code:
#SingleInstance, force
SetWinDelay, -1
SetBatchLines, -1
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_exclude=Shell_TrayWnd,32768,Progman,DV2ControlHost
   Dock_ClientId := hGui

   Dock("L","T", 25, 5)      ;left
;   Dock("R","T",-90, 5)      ;right
   Gui, Show, -1500 AutoSize
   Gui, Hide
return



GuiContextMenu:
   hwnd := WinExist("A")
   WinGetClass class, ahk_id %hwnd%
   msgbox 36, FM3, Exclude class:`n`n%class%
   ifMsgBox, No
      return

   Dock_exclude .= "," class   
return

OnClick:
   FMA_SHOW    = 3
   WM_FAVMENU   = 0x399
   PostMessage, WM_FAVMENU, FMA_SHOW,,,ahk_id 0xFFFF 
return


Dock(H="R",V="T", 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_hHook2 := Hook(hwnd, Dock_msg, 2)                           ;alert
   Dock_hHook0 := Hook(hwnd, Dock_msg, 3)                           ;EVENT_SYSTEM_FOREGROUND
;   Dock_hHook1 := Hook(hwnd, Dock_msg, 22, 23)                        ;EVENT_SYSTEM_MINIMIZEEND
   Dock_hHook3 := Hook(hwnd, Dock_msg, 0x800B, 0x800B, "Dock_HookHandler")  ;EVENT_OBJECT_STATECHANGE ,EVENT_OBJECT_LOCATIONCHANGE


   return Dock_hHook & Dock_hHookDll
}

Dock_Update:

   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_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)
   WinShow, ahk_id %Dock_ClientId%
return


Undock(){
   goSub Dock_Update
   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%
   WinGetTitle, title, ahk_id %Dock_HookHwnd%
   WinGet, style, Style, ahk_id %Dock_HookHwnd%
;   OutputDebug AHK-Dock: ENTER %dock_event% %title% %dock_cls%   

   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
   }
   
   if (title = "") or !(style & 0xC00000) or !(style & 0x10000000)   or (style & 0x40000000) {   ; WS_CAPTION = C00000 , WS_VISIBLE = 0x10000000, WS_CHILD = 0x40000000
      return
   }

   if (Dock_event = 2) {      
;      OutputDebug AHK-Dock: %dock_event% %title% %dock_cls%
      alert := Dock_HookHwnd               ; remember alert win
      return
   }
   if (alert = Dock_HookHwnd)               ; skip alert windows
      return

   if (Dock_event = 3)   {                  ; Foreground
;      OutputDebug AHK-Dock: %dock_event% %title% %dock_cls%
      gosub Dock_Update
      return
   }

   if (Dock_event=0x800B) ;or (Dock_event=0x800A) or (Dock_event = 23) 
   {
 ;      OutputDebug AHK-Dock: %dock_event% %title% %dock_cls%
      gosub Dock_Update
      return
   }
}


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)
}


_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 27th, 2007, 6:33 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
Another version.

2Laszlo
I did some more optimisation as we are aproaching v1.0. As script is like 50 lines, those will be easy to spot. I also removed 3 hook types as they seem to be non important once EVENT_OBJECT_LOCATIONCHANGE is introduced.

One last thing is still missing. User handler on host death. I am not sure how do to this without monitoring additional events which I don't like as EVENT_OBJECT_LOCATIONCHANGE already spam like crazy.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 28th, 2007, 1:14 am 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
- Version 0.96 still works OK.
- In the function Hook_Shutdown, the "" are missing in OnMessage(com_msg,""), as Chris noted.
- I wonder, if you want to get rid of Globals, all together. One way to do this to introduce a function DockGlobals, with a lot of ByRef parameters, and another one GETorSET. The globals can be then replaced by Static variables in DockGlobals. This is slow and clumsy, but requires little change in the code. The best was to pass everything in function parameters, which may not be possible, for example with Dock_HostID in the function Dock_HookHandler. This function could be called with a special parameter, indicating that Dock_HostID is given in another parameter, which has to be stored in a Static variable. The ultimate goal can be supporting multiple client windows, dynamically dock/undock them.
- (Host death) Location change messages might be numerous, but if there is a message sent when a window is closed, catching it does not add much overhead. How many windows can you close in a second?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 28th, 2007, 8:22 am 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
Quote:
- In the function Hook_Shutdown, the "" are missing in OnMessage(com_msg,""), as Chris noted.

yeh...forgot about that

Quote:
I wonder, if you want to get rid of Globals, all together.

Well, I think its fine now. You already know that update routine must be as fast as possible due to the large number of messages dock hanlder can receive. So, the only reasonable solution is to set statics in Dock_Update() function.

Globals are also problematic for "multiple dock instances" but that is some other story. I noticed many ppl impose a limit on number of instances by using globals. For instance, initial version of IE control by Sean had this limitation cuz of globals. As soon you instantiate second web control you fuked up previous .

Quote:
The ultimate goal can be supporting multiple client windows, dynamically dock/undock them.

Yeah, multidock. I was thinking about this, can be easily done by specifying dock number and remembering globals like Dock_%num%_XXX then iterating over names and dock clients in update routine. Sounds trivial. Something like:

Code:
  Dock_ClientID1 := ...
  Dock_ClientID2 := ...
  Dock_ClientID3 := ...
  Dock_HostId := ...
  Dock(.... , 1)
  Dock(....., 2)
  Dock(......,3)



Quote:
How many windows can you close in a second?

Like 100 windows in millisecond. Everything is window. Application having 50 buttons (common) when dies will produce Dock_Update work like crazy. The very same happens now with LOCATION_CHANGE. The MSDN states that LOCATION_CHANGE is not called for child windows UNLESS parent is resizing them :D.... Seems that Anchor produces this kind of effect (message spam). In title button I am checking style to filter out everything that has WM_CHILD, !WM_CAPTION and even !WM_VISIBLE (it seams that even invisible windows get "activated" when you click on the tray icon, for instance hidden ahk debuger)

I solved this easy for TitleButton.
In TB, I used this mechanism: when host dies another application receives focus. Something like:

Code:
if event=3 and Dock_HostID != HookHwnd and !died and !WinExist("ahk_id " Dock_hostID) {
    died := 1
    GoSub Dock_UserDeathHandler   
    return
}



Well, i think this works fine now, perhaps we should check what we can do with real hoook (SetWindowHookEx). There we have much better control of events IIRC. WinEvent group single events into clases.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 28th, 2007, 11:03 am 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
2 Laszlo

We can add aditional param to the Dock function. The one that will NOT create the hook :D. U probably now think I am crazy, but Update routine in last version can be used as a general positioning goodie.

The effect would be the same as this:

Code:
   Dock(0,-1,-10, 0,0,0, 0,100, 0,180)      ; left, top
   Dock_ShutDown()                     ; :D
   Dock_Update(Dock_HostId)            ; :D


After this, the one can manualy call Dock_Update whenever it wants to update docking to certain host but still keep familiar Dock interface

What do you think ?

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 28th, 2007, 4:56 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Sounds to be useful.

Non-permanent docking applications can be in explorer, when the user wants his favorite folders shown for fast navigation (so they never cover important info), just until he makes a selection. Similarly with open/save dialogs. In editors you can pop up a window with the number of characters, words, etc., always on the side. In a browser, when the address bar is selected, a list of favorites could be shown, and so on.

The main advantage of a window position tool like this is that it can be relative to another window in position and/or size, and the programmer does not need to figure the math: it is already done for him in the Dock function.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 28th, 2007, 5:21 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
Exactly.

This makes my previous note that we need to keep original WIndow GUI size in case user didn't specify them, even more needed.

Perhaps we can do this if whw & whd are zero (as it is miningless), and the same for height.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 28th, 2007, 5:37 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
majkinetor wrote:
we need to keep original WIndow GUI size in case user didn't specify them, even more needed... if whw & whd are zero (as it is miningless), and the same for height.
it is an alternative. I don't know if a non-numeric parameter ("W" as in my last posted code) or a pair of 0's is more intuitive. You can certainly save typing the quotes ;)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 28th, 2007, 6:00 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
Well, I beleive that only I like your syntax :)
After all, we are both ex-math proffesors :P

In previous syntax this was trivial and already implemented as such.
Perhaps we can devise something more user friendly :lol:

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 29th, 2007, 3:48 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
A couple of more typos:
- API_FreeLibrary() should have parameter Dock_hHookDll, not HookDll, in two places
- In the Dock function Dock_hHook2 is not defined any more, so the statement "If !(Dock_hHook1 && Dock_hHook2 && Dock_hHook3)" is always true (need to remove Dock_hHook2). It does not free the library, though, because of the bug above.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 29th, 2007, 5:07 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
Thx... now its good time to polish the script.
I always leave that for v1.0.

Anyway, Laszlo feel free to do updates on your own from the current version. If you find something, why don't u correct it imediately and post modified script here so I can update the first post.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 1st, 2007, 5:20 pm 
Offline

Joined: October 7th, 2005, 9:46 pm
Posts: 13
Great script everyone- I have been using it often.
There is an inconsistancy that occurs with the docked window when the dock host is minimized. Sometimes the window will go to the bottom left of the screen (can only see a small edge of it), or it will not move at all. I have made the following change to the Dock_Update function, which fixes the problem for me.
Code:
        If (hX="") or (hX=0 and hW=160)
          WinMove ahk_id %Dock_ClientId%,,-32000,-32000
        else
          WinMove ahk_id %Dock_ClientId%,,X,Y,W,H


Feel free to add it or modify it.
Thanks for all the work!


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 352 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7 ... 24  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: bbwht and 15 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group