Proposed New GUI API for AutoHotkey v2

Discuss the future of the AutoHotkey language
lexikos
Posts: 9551
Joined: 30 Sep 2013, 04:07
Contact:

Re: Proposed New GUI API for AutoHotkey v2

25 Mar 2017, 03:26

fincs wrote:This was inspired by OnExit, OnClipboardChange and OnMessage.
For argument's sake, I would say that these functions have different usage, so the familiar naming could be a hindrance rather than a help. These are functions used to register (add) callback functions, whereas OnClose and family are both name suffixes and properties to be assigned. It's similar to how in (older) v1 OnMessage accepted a function, OnExit accepted a label, and OnClipboardChange was a label.

I had idly considered whether it was worth implementing a method of registering events similar to the On..() functions; i.e. allowing multiple handlers for each event. It can be added later if someone decided it would be a valuable feature (even if the same name is used, since Gui.OnClose(x) raises an error), but then Gui.OnClose := x would be twice redundant. Maybe one of the existing implementations (e.g. from OnMessage) can be reused for this.
These are very generic words that could cause trouble if the Gui handler class contains a similarly named member.
Perhaps the default prefix should be "On" when an event sink object is specified. I suppose "Gui" works too.
Also, I suppose the names of the event getters/setters (e.g. gui.OnClose := Func("somefunc").Bind("Close")) will keep the On prefix.
That was the idea, unless they are replaced with something else.
... and if the beforementioned Prefix/g option were introduced for (non-control) Gui event handlers, there would be no need whatsoever for a Gui event prefix.
Prefix/g was just to allow an object and a prefix to be combined. I don't think it has any bearing on whether GUI events and control events share a prefix, unless you consider more specific alternatives, like "GuiPrefix" and "CtrlPrefix". I think the character "g" only makes sense if it's to be combined with the control's "g" option (i.e. a shared prefix, or a prefix for all controls but not GUI events).
In fact there were so many possible events that a certain group of them have to be explicitly enabled with the AltSubmit option. Perhaps this should be broken up in smaller, single-purpose handlers just like the set of event handlers that Gui themselves have.
I think that's worth considering in combination with a different mechanism to register event handlers; e.g. an OnEvent or addEventListener-like method instead of several event properties.

But then we'd have to consider whether it's worth keeping the single-handler-for-all-events method ("g" option) as well, to facilitate the transfer from v1 (or any other reason, like simplifying code reuse across multiple events). If not, I suppose that would supersede the following question:

Do you think there's value in keeping strict "Event, EventInfo, ErrorLevel" parameter ordering for all control types? For instance, Link controls pass "Normal", LinkIndex, HrefOrID where probably only HrefOrID is needed. ListBox controls might not care about click vs double-click (Event), but probably want the row number (EventInfo).
gui.AddLabel,, Text
I see your point. I tend to omit the initial comma, so being required to write double-comma rather than nothing would be a slight irritation. On the other hand, Gui Add, Text,, Text always required double-comma.
But again, if GuiCreate keeps Title first, it would be inconsistent with it.
One may also consider MsgBox, InputBox and TrayTip, which all use "Text, Title, Options" as of v2.0-a078.
lexikos
Posts: 9551
Joined: 30 Sep 2013, 04:07
Contact:

Re: Proposed New GUI API for AutoHotkey v2

25 Mar 2017, 03:30

just me wrote:IMO, the prefix should not be used as prefix for control event handlers.
I'm leaning that way myself. It seems odd for "gXXX" to not call XXX. If one wants a common prefix, it's probably better to write it explicitly for every control.

