Proposed New GUI API for AutoHotkey v2

Discuss the future of the AutoHotkey language
just me
Posts: 6486
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

28 Mar 2017, 04:04

I converted the TreeView example from the help file and added some parts of the ListView example. All is working fine as yet, but the 'splash window' is flashing. Why?

Edit:
Removed code, new version.
Last edited by just me on 06 Apr 2017, 02:59, edited 1 time in total.
Reason: Updated code version.
lexikos
Posts: 6609
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Proposed New GUI API for AutoHotkey v2

28 Mar 2017, 04:12

just me wrote: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.
Agreed; I think my initial "but why?" reaction was right. I suppose there isn't any particular reason to remove it.
lexikos
Posts: 6609
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Proposed New GUI API for AutoHotkey v2

28 Mar 2017, 04:15

just me wrote:... the 'splash window' is flashing.
I don't see any flashing.
just me
Posts: 6486
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

28 Mar 2017, 04:28

Strange, it always does here. Maybe it's caused by my grafic hardware.
lexikos
Posts: 6609
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Proposed New GUI API for AutoHotkey v2

31 Mar 2017, 20:05

fincs wrote:How about the default prefix being On for event sink objects, and Gui for regular functions?
Is there any particular reason to use the prefix "On" at all? If one wants to move one's event handlers from global scope (functions) to a class (methods), why should the prefix change from "Gui" to "On"? If the prefix is the same, I think it would be sufficient to enclose the functions in a class and pass the class/object to GuiCreate(), without any changes to the functions/methods.
Changing each control type's event handler argument list to be more natural as you suggested would make a lot of sense,
On the other hand, the "event type, parameters" pattern is easy to remember. Although the event name isn't always useful, that's also true for the Gui and/or Ctrl parameters which are always present at the start of the list. I reviewed all of the control events and I think the Link control is the only one that I would change. The current order is dictated by A_EventInfo being purely numeric while ErrorLevel can be a string. I think (Event, ID, Index, HREF) would be reasonable: all information is always available, the ID is probably most useful for the event handler, the index can be useful, and the HREF is only present if it failed to execute (since the handler isn't called on success).

I'm leaning toward replacing Gui.OnEvent := x and Ctrl.Event := x with .OnEvent(EventName, x, reg) where reg would possibly behave identically to OnMessage's MaxThreads parameter or OnExit's AddRemove parameter.

I'm not sure about the event parameters. In a script which registers one handler for each event, it makes sense to just receive the event parameters; the event name is useless. On the other hand, it can still be useful to register one handler for multiple events, and it would be inconvenient to have to bind a function/method to the event name before registering each event. OnMessage puts the MsgNumber parameter (and target HWND parameter) after the message's parameters, but there's always two parameters (wParam and lParam; though some messages don't use them). Gui and control events have a varying number of parameters.

I would want to support the automatic event handlers for Gui and the g-function/method option because they are convenient, but on the other hand it introduces complications where they overlap with functions/methods registered by .OnEvent(). -g is useful for suppressing events, but would logically only affect +gXXX, not OnEvent(), so some other form of suppressing events might be better. I think some controls fire the event when their value is changed by the script, and some don't; probably none should.
Actually, I am not sure whether automatic button event handlers are a good idea.
I still don't think they are confusing or in any way bad, but I don't think they really offer much. If they're removed, it would mean a tiny reduction in code size, and one less thing to document, or read about and remember. It's easy to add gButtonWhatever when converting scripts.
User avatar
joedf
Posts: 7250
Joined: 29 Sep 2013, 17:08
Facebook: J0EDF
Google: +joedf
GitHub: joedf
Location: Canada
Contact:

Re: Proposed New GUI API for AutoHotkey v2

01 Apr 2017, 09:12

just me wrote:[...]
AHK without quirks wouldn't be AHK anymore.
LOL :lol:
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500 @ 4.00 GHz, 2x8GB DDR4 3143 MHz, NVIDIA GTX 1060 6GB | [About Me] | [ASPDM - StdLib Distribution]
[Populate the AHK MiniCity!] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library] | [About the AHK Foundation]
just me
Posts: 6486
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

