PostMessage - How to move two windows?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
m3user
Posts: 235
Joined: 17 Jan 2014, 18:11

PostMessage - How to move two windows?

18 Mar 2016, 04:27

Hi, I work on a simple script which include moving tiles on the screen. I know how to move the gui without caption using PostMessage. However I cannot figure out how to move two guis at the same time. In the example below I would like that the second tile (gui) would move together with the first one. Unfortunately only the first PostMessage is working... Any idea how to do this? Thanks!

Code: Select all

Gui, Add, Text, w200 h200 gGuiMove, Drag to move
Gui, -Caption
Gui, Show, x500, gui1

Gui, 2:Add, Text, w200 h200, Should move together with the left one
Gui, 2:-Caption
Gui, 2:Show, x725, gui2

GuiMove:
   PostMessage, 0xA1, 2,,, gui1
   PostMessage, 0xA1, 2,,, gui2
Return
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: PostMessage - How to move two windows?

18 Mar 2016, 08:51

Try this:

Code: Select all

Gui, 1: New, -Caption
Gui, Margin, 0, 0
Gui, Add, Text, w100 h100 Border, Drag to move
Gui, Show, x500, Gui1

Gui, 2: New, -Caption
Gui, Margin, 0, 0
Gui, Add, Text, w100 h100 Border, Will move too
Gui, Show, x725, Gui2

WM_LBUTTONDOWN() {
    PostMessage, 0xA1, 2,,, Gui1
}

WM_WINDOWPOSCHANGED() {
    WinGetPos, x, y,,, Gui1
    WinMove, Gui2,, x + 225, y
}

#SingleInstance, Force
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x47, "WM_WINDOWPOSCHANGED")
Esc:: ExitApp
I hope that helps.
User avatar
lifeweaver
Posts: 144
Joined: 10 May 2014, 05:57
Location: OH
Contact:

Re: PostMessage - How to move two windows?

18 Mar 2016, 09:13

Here is an interesting post by SKAN where he explains that the 0xA1, WM_NCLBUTTONDOWN, merely simulates the message sent when you click on a titlebar. The message allows a window to be dragged, it doesn't actually do any dragging.

You might consider using ControlClick or maybe PostMessage to copy what your mouse is doing. Or use wolf_II's solution
m3user
Posts: 235
Joined: 17 Jan 2014, 18:11

Re: PostMessage - How to move two windows?

18 Mar 2016, 12:57

Thanks to both!

wolf_II: your solution works, unfortunately it is too slow for my purpose and I cannot use it.
lifeweaver: thanks for the informative link. I don't quite understand what you mean I could achieve with ControlClick or copying the mouse. Could you give an example?

Any other solution for moving both windows at the same time?
User avatar
lifeweaver
Posts: 144
Joined: 10 May 2014, 05:57
Location: OH
Contact:

Re: PostMessage - How to move two windows?

18 Mar 2016, 15:01

Here is an interesting note on windows 7:
If you have the 'Show window contents while dragging' checked wolf_II's script makes the second window follow the first real time, if you have it unchecked the second window only moves once you have let the mouse button up. System Properties -> Advanced -> Performance tab -> settings

I wouldn't be surprised if you need to have each gui in its own AutoHotkey process.
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: PostMessage - How to move two windows?

18 Mar 2016, 19:36

Use WinMove on a loop/timer, or if you're feeling adventurous, BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos via DllCall (also on a loop/timer).
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: PostMessage - How to move two windows?

18 Mar 2016, 22:49

@lexikos: something like this perhaps?

Code: Select all

#SingleInstance, Force
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x47, "WM_WINDOWPOSCHANGED")

Gui, 1: New, -Caption hWndhGUI1
Gui, Margin, 0, 0
Gui, Add, Text, w100 h100 Border, Drag to move
Gui, Show, x500, Gui1

Gui, 2: New, -Caption hWndhGUI2
Gui, Margin, 0, 0
Gui, Add, Text, w100 h100 Border, Will move too
Gui, Show, x725, Gui2

Esc:: ExitApp

WM_LBUTTONDOWN() {
    IfEqual, A_Gui, 1, PostMessage, 0xA1, 2
}

;-------------------------------------------------------------------------------
WM_WINDOWPOSCHANGED() { ; faster than light ???
;-------------------------------------------------------------------------------
    global hGUI1, hGUI2

    WinGetPos, x, y,,, ahk_id %hGUI1%
    hDWP := DllCall("BeginDeferWindowPos", "Int", 2) ; move 2 windows
    If hDWP {
        hDWP := DllCall("DeferWindowPos"
            , "Uint", hDWP, "UInt", hGUI1, "UInt", 0
            , "Int", x, "Int", y, "Int", 100, "Int", 100
            , "UInt", 0x0214)
    }
    If hDWP {
        hDWP := DllCall("DeferWindowPos"
            , "Uint", hDWP, "UInt", hGUI2, "UInt", 0
            , "Int", x + 225, "Int", y, "Int", 100, "Int", 100
            , "UInt", 0x0214)
    }
    DllCall("EndDeferWindowPos", "UInt", hDWP)
}
I don't really know how to use a timer for this. :(
So I kept my OnMessages.
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: PostMessage - How to move two windows?