Actually, it's done for both "gXXX" and Gui.OnEvent := "XXX". It's easy enough to add Func() in that case, but it might be more intuitive to use the prefix only when the name is an automatic one, not specified by the user. That could include "MyGuiButtonOK" (I don't think any other control types have an automatic handler).
Gui.Pos() ; Returns the position in an object containing x,y,w,h fields.
There's already Control.Pos, so that seems sensible.

As for Gui.Size(), I don't think it makes sense for Pos() and Size() to return the size of two different things. Also, I think it would be more useful to have Gui.ClientPos return the position and size of the client area.
I'd prefer to separate vName and gEventHandler from Options.
I don't really disagree, but I'm wary of creating lengthy parameter lists.
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

25 Mar 2017, 05:36

lexikos wrote:I don't really disagree, but I'm wary of creating lengthy parameter lists.
I wouldn't call this lengthy. But there seem to be other options.

Why doesn't this work?

Code: Select all

MyGui := GuiCreate("Test")
C := MyGui.AddLabel("Let's add some text to be shown in the GUI")
C.Name := "MyLabel" ; <- Error:  Unknown property or method.
MyGui.Show()
User avatar
fincs
Posts: 527
Joined: 30 Sep 2013, 14:17
Location: Seville, Spain
Contact:

Re: Proposed New GUI API for AutoHotkey v2

25 Mar 2017, 07:40

lexikos wrote:Perhaps the default prefix should be "On" when an event sink object is specified. I suppose "Gui" works too.
How about the default prefix being On for event sink objects, and Gui for regular functions? That way GuiClose() would exist and it would feel familiar.
lexikos wrote:Do you think there's value in keeping strict "Event, EventInfo, ErrorLevel" parameter ordering for all control types? For instance, Link controls pass "Normal", LinkIndex, HrefOrID where probably only HrefOrID is needed. ListBox controls might not care about click vs double-click (Event), but probably want the row number (EventInfo).
Changing each control type's event handler argument list to be more natural as you suggested would make a lot of sense, even if it involved more work in porting scripts. I get the impression that recent control additions (Link, Custom, etc) were trying to work around the quirks of the design of each Gui event BIV and ended up with something unwieldy; practically requiring users to read documentation everytime they are used.
lexikos wrote:One may also consider MsgBox, InputBox and TrayTip, which all use "Text, Title, Options" as of v2.0-a078.
;)
On the other hand, I realized that for some control types (mostly input related) such as Edit, the Text parameter won't really be used as much as the Options parameter; so we would be back to dealing with the same problem. Users would be irritated that Gui, Add, Edit, vMyEdit would become gui.AddEdit,, vMyEdit (or gui.AddEdit("", "vMyEdit") for that matter). Ultimately I don't know what benefits most users.
lexikos wrote:I'm leaning that way myself. It seems odd for "gXXX" to not call XXX. If one wants a common prefix, it's probably better to write it explicitly for every control. (...) it might be more intuitive to use the prefix only when the name is an automatic one, not specified by the user. That could include "MyGuiButtonOK"
Alright, so in that case control event function names should not use the prefix name. Actually, I am not sure whether automatic button event handlers are a good idea. I remember being confused a long time ago by scripts that used them instead of g-labels ("why doesn't this button have a g-label?" "why is there this label that seems to be for the button yet never referenced and for some reason it works somehow?")
just me wrote:Why doesn't this work?
Control names are supposed to be unique identifiers for each control so that they can be accessed by gui.Control["Name"] and through gui.Submit(). Unique identifiers aren't supposed to be changed after something is created. Note that v1.x didn't let you change the associated variable of a control either since their name was also used as a unique identifier. In your case it would suffice to add the vMyLabel option to your label.
fincs
Windows 11 Pro (Version 22H2) | AMD Ryzen 7 3700X with 32 GB of RAM | AutoHotkey v2.0.0 + v1.1.36.02
Get SciTE4AutoHotkey v3.1.0 - [My project list]
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

25 Mar 2017, 10:53

fincs wrote:Control names are supposed to be unique identifiers for each control so that they can be accessed by gui.Control["Name"] and through gui.Submit(). Unique identifiers aren't supposed to be changed after something is created.
fincs wrote:

Code: Select all

GuiControl object
-----------------
...
ctrl.Name
  Retrieves or sets the explicit name of the control.
Only one can be true. ;)
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

25 Mar 2017, 11:36

Another issue:

Code: Select all

MyGui := GuiCreate("Test", "+OwnDialogs")

C := MyGui.AddLabel("Add some clickable text to be shown in the GUI", "+Border")
C.Event := "LabelClicked" ; <- doesn't work, I assume that the SS_NOTIFY style isn't added

C := MyGui.AddButton("Click me!")
C.Event := "ButtonClicked"

MyGui.Show()

LabelClicked() {
   MsgBox("Label clicked!")
}

ButtonClicked() {
   MsgBox("Button clicked!")
}
lexikos
Posts: 9551
Joined: 30 Sep 2013, 04:07
Contact:

Re: Proposed New GUI API for AutoHotkey v2

25 Mar 2017, 17:50