05 Apr 2017, 02:08

Any decisions related to the discussed changes?
lexikos
Posts: 6609
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Proposed New GUI API for AutoHotkey v2

05 Apr 2017, 03:48

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

AutoHotkey_2.0-a078-31+g4fb1ab7.zip
Fixed order of parameters for Custom control 'N' event.
Changed Ctrl.Opt +Background to override Gui.CtrlColor.
Changed +Drop to +DropFiles.
Restored Gui option +LastFound.
Removed +OwnDialogs as default for new threads.
Removed Title parameter of Gui.Show().
Renamed Label control back to Text.
Changed event handler prefixes to be more v1-like.
  • - Remove "On"
    - Default prefix to "Gui"
    - Enable handler functions by default unless prefix is ""
    - Use prefix even with method names
    - Do not use prefix with controls
Added +Prefix option to set Gui event prefix (like v1 +Label).
Changed Gui.Submit() to ignore controls which don't accept input.
Added Gui.Pos and Gui.ClientPos and removed GuiControl.Position alias.


Event handling: I chose to start with the easier/more obvious changes. I will continue to consider OnEvent() or similar, which would supersede the Event/OnX properties.


Control colors:

After jNizM brought it up and I thought about it a bit, I figured that changing the current implementation to allow per-control colors would be simple. It wasn't really, but that's mostly because I kept getting caught up on minor details and refactoring.

Old:

ListView/TreeView/StatusBar/Progress supported individual background colors. +Background could be followed by a color, so +BackgroundDefault was equivalent to -Background. +Background on its own was interpreted as +Background0 (because it was assumed to always be followed by a color).

Some other controls supported background colors only via Gui,Color. -Background overrode Gui,Color to use the default system colors, and +Background reverted it to using Gui,Color (and also reverted +BackgroundTrans). Any suffix other than "Trans" was ignored.

New:

Now both sets of controls support +Background%Color%, so +BackgroundDefault is equivalent to -Background. +Background reverts -Background (but I think there may be a redraw bug). There is still some inconsistency in that Gui,Color does not affect ListView/TreeView/StatusBar/Progress after they are created.

If +BackgroundTrans or +Background%Color% is used on a control type which does not support it, an error is shown. At some point the (v1/v2) documentation should be clarified to show which control types support each option.

If +Background%Color% is applied to a DDL, the theme is removed to let it work. It also respects Gui.CtrlColor, but only if the theme is removed explicitly (or not present). The color only applies to the part of the control on the GUI, not the drop-down window.

ComboBox now respects Gui.CtrlColor and allows +Background%Color%, but if the control is themed (on Windows 10) there is a bit of white border around the colored part. Again, the drop-down window is not affected.

+Background%Color% can be applied to a Button. Although the main surface of a button can't be colored this way (WM_CTLCOLORBTN), I've found that it affects the color of the 1 pixel border which appears around themed buttons on Windows 10 (and possibly others). It can be used to give buttons emphasis, or to let them fit in better (normally the border is white). (The cost is merely one extra case WM_CTLCOLORBTN:.)


[Update: CtrlColor was removed.] I am considering removing Gui.CtrlColor, because:
  • It is now redundant.
  • It does not apply to all controls. In the unlikely event that support is extended to more control types, doing so would effectively change the behaviour of scripts which use Gui.CtrlColor. By contrast, scripts won't use +Background%Color% on a control which doesn't support it, because they would get an error.
  • It is handled inconsistently. Existing ListView/TreeView/StatusBar/Progress are not affected by changes to Gui.CtrlColor. Controls which use WM_CTLCOLOR' are.
just me wrote:Any decisions related to the discussed changes?
Some (above). I haven't thought about or worked on it since the weekend.
just me
Posts: 6486
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

05 Apr 2017, 04:05

