GUI problem - one test script works Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Albireo
Posts: 1778
Joined: 16 Oct 2013, 13:53

GUI problem - one test script works

Post by Albireo » 28 May 2020, 08:19

I try to create a GUI in a function (but some code doesn't work as desired)

In this GUI I make two BIG checkboxes.
When one is checked - the other is unchecked. (like a radio button)
and at the same time the text is changed (in the same way)
This text script works (as desired)
Code without function() - Works!


When I try to put this GUI (above) - in a function() - some features stop working...
(with strategy by @just me - To use GUI in a function() - risky or easy or the original link GUI in Function)
The GUI above in a function() (doesn't work)



One way to solve this is to change all variables in the function from Static

Code: Select all

	Static	Header
			,	U1, U2, O1, O2
			,	myBigCheckBox1, myBigCheckBox2
			,	ButtOK
to Global

Code: Select all

	Global	Header
			,	U1, U2, O1, O2
			,	myBigCheckBox1, myBigCheckBox2
			,	ButtOK
But why?
Is it possible to solve another way?
BNOLI
Posts: 548
Joined: 23 Mar 2020, 03:55

Re: GUI problem - one test script works

Post by BNOLI » 28 May 2020, 08:57

Global Header
, U1, U2, O1, O2
, myBigCheckBox1, myBigCheckBox2
, ButtOK

Well, at least your butt is OK :lol:
Remember to use [code]CODE[/code]-tags for your multi-line scripts. Stay safe, stay inside, and remember washing your hands for 20 sec !
Albireo
Posts: 1778
Joined: 16 Oct 2013, 13:53

Re: GUI problem - one test script works

Post by Albireo » 28 May 2020, 09:38

When everything happens in the function()
Why do all variables have to be set Global for my GUI to work in the function()?
(Why isn't Static enough?)

Have I missed something / somewhere?
(like Gui Submit, NoHide or....)
The tooltip is show the right status on the checkboxes (but nothing happens)
teadrinker
Posts: 4412
Joined: 29 Mar 2015, 09:41
Contact:

Re: GUI problem - one test script works

Post by teadrinker » 28 May 2020, 09:50

You are just trying to use totally wrong approach. Consider my example.
Albireo
Posts: 1778
Joined: 16 Oct 2013, 13:53

Re: GUI problem - one test script works

Post by Albireo » 28 May 2020, 10:10

teadrinker wrote:
28 May 2020, 09:50
You are just trying to use totally wrong approach. Consider my example.
As I can se you have many functions() for the "same" GUI in your suggestion?

I want the following structure

Code: Select all

;initiate
	---
Res := GuiFuctTest(A,B,C)
MsgBox % res
ExitApp

GuiFuncTest(A1,B1,C1)
{	; Gui Create
		Gui Start
			---
		Gui gButtonOK
		Show
	Return % Result

	ButtOK:
		---
	Return
	
	Sub1:
		---
	Return
		
	Sub2:
		---
	Return
	
	ButtOK:
		---
	Gui Destroy
	Return
	
}
Is this impossible / difficult or ... with AHK?
(I nearly reached my wish with the suggestion from @just me)
An the test above almost work..
teadrinker
Posts: 4412
Joined: 29 Mar 2015, 09:41
Contact:

Re: GUI problem - one test script works

Post by teadrinker » 28 May 2020, 10:42

If you want to use control variables, it's impossible without declaring them as global.
just me
Posts: 9574
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GUI problem - one test script works

Post by just me » 28 May 2020, 12:51

1GuiClose isn't a GUI default label.
Albireo
Posts: 1778
Joined: 16 Oct 2013, 13:53

Re: GUI problem - one test script works

Post by Albireo » 28 May 2020, 16:28

Thanks for the answers!
teadrinker wrote:
28 May 2020, 10:42
If you want to use control variables, it's impossible without declaring them as global.
That explains the phenomenon .. (Nothing to do about it :cry: )
Summary .:
All variables used for GuiControl must be set Global, the others can be set as Static

just me wrote:
28 May 2020, 12:51
1GuiClose isn't a GUI default label.
You have right! (I like your idea for the solution with GUI in functions())
I saw (1GuiClose:) somewhere and thought I had to enter the number for each GUI-window (if there are several)
If I understood you correctly - the label GuiClose: will apply to all GUI-windows (in the Function().
Is it correct?

Assume there are multiple functions(), with some GUI-windows in each function(), in the same AHK-program.
I got a problem with the label GuiClose:. It is impossible to use GuiClose: in all functions()
From the manual Using Subroutines Within a Function
"Currently, the name of each subroutine (label) must be unique among those of the entire script."
In practice, this means that the label GuiClose: must be placed in the main program,
outside my GUI-function() (is it even possible? Call a label outside the function())
Is GuiClose: only used as a label or is it a subroutine? (Return is expected from AHK and can be used outside the function()?)

When is the label GuiClose: needed? (in my case?)
Has not been tested, but will the entire AHK program be terminated, if a GUI-window ends with the X-button at the top right? (or is it just the GUI window that closes?)
Assume that GuiClose: is not used, and the AHK-program is stopped by the X-button.
Will not all memory be released from the AHK-program in this case?

The basic question remains - is this still the best way to solve my wish?
teadrinker
Posts: 4412
Joined: 29 Mar 2015, 09:41
Contact:

Re: GUI problem - one test script works

Post by teadrinker » 28 May 2020, 18:44

If you like all-in-one without global variables, it can be done like this:

Code: Select all

hGui := CreateGui("MyGui")
Return

CreateGui(label) {
   static FirstCheckbox, SecondCheckbox, Button
   if !(label + 0) {
      Gui, New, +Label%label% +hwndhGui
      Gui, Font, s18
      Gui, Add, Checkbox, vFirstCheckbox g%A_ThisFunc%, First Choice
      Gui, Add, Checkbox, vSecondCheckbox g%A_ThisFunc% xp y+10, Second Choice
      Gui, Add, Button, vButton g%A_ThisFunc% x200 y150 w100 disabled, OK
      Gui, Show
      Return hGui
   }
   else {
      GuiControlGet, name, Name, %label%
      if (name = "FirstCheckbox") {
         GuiControl, Enable, Button
         GuiControl,, SecondCheckbox, 0
      }
      else if (name = "SecondCheckbox") {
         GuiControl, Enable, Button
         GuiControl,, FirstCheckbox, 0
      }
      else if (name = "Button") {
         Gui, Submit, NoHide
         MsgBox, First checkbox: %FirstCheckbox%`nSecond checkbox: %SecondCheckbox%
      }
   }
}

MyGuiClose() {
   ExitApp
}
Albireo wrote: will the entire AHK program be terminated, if a GUI-window ends with the X-button at the top right?
No.
Albireo
Posts: 1778
Joined: 16 Oct 2013, 13:53

Re: GUI problem - one test script works

Post by Albireo » 29 May 2020, 02:54

Thanks for your time!
The solution works - almost ...(or I don't understand how to use the solution?)
A MsgBox was inserted after the function call (to check the results from the radio buttons)
But it didn't work. (as desired). The function is exit directly (but the GUI can still be used)
The program must wait for the result from the GUI before it can continue
(But how do I do that?)

Code: Select all

hGui := CreateGui("MyGui")
MsgBox 64, Row .: %A_LineNumber%, % hGui
Return

CreateGui(label) {
...
teadrinker
Posts: 4412
Joined: 29 Mar 2015, 09:41
Contact:

Re: GUI problem - one test script works  Topic is solved

Post by teadrinker » 29 May 2020, 06:32

Try this:

Code: Select all

WinWaitClose, % "ahk_id" CreateGui(result := [])
MsgBox, % result[1]
Return

CreateGui(param) {
   static FirstCheckbox, SecondCheckbox, Button, result
   if !(param + 0) {
      result := param
      Gui, New, +hwndhGui
      Gui, Font, s18
      Gui, Add, Checkbox, vFirstCheckbox g%A_ThisFunc%, First Choice
      Gui, Add, Checkbox, vSecondCheckbox g%A_ThisFunc% xp y+10, Second Choice
      Gui, Add, Button, vButton g%A_ThisFunc% x200 y150 w100 disabled, OK
      Gui, Show
      Return hGui
   }
   else {
      GuiControlGet, name, Name, %param%
      if (name = "FirstCheckbox") {
         GuiControl, Enable, Button
         GuiControl,, SecondCheckbox, 0
      }
      else if (name = "SecondCheckbox") {
         GuiControl, Enable, Button
         GuiControl,, FirstCheckbox, 0
      }
      else if (name = "Button") {
         Gui, Submit, NoHide
         result[1] := "First checkbox: " . FirstCheckbox . "`nSecond checkbox: " . SecondCheckbox
         Gui, Destroy
      }
   }
}
Albireo
Posts: 1778
Joined: 16 Oct 2013, 13:53

Re: GUI problem - one test script works

Post by Albireo » 30 May 2020, 03:59

Thanks (for all the advice and ideas)
Have tried to convert a GUI to that structure, but it wasn't that easy.
Most of it was not a problem, but I had problems with some parts of the code
One example .:

Code: Select all

		Loop % selNames
			CountFile := A_Index
		If ( CountFile > 20 )
			CountFile = 20
		
		Gui Font, cBlack s9 Normal, Arial
		; Gui Add, ListView, x50 y245 r%CountFile% w600 grid vMyListView g%A_ThisFunc%, Filename | | Date | | Time | Size | Unit
		Gui Add, ListView, x50 y245 r20 w600 grid vMyListView g%A_ThisFunc%, Filename | | Date | | Time | Size | Unit
r20 works (r%CountFile% doesn't) - all variables must be Static or Global (in this case 30-40 variables) - and it's easy to forget.
Another example is "my own" radio button

Code: Select all

if ( name = "myBigCheckBox2" ) 
				{	GuiControl, myBigCheckBox2, % ( myBigCheckBox2 := !myBigCheckBox2 ) ? Chr(252) : ""
					Gui Font, cBlue s16 Bold, Arial
					GuiControl Font, OrtO2
					
					GuiControl, myBigCheckBox1, % ( myBigCheckBox1 := False ) ? Chr(252) : ""
					Gui Font, cBlack s16 Normal, Arial
					GuiControl Font, OrtU2
					...
(Have No idea why it doesn't work.)
It is easy it become unknown "syntax error" with the solution

But
The solution from teadrinker works (with the example file) - A nice solution (for smaller GUI with standard functions).
The upside (as I sse it)
- The GUI-function() is really standalone.
- Can completely choose whether the variables should be Static or Global
- No need to think about labels.
- Easy to move to other AHK programs.
- It was interesting to see an alternative solution, to create a GUI in a function()


The downside (as I see it)
When I have to write my own "button" or something, and want help - (for example here on the forum) I have to create the example based on the standard structure of a GUI. (Could be very many if ... else … ;) )
The solutions and help I can get, may be difficult to transform into this GUI structure.

Still haven't done a test script to find out if the jump to GuiClose: (when a GUI window closes) is a Goto or GoSub
teadrinker
Posts: 4412
Joined: 29 Mar 2015, 09:41
Contact:

Re: GUI problem - one test script works

Post by teadrinker » 30 May 2020, 07:10

Albireo wrote:

Code: Select all

		Loop % selNames
			CountFile := A_Index
		If ( CountFile > 20 )
			CountFile = 20
I can't understand what this code does. Why you need Loop? Anyway, the selNames variable must be defined, make sure of it: MsgBox, % selNames.
Albireo wrote:

Code: Select all

GuiControl, myBigCheckBox2, % ( myBigCheckBox2 := !myBigCheckBox2 ) ? Chr(252) : ""
A wrong syntax, see documents.
Albireo
Posts: 1778
Joined: 16 Oct 2013, 13:53

Re: GUI problem - one test script works

Post by Albireo » 30 May 2020, 15:48

Thanks teadrinker for your time! (I think it is not easy…)

Made another attempt with a smaller AHK script
Original ahk-GUI - (it works)



Then I tried to translate the same code to one function(). I only tried to translate the first main GUI. (but it doesn't work as desired)
Many GUI:s is created ;) (Have no idea what MyGuiClose() is.)
GUI with strategy 'teadrinker'


Wrote the same program - GUI in one function with the strategy from 'just me'.
One function from 'just me' - works


But when I tried to add the third GUI (for the Cancel button) there were problems... ( I have no idea why - maybe lost some pointer)
One function with two GUI -trategy 'just me' - crashes with the x-button
just me
Posts: 9574
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GUI problem - one test script works

Post by just me » 31 May 2020, 04:40

Albireo wrote: Then I tried to translate the same code to one function(). I only tried to translate the first main GUI. (but it doesn't work as desired)
Many GUI:s is created ;) (Have no idea what MyGuiClose() is.)
GUI with strategy 'teadrinker'
Obviously you didn't understand the concept. You removed the function's parameter which is needed when called as a control's event handler.

MyGuiClose() is the GuiClose function for one of teadrinker's examples.
just me
Posts: 9574
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: GUI problem - one test script works

Post by just me » 31 May 2020, 05:58

The last two examples are a bit strange. I didn`t expect that GuiHwnd would be accessible in the GuiClose routine of the first one, but for what reason ever it is.

In the second one

Code: Select all

		WinGetPos PosX, PosY, Width, Hight, ahk_id %GuiHwnd%	; GuiHwnd kommer från .: Gui +AlwaysOnTop hwndGuiHwnd
within the function prevents GuiHwnd from beeing 'seen' by the subroutine (might be one of the 'common sources of confusion').

But you don't need GuiHwnd in the subroutine at all, because the Gui window is set as the last-found-window.
Albireo
Posts: 1778
Joined: 16 Oct 2013, 13:53

Re: GUI problem - one test script works

Post by Albireo » 31 May 2020, 07:25

Thanks for your time!
teadrinker wrote:
30 May 2020, 07:10
Albireo wrote:

Code: Select all

		Loop % selNames
			CountFile := A_Index
		If ( CountFile > 20 )
			CountFile = 20
I can't understand what this code does. Why you need Loop? Anyway, the selNames variable must be defined, make sure of it: MsgBox, % selNames.
Do not want to display 15 empty rows if the input of files is only 5, but also want the table not to be larger than 20 rows in total. Only the size of the table changes - not the GUI window - (thats why I count the number of rows)

teadrinker wrote:
30 May 2020, 07:10
Albireo wrote:

Code: Select all

GuiControl, myBigCheckBox2, % ( myBigCheckBox2 := !myBigCheckBox2 ) ? Chr(252) : ""
A wrong syntax, see documents.
Can't see the "wrong syntax" in the code (It works in the "normal" GUI:s)
(how would you have written this code?)

just me wrote:
31 May 2020, 04:40
Albireo wrote: Then I tried to translate the same code to one function(). I only tried to translate the first main GUI. (but it doesn't work as desired)
Many GUI:s is created ;) (Have no idea what MyGuiClose() is.)
GUI with strategy 'teadrinker'
Obviously you didn't understand the concept. You removed the function's parameter which is needed when called as a control's event handler.

MyGuiClose() is the GuiClose function for one of teadrinker's examples.
Thanks! which explains when I need this function().

just me wrote:
31 May 2020, 05:58
The last two examples are a bit strange. I didn`t expect that GuiHwnd would be accessible in the GuiClose routine of the first one, but for what reason ever it is.
Thats correct! Now I save the hwnd in a variable (maybe not the best way but it works). Like this .:

Code: Select all

Gui 1: +AlwaysOnTop hwndGuiHwnd	; This option stores the window handle (HWND) of the GUI in OutputVar (GuiHwnd)
		MainGUI := GuiHwnd


just me wrote:
31 May 2020, 05:58
In the second one

Code: Select all

WinGetPos PosX, PosY, Width, Hight, ahk_id %GuiHwnd%
within the function prevents GuiHwnd from beeing 'seen' by the subroutine (might be one of the 'common sources of confusion').
But you don't need GuiHwnd in the subroutine at all, because the Gui window is set as the last-found-window.
I use WinGetPos PosX, PosY, Width, Hight, ahk_id %MainGUI% to get the size of the main GUI and place this "popup message" in the middle of the mian window. (thats why :) )

Now the code for my GUI function() seems to work again with four GUI:s. (the last major bug was that I wrote GUI Submit and not GUI Submit, NoHide :problem: )
teadrinker
Posts: 4412
Joined: 29 Mar 2015, 09:41
Contact:

Re: GUI problem - one test script works

Post by teadrinker » 31 May 2020, 11:01

Albireo wrote: Do not want to display 15 empty rows if the input of files is only 5, but also want the table not to be larger than 20 rows in total. Only the size of the table changes - not the GUI window
You've chosen a weird way to achieve that. I'd suggest just CountFile := selNames > 20 ? 20 : selNames
Albireo wrote: Can't see the "wrong syntax" in the code (It works in the "normal" GUI:s)
Since it's a Text control, you must leave the first parameter blank when changing its content:
GuiControl wrote:(Blank)
Puts new contents into the control.

Code: Select all

GuiControl,, ControlID , [Value]
Leave SubCommand blank to put new contents into the control via Value. Specifically:
...
Text/Button/GroupBox/StatusBar/Link: Specify for Value the control's new text...
Albireo
Posts: 1778
Joined: 16 Oct 2013, 13:53

Re: GUI problem - one test script works

Post by Albireo » 01 Jun 2020, 07:06

Thanks for your objections!
teadrinker wrote:
31 May 2020, 11:01
Albireo wrote: Do not want to display 15 empty rows if the input of files is only 5, but also want the table not to be larger than 20 rows in total. Only the size of the table changes - not the GUI window
You've chosen a weird way to achieve that. I'd suggest just CountFile := selNames > 20 ? 20 : selNames
A fantastic fast solution (about 2000 times faster than mine)
but - something I don't understand? - I don't get the same result (if the selNames are <20)
I got the same result as … ListView, x50 y245 r20 ... (instead of … ListView, x50 y245 r%CountFile% ... )

teadrinker wrote:
31 May 2020, 11:01
Albireo wrote: Can't see the "wrong syntax" in the code (It works in the "normal" GUI:s)
Since it's a Text control, you must leave the first parameter blank when changing its content:
GuiControl wrote:(Blank)
Puts new contents into the control.

Code: Select all

GuiControl,, ControlID , [Value]
Leave SubCommand blank to put new contents into the control via Value. Specifically:
...
Text/Button/GroupBox/StatusBar/Link: Specify for Value the control's new text...
Again something I do not understand!
is this code below some "Text/Button/GroupBox/StatusBar/Link"

Code: Select all

	Gui 1: Font, cBlue s25, Wingdings
	Gui 1: Add, Text, x50 y80 w25 h25 0x6 vU1
	Gui 1: Add, Text, xp yp w25 h25 0x12
	Gui 1: Add, Text, xp yp w25 h25 0x200 center BackgroundTrans vmyBigCheckBox1 gBigCheckBox1
I see it as graphics or possibly single characters (but not as empty strings). myBigCheckBox1 is used as a variable (and a ControlID) to place the character ü on desired place. Then a mouseclick can toggle a character visible or none (true or false) but it isn't a CheckBox
I don't know how to write this, to get the "right" structure. Right now it works. (as wished)
Is there any other way to get big radio buttons? (Do you have any idea).

Tested if Owner of a GUI window could place second GUI in the middle of first GUI (but it does not).

Code: Select all

	WinGetPos PosX, PosY, Width, Hight, ahk_id %GuiHwnd%
	Gu1w = 200
	Gu1h = 200
	PosX := Round(((Width / 2) - (Gu1w / 2)) + PosX, 0)
	PosY := Round(((Hight / 2) - (Gu1h / 2)) + PosY, 0)
It's probably just to keep calculating the position of the other GUI :)
However, there are other benefits to using +Owner
teadrinker
Posts: 4412
Joined: 29 Mar 2015, 09:41
Contact:

Re: GUI problem - one test script works

Post by teadrinker » 01 Jun 2020, 09:20

Albireo wrote: I got the same result as … ListView, x50 y245 r20 ... (instead of … ListView, x50 y245 r%CountFile% ... )
The following example demonstrates, that my code works properly:

Code: Select all

Gui, Add, ListView, r20

selNames := 10
CountFile := selNames > 20 ? 20 : selNames
Gui, Add, ListView, r%CountFile%

Gui, Show
Albireo wrote: I don't know how to write this, to get the "right" structure.
Perhaps like this:

Code: Select all

WinWaitClose, % "ahk_id" CreateGui(result := [])
MsgBox, % result[1]

CreateGui(param) {
   static FirstCheckbox, FirstText, SecondCheckbox, SecondText, Button, result
   if !(param + 0) {
      result := param
      Gui, New, +hwndhGui
      Gui, Font, s12
      
      Gui, Add, Text, x20 y20 w22 h22 7
      Gui, Add, Text, BackgroundTrans xp+1 yp+1 wp-2 hp-2 center vFirstCheckbox g%A_ThisFunc%
      Gui, Add, Text, x+10 yp vFirstText, First Choice
      
      Gui, Add, Text, x20 y+10 w22 h22 7
      Gui, Add, Text, BackgroundTrans xp+1 yp+1 wp-2 hp-2 center vSecondCheckbox g%A_ThisFunc%
      Gui, Add, Text, x+10 yp vSecondText, Second Choice
      
      Gui, Add, Button, xp+100 y+20 w100 h28 Disabled vButton g%A_ThisFunc%, OK
      Gui, Show
      Return hGui
   }
   else {
      GuiControlGet, name, Name, %param%
      if (name = "FirstCheckbox") {
         GuiControl, Enable, Button
         GuiControl,, FirstCheckbox, ✓
         GuiControl,, SecondCheckbox
         Gui, Font, cBlue
         GuiControl, Font, FirstText
         Gui, Font, cDefault
         GuiControl, Font, SecondText
      }
      if (name = "SecondCheckbox") {
         GuiControl, Enable, Button
         GuiControl,, SecondCheckbox, ✓
         GuiControl,, FirstCheckbox
         Gui, Font, cBlue
         GuiControl, Font, SecondText
         Gui, Font, cDefault
         GuiControl, Font, FirstText
      }
      if (name = "Button") {
         GuiControlGet, FirstCheckbox
         GuiControlGet, SecondCheckbox
         Gui, Destroy
         result[1] := FirstCheckbox ? "First" : "Second"
      }
   }
}
Or, for short

Code: Select all

WinWaitClose, % "ahk_id" CreateGui(result := [])
MsgBox, % result[1]

CreateGui(param) {
   static
   if !(param + 0) {
      result := param
      Gui, New, +hwndhGui
      Gui, Font, s12
      
      for k, v in ["First", "Second"] {
         Gui, Add, Text, % "x20 w22 h22 7 y" . (k = 1 ? "20" : "+10")
         Gui, Add, Text, BackgroundTrans xp+1 yp+1 wp-2 hp-2 center v%v%Checkbox g%A_ThisFunc%
         Gui, Add, Text, x+10 yp v%v%Text, %v% Choice
      }
      Gui, Add, Button, xp+100 y+20 w100 h28 Disabled vButton g%A_ThisFunc%, OK
      Gui, Show
      Return hGui
   }
   else {
      GuiControlGet, name, Name, %param%
      for k, v in ["First", "Second"] {
         if (name = v . "Checkbox") {
            GuiControl, Enable, Button
            GuiControl,, %v%Checkbox, ✓
            opposite := ["First", "Second"][!(k - 1) + 1]
            GuiControl,, %opposite%Checkbox
            Gui, Font, cBlue
            GuiControl, Font, %v%Text
            Gui, Font, cDefault
            GuiControl, Font, %opposite%Text
         }
      }
      if (name = "Button") {
         GuiControlGet, FirstCheckbox
         GuiControlGet, SecondCheckbox
         Gui, Destroy
         result[1] := FirstCheckbox ? "First" : "Second"
      }
   }
}
Post Reply

Return to “Ask for Help (v1)”