just me wrote:I wouldn't call this lengthy.
There would still be many cases where one would have to count the commas because several parameters are omitted. I think it becomes harder to remember the position of the parameter when you aren't using the other parameters.
Why doesn't this work?
As far as I can tell, Control.Name hasn't been implemented, but Control.Opt vName works after a control is created.
I assume that the SS_NOTIFY style isn't added
That's a good assumption. Looks like it's only done by "gXXX" at the moment. C.Opt +0x100 evidently makes it work.
fincs wrote:Actually, I am not sure whether automatic button event handlers are a good idea. I remember being confused a long time ago by scripts that used them instead of g-labels
Were Gui event labels somehow more intuitive? Menu items have the same kind of automatically constructed default label, except that the label is required to exist (which is inconvenient for me, because usually I just want to add an item that does nothing for testing purposes ;)). Unlike most controls, buttons are generally useless without an associated label/function, so it makes sense to hook them up by default.
Unique identifiers aren't supposed to be changed after something is created.
There doesn't appear to be any harm, and it might be useful to someone. It only has to be unique, not permanent.
lexikos
Posts: 9551
Joined: 30 Sep 2013, 04:07
Contact:

Re: Proposed New GUI API for AutoHotkey v2

25 Mar 2017, 23:27

Update: This test build is obsolete. See the next test build.

AutoHotkey_2.0-a078-19+gcfbf0a0.zip
I have finished reviewing the new code and made changes as follows:

Added GuiControl.Name.

Fixed Gui.BgColor/CtrlColor to accept pure numbers. Gui.BgColor := n is not the same as Gui.BgColor := "" n because v2 uses mandatory decimal formatting, whereas BgColor expects a hexadecimal string.

Fixed use of ErrorLevel by GuiControl.Opt(). It was setting ErrorLevel only on failure to apply styles or if +g was used with an invalid control type, never on success. Now it sets ErrorLevel to indicate success or failure to apply styles and throws an exception if +g is used incorrectly.

Some code changes and fixes which won't interest or affect most people.
Corrected error-handling and messages in several places.
Fixed crashes resulting from destruction of partially constructed Gui. This affects GuiCreate(,, "not valid").
Fixed handling of pure numeric values by some Gui methods/properties.
Fixed GUI option strings remaining truncated when an error is raised.
Fixed Custom controls to respect the correct max-threads limit.
Fixed Gui being destroyed on close if !Gui.OnClose even if RefCount>1.
Fixed GuiControl.Event := "" to not throw an exception after it clears the event handler.
Fixed LabelControl.Event := x to apply SS_NOTIFY style.

I have not yet acted on most of the ideas brought up in this topic.

Some other concerns that my review brought up:

[Update: This option name was removed as WS_EX_ACCEPTFILES is applied or removed automatically.] There is now an option +/-Drop which applies or removes WS_EX_ACCEPTFILES. Shouldn't it be DropFiles?

[Update: +OwnDialogs is not the default anymore.] Gui.Opt("+OwnDialogs") is now the default for threads launched by Gui, because it "Seems like a sensible default". Does it really? I think it would be safer to let the author apply that option if he really wants the GUI to be disabled when a dialog is shown.

Arrays used to populate a control (e.g. ListBox) don't start at element 1, but rather, all integer-keyed elements are used. This is inconsistent with variadic calls (though for those leaving a gap in the array is meaningful). Would it be more or less intuitive to ignore elements at index < 1? How should omitted items (["A",,"C"]) be handled?

