Dock/Attach window function for AHK v2 Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
hiahkforum
Posts: 45
Joined: 08 Feb 2024, 04:21

Dock/Attach window function for AHK v2

17 Apr 2024, 10:03

There are plenty functions of this kind all over the place, which you can find on this forum or here, in particular: https://github.com/Ixiko/AHK-libs-and-classes-collection. Yes, most of them are complex and complicated, this is an important factor, but despite their quantity, not a single author has translated their function to AHK v2 yet! This is very upsetting for noobs like me. :(

I tried to convert this script to v2 on my own, but didn't succeed: https://github.com/alexofrhodes/AHK-DockWindows/blob/main/Class%20Dock.ahk, so can someone help me to reach my goal? It can be different script to translate from or you can take your own shot and do it maybe not so smooth and fancy, but simple.

So, I have GUI which can be activated up to 6 times, and it would be great if all these windows could be linked and moved when one window is moved. As I said, I'm noob, so my function for positioning windows relatively to each other may be not well optimised and good at all, but at least it works at first glance (actually, it works well only when windows are opened in sequential order, but if you close at least one window and open it again, everything breaks, haha).
guiwindows.png
(182.2 KiB) Downloaded 138 times

Code: Select all

f::{
    Static Order := 0
    if Order > 5 {
        return
    }
    G := Gui('+AlwaysOnTop -MinimizeBox +Owner', 'Static Title'), G.SetFont('s15 bold', 'Arial')
    G.Add('Edit', 'r1 w35 +Border +Center +Disabled', ++Order)
    G.OnEvent('Close', (*) => (--Order, G.Destroy())), G.OnEvent('Escape', (*) => (--Order, G.Destroy()))

    if !WinExist('ahk_class AutoHotkeyGUI') {
        G.Show('w425 h285')
    }
    else {
		for This_ID in IDs := WinGetList('ahk_class AutoHotkeyGUI') {
			WinGetPos(&X, &Y, &W, &H, This_ID)
			if IDs.Length = 1 {
				WinMove(X-W/2+9,,,, This_ID)
				G.Show('w425 h285 x' X+W/2-9)
			}
			if IDs.Length = 2 {
				WinMove(, Y-H/2+4,,, This_ID)
				G.Show('w425 h285 y' Y+H/2-5)
			}
			if IDs.Length = 3 {
				WinMove(X-W/2+9,,,, 'ahk_class AutoHotkeyGUI')
				G.Show('w425 h285 x' X+W-18 ' y' Y+H-9)
			}
			if IDs.Length = 4 {
				G.Show('w425 h285 x' X-W+17 ' y' Y+H/2-9)
			}
			if IDs.Length = 5 {
				G.Show('w425 h285 x' X+W*2-35 ' y' Y+H/2-9)
			}
		}
	}
}
hiahkforum
Posts: 45
Joined: 08 Feb 2024, 04:21

Re: Dock/Attach window function for AHK v2

21 Apr 2024, 17:21

Okay, I get it, what I'm asking is probably too complicated or requires a lot of work, so I'll give up. Apparently, I will have to resort to using scripts of 2 versions at once.

Can I then ask for help with that part of the script that I mentioned is not working completely? At first glance, what I'm trying to achieve is very simple and doesn't require much work if you have the knowledge... I've been trying for 2 days now to get all the other windows to be reordered when closing one window.

The best I could achieve was a 90% chance of correct operation, but if you click on some “wrong” window before closing, there is a high chance that the order will be set incorrectly. I assume that this is due to the so-called "z-order change”. I tried, instead of using WinGetList(), which returns an array with the wrong order, to create a Map() to assign the correct number to each HWND every time the GUI is created, but for some reason this did not work and during the for-loop the numbers from Map() were still retrieved in some random way.

Don't look at the mess under else, anything you should try to do is just related to the Close(*) callback.

Code: Select all