Great news (much more than I was hoping)! Thanks!!!
just me
Posts: 6486
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

06 Apr 2017, 02:56

I revised my TreeView/ListView/StatusBar example. It's a real pleasure to have this new interface.

Code: Select all

; The following is a working script that creates and displays a TreeView containing all folders in the all-users Start Menu.
; When the user selects a folder, its contents are shown in a ListView to the right (like Windows Explorer).
; In addition, a StatusBar control shows information about the currently selected folder.

; Super-global Gui/Control objects:
Global MainGui
Global MainTV
Global MainLV
Global MainSB
; Super-global to hold the path currently selected in the TreeView:
Global SelectedFolderPath := ""
; Create a popup menu to be used as the context menu:
Menu, ContextMenu, Add, Properties, ContextProperties
; The following folder will be the root folder for the TreeView. Note that loading might take a long
; time if an entire drive such as C:\ is specified:
TreeRoot := A_StartMenu
TreeViewWidth := 280
ListViewWidth := 420
; Create an ImageList and put some standard system icons into it. Only icon 4 (folder icon) will be used in the TreeView:
ImageListID := IL_Create(5)
Loop 5
   IL_Add(ImageListID, "Shell32.dll", A_Index)
; Create the main Gui, allow the user to maximize or drag-resize the window. Passing an object as event handler
; will keep all event handlers related to this Gui in that object:
MainGui := GuiCreate("ListView, TreeView, and StatusBar Example", "+Resize +MinSize", MainGuiEvents)
; Create a TreeView and a ListView side-by-side to behave like Windows Explorer:
MainTV := MainGui.AddTreeView("", "w%TreeViewWidth% r20 -Lines ImageList%ImageListID%")
MainTV.Name := "DirTreeView"
MainTV.Event := "DirTreeViewEvents"
MainLV := MainGui.AddListView("Name|Modified", "hp w%ListViewWidth% x+1 AltSubmit")
MainLV.Name := "FileListView"
MainLV.Event := "FileListViewEvents"
; Set the ListView's column widths (this is optional):
Col2Width := 70  ; Narrow to reveal only the YYYYMMDD part.
MainLV.ModifyCol(1, ListViewWidth - Col2Width - 30)  ; Allows room for vertical scrollbar.
MainLV.ModifyCol(2, Col2Width)
; Create a small-icon image list and assign it to the ListView; will be filled later.
HIL := IL_Create(100, 100)
MainLV.SetImageList(HIL)
; Create a Status Bar to give info about the number of files and their total size:
MainSB := MainGui.AddStatusBar()
MainSB.SetParts(60, 85)  ; Create three parts in the bar (the third part fills all the remaining width).
; Add folders and their subfolders to the tree. Display the status in case loading takes a long time:
Start := A_TickCount
SplashText("Loading the Tree ...", , "BCBlack FCWhite FS24 MX50 MY30")
AddSubFoldersToTree(MainTV, TreeRoot)
; Keep the splash window open for at least on second:
Duration := A_TickCount - Start
If (Duration < 1000)
   Sleep(1000 - Duration)