[Update: Submit does not store values of controls which don't accept user input, nor ActiveX.] Gui.Submit() stores ActiveX objects and Progress control values. These are not the result of user input, so in v1 they are not stored. An ActiveX object likely would have already been retrieved by the script in order to set up the control. The value of a Progress control is always what the script specified (unless some external program sent it a message). Does it make any sense to include these in Submit()?

[Update: "Cancel" no longer has any special meaning; also, g-labels were replaced with OnEvent.] Control events can't use the function or method name/suffix "Cancel", except by passing a reference to a function or bound method. In v1, if a label named "Cancel" was defined, it took precedence. This small exception could catch someone by surprise, but I'm not sure how to deal with it.

[Update: LastFound was restored.] +LastFound and +LastFoundExist were removed. +LastFoundExist is obsolete and not applicable anymore, but +LastFound is still useful for applying Win/Control functions to a Gui. Although WinExist("ahk_id " Gui.Hwnd) sets the last found window, it only works if the GUI is visible. (On the other hand, someone suggested changing ahk_id to ignore DetectHiddenWindows.)

These final notes aren't issues per se, but may be important to anyone coming from the old API:

The Slider control's +Buddy%N%%Control% option required a variable name in v1. It still needs to be a control created by the Gui API, but now it works by HWND, name, or the first word of the text/ClassNN (because of the way options are parsed). (ClassNN takes precedence over text, as per the standard "control ID" behaviour.) I presume this change was a side-effect of fincs having removed the "vName" option completely in his early builds.

When a Tab control's g-label is called in v1, its output var is set to the previously selected tab. With the new API, the script will be required to keep track of the tab if needed (i.e. store it in a variable for use by the next call).
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

26 Mar 2017, 03:34

Thanks, all my issues are fixed now.
lexikos wrote:There is now an option +/-Drop which applies or removes WS_EX_ACCEPTFILES. Shouldn't it be DropFiles?
Seems to be available only for Gui windows. I don't see the benefit, but vote for +/-DropFiles.
Gui.Opt("+OwnDialogs") is now the default for threads launched by Gui, ...
It shouldn't.
Arrays used to populate a control (e.g. ListBox) don't start at element 1 ...
It should be restricted to simple arrays starting at index 1.
+LastFound and +LastFoundExist were removed.
What do you think about a new variable A_LastFoundWindow (read/write)? It's part of my internal wish list for a long time.

Some addition to my wish list:

Code: Select all

Gui.Styles
Gui.ExStyles
Ctrl.Styles
Ctrl.ExStyles
LVCtrl.LVExStyles
TVCtrl.TVEyStyles
  Retrieves or sets ...
lexikos
Posts: 9551
Joined: 30 Sep 2013, 04:07
Contact:

Re: Proposed New GUI API for AutoHotkey v2

26 Mar 2017, 05:43

just me wrote:I don't see the benefit, but vote for +/-DropFiles.
v1 adds or removes WS_EX_ACCEPTFILES automatically depending on the presence or absence of a DropFiles label. It isn't done that way anymore, presumably because of the difficulty in detecting methods. If you don't apply the style/option, the window won't accept files, so the OnDropFiles event will never be raised.
What do you think about a new variable A_LastFoundWindow (read/write)?
I would never use it. I assume you already know that it would be redundant.

As for Styles, I suppose that "Style" and "ExStyle" would be more traditional.
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

26 Mar 2017, 07:07

lexikos wrote:I would never use it. I assume you already know that it would be redundant.
I've no idea.What do you mean?
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

26 Mar 2017, 07:16

v1 adds or removes WS_EX_ACCEPTFILES automatically depending on the presence or absence of a DropFiles label. It isn't done that way anymore, presumably because of the difficulty in detecting methods.
It's still working in the current test version if you set a prefix:

Code: Select all

MyGui := GuiCreate("Test", , "Gui")
MyGui.Show("w400 h400")
GuiOnDropFiles(gui, fileArray, control, x, y) {
   MsgBox(A_ThisFunc)
}
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Proposed New GUI API for AutoHotkey v2

26 Mar 2017, 07:45

@ Topic and recent updates :thumbup:
just me wrote:I've no idea.What do you mean?
Perhaps,
WinExist -Remarks wrote: If all parameters are omitted, the Last Found Window will be checked to see if it still exists.
That is,

Code: Select all

A_LastFoundWindow:=WinExist()
But I'm not sure exactly what you suggest that A_LastFoundWindow should contain.
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

26 Mar 2017, 08:04

A_LastFoundWindow should contain the HWND of the last-found window, if any. And it should be writeable, e.g.

Code: Select all

A_LastFoundWindow := Gui.Hwnd ; without the need to call WinExist() which will fail currently if the Gui isn't visible
lexikos
Posts: 9551
Joined: 30 Sep 2013, 04:07
Contact:

Re: Proposed New GUI API for AutoHotkey v2

26 Mar 2017, 21:10

just me wrote:I've no idea.What do you mean?
Well, not quite redundant due to DetectHiddenWindows (in current versions). But even if the last found window is set, it can't be used if the window is hidden and DetectHiddenWindows is Off (i.e. WinSetTitle and other the window commands will fail, except WinShow).

Code: Select all

Run notepad
WinWait Untitled - Notepad
WinSetTitle Title 1  ; Works
WinHide
WinSetTitle Title 2  ; Fails
WinShow  ; Works
Aside from that, you can already retrieve it as Helgef showed, and set it as I showed.
It's still working in the current test version if you set a prefix:
But not if you use a class. I'm a little surprised that it works with a prefix; I think it's better to either always require or never require manually adding +Drop.
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

27 Mar 2017, 02:11

lexikos wrote:But even if the last found window is set, it can't be used if the window is hidden and DetectHiddenWindows is Off ...
If used as a replacement for +LastFound it already would work:
If the last found window is a hidden Gui window, it can be used even when DetectHiddenWindows is Off.
The same behaviour could easily be added for all other windows. Your example is clearly showing the inconsistency of the current behaviour.

Alternatively you could change the behaviour if only ahk_id is specified in the WinTitle parameter. Win... commands would behave like Control commands then. But I think it would contradict the purpose of the "Last Found Window".
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Proposed New GUI API for AutoHotkey v2

27 Mar 2017, 02:25

Is there any chance that coloring controls will be integrated too? https://autohotkey.com/boards/viewtopic.php?f=6&t=2197
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
lexikos
Posts: 9551
Joined: 30 Sep 2013, 04:07
Contact:

Re: Proposed New GUI API for AutoHotkey v2

27 Mar 2017, 05:43

just me wrote:If used as a replacement for +LastFound it already would work:
That was somewhere in the back of my mind, but when I looked into the internal WinExist() function, I couldn't see it. I was looking in the wrong place.
Your example is clearly showing the inconsistency of the current behaviour.
No, it isn't. It only shows one behaviour. Someone who isn't aware of the other behaviour will never see the inconsistency. Anyway, we already knew there was inconsistency, because the documentation told us so. It said "If the window [meets a specific condition], it can [act differently to how it does in other cases]." That's inconsistency.

Scripts have much more control over their own Gui windows, and tend to use the Win commands on Gui windows for different purposes than on external windows. For instance, to "set up" a Gui window prior to showing it. I suppose it's rarer that the script author would be aware of a hidden window belonging to an external app, and actually want to interact with one.
Alternatively you could change the behaviour if only ahk_id is specified in the WinTitle parameter.
It sounds like your hypothetical suggestion is for ahk_id %hwnd% to detect hidden windows but not Foo ahk_class bar ahk_id %hwnd%. (I use the latter to confirm that a given window matches the criteria.) That kind of inconsistency would be worse. I think if you omit "only", it sounds more reasonable. (Maybe you had thought ahk_id would only ever be used on its own.)
But I think it would contradict the purpose of the "Last Found Window".
I think you mean that being required to use ahk_id in order to interact with a hidden window would defeat the purpose of the LFW (that purpose being convenience). Its other purposes can be fulfilled by ahk_id: performance (avoiding unnecessary enumeration of windows) and reliability (ensuring that commands operate on the same window even if another window matching the original criteria appears).

I think DetectHiddenWindows has two purposes:
  1. To ensure commands act on the appropriate visible window even when a hidden window matches the same criteria.
  2. To prevent commands from acting on windows which don't exist from the user's perspective.
I feel that I don't fully understand the reasons for DetectHiddenWindows or the repercussions of bypassing it by default (for ahk_id/LFW). I suppose there's one way to find out.

If DetectHiddenWindows does not affect ahk_id or LFW, I think WinExist("ahk_id " Gui.Hwnd) if exactly equivalent to Gui +LastFound and (hypothetically) A_LastFoundWindow := Gui.Hwnd, so there'd not be much reason to add the more verbose variable.
jNizM wrote:Is there any chance that coloring controls will be integrated too?
I'm not at all interested in adding features at this stage.

On the other hand, it may be worth considering what impact it would have on the existing Gui.BgColor and Gui.CtrlColor properties and control +Ccolor and +Background (for ListView/TreeView) options. Speaking of which, they're rather inconsistent. Perhaps they should be renamed, and the options implemented as properties.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Proposed New GUI API for AutoHotkey v2

27 Mar 2017, 12:09

just me wrote:A_LastFoundWindow should contain the HWND of the last-found window, if any. And it should be writeable, e.g.

Code: Select all

A_LastFoundWindow := Gui.Hwnd ; without the need to call WinExist() which will fail currently if the Gui isn't visible
If the last window found is hidden, then you had DetecthiddenWindows, On when it was found, if you want to consider hidden windows after the last found window was found don't turn it off, In case the last window wasn't hidden, but got hidden, after it was found, you still need to turn on DetectHiddenWindows if you want to use A_LastFound with the ahk functions. Now, if you want to use the last found window for something else, eg, for some DllCall(...) which doesn't care about DetectHiddenWindows, then I could see value for it.
My argument for it would be readabillity, eg,

Code: Select all

WinShow ; vs
WinShow, % "ahk_id" WinExist() ; vs
WinShow, % "ahk_id" A_LastFound ; This is clearer to me than the above, but then
WinShow ; Last found   (is clear enough.)
Cheers!
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

28 Mar 2017, 03:52

I think this 'last found' discussion is running out of scope.
Back to the roots: Re-add the +LastFound option for Guis and leave the rest as is.
AHK without quirks wouldn't be AHK anymore.

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 5 guests