AutoHotkey / AutoHotkeyDocs

Documentation for AutoHotkey
https://autohotkey.com/
375 stars 746 forks source link

Update Gui.htm #698

Closed iPhilip closed 3 months ago

iPhilip commented 3 months ago

Added a conditional statement about when an owned window is automatically destroyed.

When an owner window is destroyed it automatically destroys the associated owned windows but a thread cannot use the WM_DESTROY message to destroy a window created by a different thread [link].

This works: the second Gui window is destroyed automatically when the first Gui window is destroyed.

MyGui1 := Gui(, 'Owner')
MyGui1.Add('Text', , 'Owner')
MyGui1.Show('x0 y0 w150 h150')
MyGui1.OnEvent('Close', (*) => MyGui1.Destroy())
hwnd := MyGui1.hwnd

MyGui2 := Gui('+Owner' hwnd, 'Owned')
MyGui2.Add('Text', , 'Owned')
MyGui2.Show('x200 y200 w150 h150')

This doesn't work: the Gui window is not destroyed when the Notepad window is destroyed.

Run 'Notepad.exe', , , &PID
WinWaitActive 'ahk_pid ' PID
hwnd := WinExist('A')

MyGui2 := Gui('+Owner' hwnd, 'Owned')
MyGui2.Add('Text', , 'Owned')
MyGui2.Show('x200 y200 w150 h150')

F4::WinClose hwnd  ; Closes the Notepad window but doesn't close the Gui window.
Ragnar-F commented 3 months ago

The new Notepad is a bad example. For me (Windows 11) the script stops working at WinWaitActive because the PID returned by Run is invalid.

With classic applications like WordPad (C:\Program Files\Windows NT\Accessories\wordpad.exe) it works as expected.

iPhilip commented 3 months ago

The new Notepad is a bad example. For me (Windows 11) the script stops working at WinWaitActive because the PID returned by Run is invalid.

Sorry about that. I tested my script using the old Notepad on Windows 10. Here's a version that should work with the new Notepad as well.

hwnd := WinExist('ahk_class Notepad')
if !hwnd
   throw Error('Missing Notepad window.')

MyGui2 := Gui('+Owner' hwnd, 'Owned')
MyGui2.Add('Text', , 'Owned')
MyGui2.Show('x200 y200 w150 h150')

F4::WinClose hwnd  ; Closes the Notepad window but doesn't close the Gui window.

With classic applications like WordPad (C:\Program Files\Windows NT\Accessories\wordpad.exe) it works as expected.

If by "expected" you mean that the Gui window is destroyed, that's not what I observed. The script below shows how the Gui window is not destroyed when the WordPad window is closed. Rather, the Gui window is hidden and can be shown again.

Run 'Wordpad.exe', , , &PID
WinWaitActive 'ahk_pid ' PID
hwnd := WinExist('A')

; hwnd := WinExist('ahk_class WordPadClass')
; if !hwnd
;    throw Error('Missing WordPad window.')

MyGui2 := Gui('+Owner' hwnd, 'Owned')
MyGui2.Add('Text', , 'Owned')
MyGui2.Show('x200 y200 w150 h150')

F3:: {
   WinClose hwnd  ; Hides MyGui2
   MsgBox
   MyGui2.Show()
}
Ragnar-F commented 3 months ago

Okay, I haven't looked into this further. However, "same thread" might be confusing if you assume what a thread means within AutoHotkey. That is, if the GUIs are created in different threads within AutoHotkey, the owned window is still automatically destroyed when the owner is destroyed. Maybe "same script" would be easier to understand.

iPhilip commented 3 months ago

I agree that "same thread" could be confusing. How about the following: "as long as the owner has the same Process ID"?

Ragnar-F commented 3 months ago

Process ID is too specific. I think "created by the same script" is better, unless you have a plausible reason not to use it. If possible, keep it simple for the readers. They may not know what a process is.

iPhilip commented 3 months ago

Sounds good. Keeping things simple for the reader is a good thing.

iPhilip commented 3 months ago

In retrospect, I am concerned that "created by the same script" may lead to confusion. For example, take the above script where a WordPad window is created using Run 'Wordpad.exe', , , &PID. A user may assume that, because the WordPad window was created in the same script, it should work. In fact, it won't.

I would encourage you to reconsider and use "as long as the owner has the same Process ID". A link to a part of the documentation describing what a Process ID is might help those who don't know what it is.