SplashText("")
; Display the window and return. The OS will notify the script whenever the user performs an eligible action:
MainGui.Show()
Return
; ==================================================================================================================================
; MainGui event handler
; ==================================================================================================================================
Class MainGuiEvents {
   ; ===============================================================================================================================
   ; Gui events
   ; ===============================================================================================================================
   GuiSize(Gui, EventInfo, Width, Height) ; Expand or shrink the TreeView and ListView in response to user's resizing of window.
   {
      If (EventInfo = 1)  ; The window has been minimized.  No action needed.
         Return
      ; Otherwise, the window has been resized or maximized. Resize the controls to match.
      MainTV.Move("h" . (Height - MainTV.Pos.Y - Gui.MarginY - MainSB.Pos.H))
      MainLV.Move("w" . (Width - MainLV.Pos.X - Gui.MarginX) . " h" . (Height - MainLV.Pos.Y - Gui.MarginY - MainSB.Pos.H))
   }
   ; -------------------------------------------------------------------------------------------------------------------------------
   GuiContextMenu(Gui, Ctrl, EventInfo, Right, X, Y) ; Launched in response to a right-click or press of the Apps key.
   {
      If !(Ctrl) || (Ctrl.Hwnd <> MainLV.Hwnd) || !(EventInfo) ; Display the menu only for clicks inside the ListView.
         Return
      ; Show the menu at the provided coordinates, A_GuiX and A_GuiY.  These should be used
      ; because they provide correct coordinates even if the user pressed the Apps key:
      Menu("ContextMenu", "Show", X, Y)
   }
   ; ===============================================================================================================================
   ; TreeView events
   ; ===============================================================================================================================
   DirTreeViewEvents(Ctrl, Event, EventInfo) ; This method handles user actions (such as clicking).
   {
      If (Event == "S") ; i.e. "select new tree item", all other events are ignored.
      {
         ; Otherwise, populate the ListView with the contents of the selected folder.
         ; First determine the full path of the selected folder:
         SelectedFolderPath := Ctrl.GetText(EventInfo)
         ParentID := EventInfo
         While (ParentID := Ctrl.GetParent(ParentID))   ; Build the full path to the selected folder.
            SelectedFolderPath := Ctrl.GetText(ParentID) . "\" . SelectedFolderPath
         ; Put the files into the ListView:
         ShowFilesInListView(SelectedFolderPath)
      }
   }
   ; ===============================================================================================================================
   ; ListView events
   ; ===============================================================================================================================
   FileListViewEvents(Ctrl, Event, EventInfo, ErrLevel := "") ; This method handles user actions (such as clicking).
   {
      If (Event == "A") ; i.e. "a row has been activated", all other events are ignored.
      {
         ; For simplicitly, we just call ContextProperties() here:
         ContextProperties("Properties")
      }
   }
}
; ==================================================================================================================================
; Context menu functions
; ==================================================================================================================================
ContextProperties(ItemName)
{
   ; The menu contains only one item, so we don't have to check ItemName here.
   ; For simplicitly, operate upon only the focused row rather than all selected rows:
   If !(FocusedRowNumber := MainLV.GetNext(0, "F"))  ; Find the focused row.
      Return  ; No row is focused.
   FileName := MainLV.GetText(FocusedRowNumber)
   Run Properties "%SelectedFolderPath%\%FileName%", , UseErrorLevel
   If ErrorLevel
      MsgBox("Could not perform requested action on %FileDir%\%FileName%")
}
; ==================================================================================================================================
; Other functions
; ==================================================================================================================================
AddSubFoldersToTree(TV, Folder, ParentItemID := 0)
{
   ; This function adds to the TreeView all subfolders in the specified folder.
   ; It also calls itself recursively to gather nested folders to any depth.
   If (ParentItemID = 0)
      ParentItemID := TV.Add(Folder, 0, "Expand Icon4")
   Loop Files, %Folder%\*.*, D  ; Retrieve all of Folder's sub-folders.
      AddSubFoldersToTree(TV, A_LoopFileFullPath, TV.Add(A_LoopFileName, ParentItemID, "Icon4"))
}
; ----------------------------------------------------------------------------------------------------------------------------------
ShowFilesInListView(Folder)
{
   ; Put the files contained in this folder into the ListView:
   MainLV.Delete()  ; Clear all rows.
   MainLV.Options("-Redraw") ; Improve performance by disabling redrawing during load.
   FileCount := 0  ; Init prior to loop below.
   TotalSize := 0
   Loop Files, %Folder%\*.*  ; For simplicity, this omits folders so that only files are shown in the ListView.
   {
      IconNumber := GetFileExtIcon(A_LoopFileExt)
      MainLV.Add("Icon%IconNumber%", A_LoopFileName, A_LoopFileTimeModified)
      FileCount += 1
      TotalSize += A_LoopFileSize
   }
   MainLV.Options("+Redraw")
   ; Update the three parts of the status bar to show info about the currently selected folder:
   MainSB.SetText(FileCount . " files", 1)
   MainSB.SetText(Round(TotalSize / 1024, 1) . " KB", 2)
   MainSB.SetText(SelectedFullPath, 3)
}
; ----------------------------------------------------------------------------------------------------------------------------------
GetFileExtIcon(FileExt)
{
   ; Gets the small icon associated with this file extension:
   Static IconArray := []
   If !(IconNumber := IconArray[FileExt])
   {
      ; Get the ListView's small-icon image list (LVSIL_SMALL = 1).
      HIL := DllCall("SendMessage", "Ptr", MainLV.Hwnd, "UInt", 0x1002, "Ptr", 1, "Ptr", 0, "UPtr") ; LVM_GETIMAGELIST
      ; Calculate buffer size required for SHFILEINFO structure.
      SFI_Size := A_PtrSize + 688
      VarSetCapacity(SFI, SFI_Size)
      File := FileExt ? ".%FileExt%" : ".*"
      ; Get the high-quality small icon associated with this file extension.
      ; 0x80 is FILE_ATTRIBUTE_NORMAL, 0x0111 is SHGFI_SMALLICON + SHGFI_USEFILEATTRIBUTES + SHGFI_ICON
      If !DllCall("Shell32.dll\SHGetFileInfoW", "Str", File, "UInt", 0x80, "Ptr", &SFI, "UInt", SFI_Size, "UInt", 0x0111)
         IconNumber := 9999999  ; Set it out of bounds to display a blank icon.
      Else
      {
         ; Extract the hIcon member from the structure:
         HICON := NumGet(SFI, 0, "UPtr")
         ; Add the HICON to the image list.
         IconNumber := IL_Add(HIL, "HICON:%HICON%")
         IconArray[FileExt] := IconNumber
      }
   }
   Return IconNumber
}
; ==================================================================================================================================
; Simple SplashTextOn/Off (v1) replacement for AHK v2 (with some additions).
; Parameters:
;     Text     -  The text of the window. If empty (blank) the splash window will be destroyed.
;     Title    -  The title of the window.
;                 Default: Empty (blank) - no title bar
;     Options  -  A string of zero or more of the following options separated by at least one space or tab:
;                 BC    -  Background color name or RGB value.
;                          Default: "Default"
;                 FC    -  Font color name or RGB value.
;                          Default: "Default"
;                 FS    -  Font size in points (decimal).
;                          Default: 10
;                 MX    -  Gui.MarginX in pixels.
;                          Default: Same as font size.
;                 MY    -  Gui.MarginY in pixels.
;                          Default: Same as font size.
;                 W     -  Width of the client area in pixels. If specified, X-margins (MX) are set to zero.
;                          Default: The width is determined by the width of the text plus x-margins.
;                 H     -  Height of the client area in pixels. If specified, Y-margins (MY) are set to zero.
;                          Default: The height is determined by the height of the text plus y-margins.
; ==================================================================================================================================
SplashText(Text, Title := "", Options := "") {
   Static DefaultOpts := {BC: "Default", FC: "Default", FS: "10", MX: "", MY: "", W: "", H: ""}
   Static SplashTextGui := ""
   Opts := New DefaultOpts
   For Each, Opt In StrSplit(RegExReplace(Options, "\s+", " "), " ")
      If DefaultOpts.HasKey(K := SubStr(Opt, 1, 2))
         Opts[K] := SubStr(Opt, 3)
      Else If DefaultOpts.HasKey(K := SubStr(Opt, 1, 1))
         Opts[K] := Opt
   If (Text <> "") {
      If (SplashTextGui)
         SplashTextGui.Destroy()
      SplashTextGui := GuiCreate(Title, "-SysMenu +AlwaysOnTop +Disabled +Owner%A_ScriptHwnd%" . (Title = "" ? " -Caption" : ""))
      SplashTextGui.SetFont("C%Opts.FC% S%Opts.FS%", "MS Shell Dlg 2")
      SplashTextGui.BgColor := Opts.BC
      SplashTextGui.MarginX := Opts.W = "" ? (Opts.MX = "" ? Opts.FS : Opts.MX) : 0
      SplashTextGui.MarginY := Opts.H = "" ? (Opts.MY = "" ? Opts.FS : Opts.MY) : 0
      SplashTextGui.AddText(Text, "xm %Opts.W% Center")
      SplashTextGui.Show("%Opts.W% %Opts.H% NA")
      Return True
   }
   Else {
      If (SplashTextGui)
         SplashTextGui.Destroy()
      SplashTextGui := ""
      Return True
   }
   Return False
}
just me
Posts: 6486
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