19 Mar 2016, 03:02

m3user wrote:wolf_II: your solution works, unfortunately it is too slow for my purpose and I cannot use it.
Try to add

Code: Select all

#NoEnv
SetBatchLines, -1
SetWinDelay, -1
Also, you can modify the message handlers in this case (Gui2 shall follow Gui1)

Code: Select all

WM_LBUTTONDOWN() {
   If (A_Gui = 1)
      PostMessage, 0xA1, 2,,, Gui1
}
WM_WINDOWPOSCHANGED() {
   If (A_Gui = 1) {
       WinGetPos, x, y,,, Gui1
       WinMove, Gui2,, x + 225, y
   }
}
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: PostMessage - How to move two windows?

19 Mar 2016, 18:33

wolf_II wrote:@lexikos: something like this perhaps?
No and yes. Something like that, but not that. You're still reacting to the movement of one window by moving the other, and there will always be a delay (though subjectively it might not be noticable). The point of DeferWindowPos is to move all of the windows simultaneously, so that a) the user doesn't see each one move one at a time and b) the system doesn't waste time refreshing the screen (perhaps redundantly) in between each move. Your script is passing both GUI HWNDs, but GUI 1 is already in the position you're requesting, which defeats the point of using DeferWindowPos.

To use it on a loop or timer, you would NOT use PostMessage (i.e. you would not start a standard system modal-move loop). Instead, you would retrieve the mouse position at the start and at each iteration, and move both windows according to the difference in mouse position.
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: PostMessage - How to move two windows?

19 Mar 2016, 23:57

I think this is more like lexikos suggested:
(uses 1.1.23+ new build-in variable A_CoordModeMouse)

Code: Select all

#SingleInstance, Force
OnMessage(0x201, "WM_LBUTTONDOWN")

Gui, 1: New, -Caption hWndhGUI1
Gui, Margin, 0, 0
Gui, Add, Text, w100 h100 Border, Drag to move
Gui, Show, x500

Gui, 2: New, -Caption hWndhGUI2
Gui, Margin, 0, 0
Gui, Add, Text, w100 h100 Border, Will move too
Gui, Show, x725

Esc:: ExitApp



;-------------------------------------------------------------------------------
WM_LBUTTONDOWN() { ; moves two windows
;-------------------------------------------------------------------------------
    global hGUI1, hGUI2

    IfNotEqual, A_Gui, 1, Return

    Prev_CoordModeMouse := A_CoordModeMouse
    CoordMode, Mouse, Screen

    MouseGetPos, old_Mx, old_My
    WinGetPos, old_Wx, old_Wy

    While GetKeyState("LButton") {

        MouseGetPos, now_Mx, now_My
        x := old_Wx + now_Mx - old_Mx
      , y := old_Wy + now_My - old_My
      , old_Mx := now_Mx, old_Wx := x
      , old_My := now_My, old_Wy := y

        hDWP := DllCall("BeginDeferWindowPos", "Int", 2) ; 2 windows
        If hDWP {
            hDWP := DllCall("DeferWindowPos"
                , "Uint", hDWP, "UInt", hGUI1, "UInt", 0
                , "Int", x, "Int", y, "Int", 100, "Int", 100
                , "UInt", 0x0214)
        }
        If hDWP {
            hDWP := DllCall("DeferWindowPos"
                , "Uint", hDWP, "UInt", hGUI2, "UInt", 0
                , "Int", x + 225, "Int", y, "Int", 100, "Int", 100
                , "UInt", 0x0214)
        }
        DllCall("EndDeferWindowPos", "UInt", hDWP)
    }
    CoordMode, Mouse, %Prev_CoordModeMouse% ; restore
}
Thank you for the hints!
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: PostMessage - How to move two windows?

20 Mar 2016, 03:07

Yes, that's it.

When calling functions which return handles, it is important that you specify the return type "ptr" or "uptr". If you do not, the handle may be truncated when running with AutoHotkey 64-bit. I think this will only cause problems when one or more of the upper 33 bits are non-zero, and that may be rare, but that just means it may be difficult to debug.

When passing handle values (in) to a function, it is clearer to use the arg type "ptr" or "uptr", but it doesn't make any actual difference with the current implementation.
m3user
Posts: 235
Joined: 17 Jan 2014, 18:11

Re: PostMessage - How to move two windows?

20 Mar 2016, 04:00

Thank you all, all solutions provided are great! :-)

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: boydfields and 149 guests