f::{
    Static Order := 0, First := 0, Third := 0
    if Order > 5 {
        return
    }
    G := Gui('-MinimizeBox +Owner', 'Static Title'), G.SetFont('s15 bold', 'Arial')
    G.Add('Edit', 'r1 w35 +Border +Center +Disabled', ++Order)
    G.OnEvent('Close', Close), G.OnEvent('Escape', Close)

    if !WinExist('ahk_class AutoHotkeyGUI') {
        G.Show('w425 h285'), First := 1, Third := 1
    }
    else {
		IDs := WinGetList('ahk_class AutoHotkeyGUI'), WinGetPos(&X, &Y, &W, &H, IDs[1])
		(IDs.Length = 1) ? (First ? (WinMove(X-W/2+9,,,, IDs[1]), G.Show('w425 h285 x' X+W/2-9 ' y' Y), First := 0) : G.Show('w425 h285 x' X+W-17 ' y' Y)) :
		(IDs.Length = 2) ? (Third ? (WinMove(, Y-H/2+4,,, IDs[1]), WinMove(, Y-H/2+4,,, IDs[2]), G.Show('w425 h285 x' X-W/2-8 ' y' Y+H/2-5), Third := 0) : G.Show('w425 h285 x' X-W/2-8 ' y' Y+H-9)) :
		(IDs.Length = 3) ? (WinMove(X-W/2+27,,,, IDs[1]), G.Show('w425 h285 x' X+W/2+9 ' y' Y)) :
		(IDs.Length = 4) ? G.Show('w425 h285 x' X-W*2+35 ' y' Y-H/2) :
		(IDs.Length = 5) ? G.Show('w425 h285 x' X+W*3-52 ' y' Y) : ''
	}

	Close(*) {
		--Order, G.Destroy()
		for This_ID in IDsR := WinGetList('ahk_class AutoHotkeyGUI') {
			ControlSetText(IDsR.Length-A_Index+1, 'Edit1', This_ID)
		}
	}
}
Noitalommi_2
Posts: 260
Joined: 16 Aug 2023, 10:58

Re: Dock/Attach window function for AHK v2

22 Apr 2024, 11:37

Hi. @hiahkforum

I can't help you that much with the topic but i thought you might need some help about how to get informations about the guis you are trying to work with. So i made a script you can play around with.
Btw. WM_Move might be interesting later on, if you want to find out if a Gui is moving.

Code: Select all

#Requires AutoHotkey 2.0
#SingleInstance


Hwnds := []

F4::ExitApp
F1::{

    MyGui := Gui("-DPIScale")
	Hwnds.Push(MyGui.Hwnd)
	MyGui.AddText(, "GuiHwnd=" MyGui.Hwnd)
	MyGui.OnEvent('Close', Close)
	MyGui.Show("w400 h100")

	if Hwnds.Length = 1
		OnMessage(WM_WINDOWPOSCHANGED := 0x0047, WINDOWPOSCHANGED)

	Close(GuiObj) {

		for Index, Hwnd in Hwnds
			if GuiObj.Hwnd = Hwnd {

				Hwnds.RemoveAt(Index)
				break
			}
		if Hwnds.Length = 0
			OnMessage(WM_WINDOWPOSCHANGED := 0x0047, WINDOWPOSCHANGED, 0)
	}
}

WINDOWPOSCHANGED(wParam, lParam, *) {

	; https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-windowposchanged

	for Index, Hwnd in Hwnds {
		try WinGetPos(&X, &Y, &Width, &Height, "ahk_id" Hwnd)
		HwndText .= (
						"Gui" Index "Hwnd=" 	(Hwnd ?? "")	"`n"
						"Gui" Index "X=" 		(X ?? "")		"`n"
						"Gui" Index "Y=" 		(Y  ?? "") 		"`n"
						"Gui" Index "Width=" 	(Width ?? "") 	"`n"
						"Gui" Index "Height=" 	(Height ?? "") 	"`n`n"
		)
	}

	ToolTip(

		"GuisTotal=" Hwnds.Length "`n`n"

		"ActivGui:`n" ; shows information about the gui you are dragging around
		"X=" 				NumGet(lParam, 16, "Int") 	"`n" ; The position of the left edge of the window.
		"Y=" 				NumGet(lParam, 20, "Int") 	"`n" ; The position of the top edge of the window.
		"Width=" 			NumGet(lParam, 24, "Int") 	"`n" ; The window width, in pixels.
		"Height=" 			NumGet(lParam, 28, "Int") 	"`n" ; The window height, in pixels.
		"hwnd=" 			NumGet(lParam, 0, "Ptr") 	"`n" ; A handle to the window.
		"hwndInsertAfter=" 	NumGet(lParam, 8, "Ptr")	"`n`n" ; The position of the window in Z order (front-to-back position).
															   ; This member can be a handle to the window behind which this window is placed,
															   ; or can be one of the special values listed with the SetWindowPos function.
		"AllGuis:`n" ; shows information about all guis
		(HwndText ?? "")
	)

}
hiahkforum
Posts: 45
Joined: 08 Feb 2024, 04:21

Re: Dock/Attach window function for AHK v2  Topic is solved

26 Apr 2024, 18:12

I did it! I tried to play around with v1 scripts and it finally worked out for me. The first one I tried was DockA from majkinetor, modified by jballi: viewtopic.php?p=51279. It works fine on AHK v1.1.37.02 when done like this:

Code: Select all

gui 1:-DPIScale +LastFound +Resize +LabelForm1_
gui,1:Show,w400 h300,Form1
hForm1 :=WinExist()

gui 2:+LastFound +Resize +ToolWindow -Sysmenu
gui 2:Show,w300 h200,Form2
hForm2 :=WinExist()

DockA(hForm1,hForm2,"x(1) y() h(1) w(1)")
But doesn't work when HWND1 and HWND2 are windows created in AHK v2:

Code: Select all

HWND1 := WinExist("ahk_class AutoHotkeyGUI", 1)
HWND2 := WinExist("ahk_class AutoHotkeyGUI", 2)
DockA(HWND1,HWND2,"x(1) y()")
Which makes sense, because in the second case the windows are considered external. The only way to use this extremely useful script with v2 is to convert the syntax. I tried to do it myself, but got stuck on the pseudo-arrays that seem to be the basis of the script (which isn't surprising, since this is the very first time I've actually seen v1 syntax). But overall, the script is quite small, and if you already had experience with AHK v1, then it shouldn't be difficult or time-consuming compared to the benefit you will bring, so it will be very valuable if someone decides to do it.

The second thing I tried was Dock from the same majkinetor, modified to work with the more modern version of AHK v1: https://www.autohotkey.com/board/topic/17850-module-dock-10-%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0-testing-20-b3/page-24#entry547469. This script already expects to work with external windows, so through a workaround I was able to get it to work with my windows from AHK v2. I did it like this, I added this code to the beginning of the Dock script:

Code: Select all

#NoEnv
#Persistent
#SingleInstance Force
#NoTrayIcon
SetBatchLines, -1

    Dock_HostID := WinExist("ahk_class AutoHotkeyGUI", 1)
    c2 := WinExist("ahk_class AutoHotkeyGUI", 2)
    c3 := WinExist("ahk_class AutoHotkeyGUI", 3)
    c4 := WinExist("ahk_class AutoHotkeyGUI", 4)
    c5 := WinExist("ahk_class AutoHotkeyGUI", 5)
    c6 := WinExist("ahk_class AutoHotkeyGUI", 6)

    WinGet, Count, Count, ahk_class AutoHotkeyGUI

    Dock(c2, "x(1,,-11) y() h(0.986)")
    (Count == 3) ? Dock(c3, "x(.5) y(1,,-9) h(0.986)") : Dock(c3, "x(,,6) y(1,,-9) w(0.979) h(0.986)")
    Dock(c4, "x(1,,-11) y(1,,-9) h(0.986)")
    Dock(c5, "x(-1,,11) y(.5) h(0.986)")
    Dock(c6, "x(2,,-16) y(.5) h(0.986)")
    return
Then on each G.Show() and Close(*) I call Run('DockL.ahk') function.

All that remains is to fix the renumbering of edit controls to make it possible to reorder windows on closing.

Code: Select all

Close(*) {
	--Order, G.Destroy()
	for This_ID in IDsR := WinGetList('ahk_class AutoHotkeyGUI') {
		ControlSetText(IDsR.Length-A_Index+1, 'Edit1', This_ID)
	}
Does anyone know how to do this the correct way? I will be very, VERY APPRECIATED for this!

Thanks for the reply and at least for trying to help in any way you can, @Noitalommi_2! Since everyone seems to be ignoring me. :cry:
User avatar
boiler
Posts: 17123
Joined: 21 Dec 2014, 02:44

Re: Dock/Attach window function for AHK v2

26 Apr 2024, 21:56

hiahkforum wrote: Since everyone seems to be ignoring me. :cry:
Well, the thread’s subject and first post is mainly about seeing who might want to translate a relatively involved script to v2, so most would probably stop reading there, and each lengthy post after that tends to turn away pretty much everyone else who made it that far. Make it easy for helpers to help you with a thread asking for help with a short script isolating the issue of concern. They’re not looking for a homework assignment.
hiahkforum
Posts: 45
Joined: 08 Feb 2024, 04:21

Re: Dock/Attach window function for AHK v2

27 Apr 2024, 21:35

I go by the logic that if I'm asking about something that is directly related to my problem, then I should write a post instead of creating a separate topic, which is good communication manners in my opinion. But I see your point, and since the moderator supports the principle of “fewer posts - more topics to get maximum attention”, then from now on I should stop being shy about creating separate topics for the slightest problems, so that's what I did: viewtopic.php?f=82&t=129361

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: marypoppins_1, usser and 42 guests