06 Apr 2017, 11:17

Code: Select all

MsgBox(Type(Gui1), "Type of Gui object")     ; -> GuiType
MsgBox(Type(Ctl1), "Type of control object") ; -> struct GuiControlType
Is it intended?
lexikos
Posts: 6609
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Proposed New GUI API for AutoHotkey v2

06 Apr 2017, 16:15

No.
User avatar
joedf
Posts: 7250
Joined: 29 Sep 2013, 17:08
Facebook: J0EDF
Google: +joedf
GitHub: joedf
Location: Canada
Contact:

Re: Proposed New GUI API for AutoHotkey v2

06 Apr 2017, 22:55

"a man of few words" isn't the right description.
I'd say "the man of fewest words". ;) :hehe:
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500 @ 4.00 GHz, 2x8GB DDR4 3143 MHz, NVIDIA GTX 1060 6GB | [About Me] | [ASPDM - StdLib Distribution]
[Populate the AHK MiniCity!] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library] | [About the AHK Foundation]
User avatar
Ragnar
Posts: 259
Joined: 30 Sep 2013, 15:25

Re: Proposed New GUI API for AutoHotkey v2

07 Apr 2017, 07:05

It seems like there's a new bug, referring to "Changed event handler prefixes to be more v1-like."

In the following example, since Gui.OnClose wants a function with Gui prefix, it's unable to call the automatic label of the OK button (which only works without the Gui prefix):

Code: Select all

; Example: A simple input-box that asks for first name and last name:

Gui := GuiCreate("Simple Input Example")
Gui.Add("Text", "First name:")
Gui.Add("Text", "Last name:")
Gui.Add("Edit",, "vFirstName ym")  ; The ym option starts a new column of controls.
Gui.Add("Edit",, "vLastName")
Gui.Add("Button", "OK", "default")  ; The function ButtonOK (if it exists) will be run when the button is pressed.

Gui.OnClose := "ButtonOK"  ; Tell the GUI to call ButtonOK when closing it.

Gui.Show()

ButtonOK()
{
  global Gui  ; Important to get access to the Gui object.
  Saved := Gui.Submit()  ; Save the user input to each control's associated name.
  MsgBox You entered "%Saved.FirstName% %Saved.LastName%".
}
I assume, the automatic label should works only if the Gui prefix is present.
just me
Posts: 6486
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

07 Apr 2017, 07:48

lexikos wrote:Changed event handler prefixes to be more v1-like.
...
- Default prefix to "Gui"
- Enable handler functions by default unless prefix is ""
...

Code: Select all

Gui := GuiCreate("Simple Input Example", , "")
seems to be working as you want.
just me
Posts: 6486
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

07 Apr 2017, 09:10

fincs wrote:

Code: Select all

gui.Submit([Hide := false])
  Returns an associative array containing the values of all the controls that have been explicitly named.
  Similar to v1 Gui, Submit
Default Hide := false looks like NoHide. The current test built seems to use the default Hide := True.
User avatar
Ragnar
Posts: 259
Joined: 30 Sep 2013, 15:25

Re: Proposed New GUI API for AutoHotkey v2

07 Apr 2017, 09:26

just me wrote:seems to be working as you want.
Yes, thanks it works, but it does not change the fact that's something strange here (or my mind tricks me once again). Based on the example:

Code: Select all

Gui2 := GuiCreate(,, "foo")
Gui2.Add("Button", "OK")

Gui := GuiCreate(,, "bar")
Gui.Add("Button", "OK")

; Gui.OnClose := "ButtonOK"

Gui.Show("w200")
Gui2.Show("w200")

ButtonOK()
{
    MsgBox
}
I notice two things:
  1. Regardless of which prefix is specified in the GuiCreate's last parameter, the automatic label ButtonOK is always called. There's no way to separate multiple buttons with the same name when using automatic labels only. Specifying fooButtonOK causes the button(s) to do nothing. The same applies to barButtonOK. AHK v1 has an easy solution for this: For GUI windows other than the first, you can add the window's number or name in front of the button's automatic label. I assumed, since the prefix functionality is retained, this would work in AHK v2 too.
  2. In conjunction with automatic labels, Gui.OnClose works only if it assigns the automatic label without prefix (Gui.OnClose := "ButtonOK") and if the function definition is barButtonOK() {...}. In combination with the above point, a conflict.
As a side note, something like Gui.OnEscape := "ExitApp" or Gui.OnEscape := "MsgBox" (calling built-in AHK commands/functions directly) doesn't work either anymore, because of this prefix requirement.
Last edited by Ragnar on 07 Apr 2017, 10:00, edited 1 time in total.
just me
Posts: 6486
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

07 Apr 2017, 09:52

Confirmed! I never used this 'automatic button labels' and won't miss them.
lexikos wrote:I would want to support the automatic event handlers for Gui and the g-function/method option because they are convenient, but on the other hand it introduces complications where they overlap with functions/methods registered by .OnEvent(). -g is useful for suppressing events, but would logically only affect +gXXX, not OnEvent(), so some other form of suppressing events might be better. I think some controls fire the event when their value is changed by the script, and some don't; probably none should.
Actually, I am not sure whether automatic button event handlers are a good idea.
I still don't think they are confusing or in any way bad, but I don't think they really offer much. If they're removed, it would mean a tiny reduction in code size, and one less thing to document, or read about and remember. It's easy to add gButtonWhatever when converting scripts.
just me
Posts: 6486
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Proposed New GUI API for AutoHotkey v2

07 Apr 2017, 10:19

After some more thoughts: It behaves exactly like v1.1 using 'nameless' GUIs.

Code: Select all

Gui, New
Gui, Add, Button, w200, OK
Gui, Show, , Gui1
Gui, New
Gui, Add, Button, w200, OK
Gui, Show, , Gui2
Return
GuiClose:
ExitApp

ButtonOK:
MsgBox, Bingo!
Return
My conclusion: If 'automatic labels' will stay supported and a prefix has been defined for a GUI, the prefix should be used for all 'automatic labels' including button labels.
lexikos
Posts: 6609
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Proposed New GUI API for AutoHotkey v2

07 Apr 2017, 17:21

As just me hinted, automatic button labels never used the Gui prefix (+label), only the Gui name or number (if > 1). Guis have no name or number in v2 (unless you count the HWND, which v1 did not use in this manner).
Ragnar wrote:As a side note, something like Gui.OnEscape := "ExitApp" or Gui.OnEscape := "MsgBox" (calling built-in AHK commands/functions directly) doesn't work either anymore
Something like that does work. Just pass Func("ExitApp"). But this is rarely useful (or at least, its a bit of a kludge), because the events always pass additional parameters that are not meaningful for built-in functions. Even MsgBox, since the first parameter of a Gui event is always an object.

I'm not really sure whether it should accept a suffix (overriding the default suffix) or an entire string (overriding the prefix and default suffix). It's not a function, after all, but a string. I don't really intend to keep these OnEvent properties anyway (as per my previous comments on event handlers).

Return to “AutoHotkey v2 Development”

Who is online

Users browsing this forum: No registered users and 7 guests