Page 1 of 1

Inconsistent GuiControlGet, OutputVariable, Focus/FocusV results between in-line and button calls to the same code.

Posted: 03 Sep 2017, 07:14
by DrReflex
I RAN INTO AN ISSUE USING GuiControl, OutputVar, Focus AND GuiControl, OutputVar, FocusV AND CAN NOT FIND AN EXPLANATION FOR THE INCONSISTENT PERFORMANCE IN THE AHK DOCUMENTATION OR IN THE AHK FORUMS.

I was able to find a work around after multiple trials and multiple errors. Now I have a "fix" but I can't explain why it works or what caused me to need the work around in the first place. It appears to be due to a possible bug in how GUIs interact with Focus and therefore with FocusV. I would really like understand what is happening.

Here is the issue:
When running simple in-line code (GetPB1Data:), immediately after building a new GUI, a call to ControlFocus to change the focus to a progress bar in that GUI followed by calls to GuiControlGet, OutputVar, Focus and to GuiControlGet, OutputVar, FocusV fail to return the focus and the focus variable despite using the window handle assigned to the progress bar when it was added to the new Gui (in this case GUI1:). Calls to numerous other GuiControlGet sub-commands work fine.

When the same code B1: is called by a button push (gB1), the code works fine.

When Focus and FocusV are prefaced with GUI1: the code works fine.

The example below documents the issue. I have extracted the pertinent code, merged my in-line and debugging button called code into a single block with two labels. I have added an If statement to toggle between the two version of the code.

When the global RunWithPrefacingGUI1 is false, GUI1: is not prefaced to Focus and to FocusV and the in-line code fails while the button call to the same code works.
When the global RunWithPrefacingGUI1 is true, GUI1: is prefaced to Focus and to FocusV and both calls to the code work.

Why is this happening?

Thanks for your time and your answer (if you have one).

Code: Select all

#SingleInstance, Force
global RunWithPrefacingGUI1 := false
{
	; BUILD GUI1 USING Build_GUI1_0()
	Gui, GUI1:Add, Progress, hwndPB1HW vPB1Var    , 50
	Gui, GUI1:Add, Button,   hwndB1    vB1Var  gB1, Push to see results of GetPB1Data
	Gui, GUI1:Show, AutoSize, GUI1

	GoTo GetPB1Data
	return
}
	
B1:                ;THIS WORKS WITHOUT OR WITH THE PREFACING GUI1:
GetPB1Data:  ;THIS ONLY WORKS       WITH THE PREFACING GUI1: 
{
	ControlFocus,,ahk_id %PB1HW%
	If (RunWithPrefacingGUI1)
	{
	GuiControlGet, MyPB1F,   	GUI1:Focus       	  ;>>>>> THIS WORKS WITH GUI1: PREFACED TO Focus.  <<<<<
	GuiControlGet, MyPB1FV,  	GUI1:Focus          ;>>>>> THIS WORKS WITH GUI1: PREFACED TO FocusV. <<<<<
	}	else
	{
	GuiControlGet, MyPB1F,   	Focus       	          ;##### THIS FAILS HERE UNLESS GUI1: is prefaced to Focus.  (SEE ###### BELOW)
	GuiControlGet, MyPB1FV,  	FocusV  	          ;##### THIS FAILS HERE UNLESS GUI1: is prefaced to FocusV. (SEE ###### BELOW)
	} 
	GuiControlGet, MyPB1HW,   GUI1:Hwnd,  %PB1HW% ;GET progress bar HWND
	GuiControlGet, MyPB1Name, GUI1:Name,  %PB1HW% ;GET progress bar NAME

	;BUILD AND SHOW MyMsg
	MyMsg := Format("Focus: {} `nFocusV: {}`nHwnd: {}`nName: {}`n",MyPB1F,MyPB1FV,MyPB1HW,MyPB1Name)
	MsgBox %MyMsg%
}	
ESC::
ExitApp

Re: Inconsistent GuiControlGet, OutputVariable, Focus/FocusV results between in-line and button calls to the same code.

Posted: 06 Sep 2017, 15:55
by just me
I thought this had been answered already. :roll:
:arrow: GUI Events, Threads, and Subroutines

A GUI thread is defined as any thread launched as a result of a GUI action. GUI actions include selecting an item from a GUI window's menu bar, or triggering one of its g-labels (such as by pressing a button).

The default window name for a GUI thread is that of the window that launched the thread. Non-GUI threads use 1 as their default.
The auto-execute section is a non-GUI thread, so its default GUI is 1. Commands like

Code: Select all

Gui, GUI1:Add, Progress, hwndPB1HW vPB1Var    , 50
don't change the default GUI. You have to do it using either

Code: Select all

Gui, GUI1: , New ...
or

Code: Select all

Gui, GUI1: Default

Code: Select all

GoTo GetPB1Data
remains in the same thread, so the default GUI is still 1.

Code: Select all

B1:                ;THIS WORKS WITHOUT OR WITH THE PREFACING GUI1:
is triggered by a button event as a GUI thread, so the default GUI is set to the GUI containing the button: GUI1.

BTW:
:arrow: GuiControlGet -> ControlID

If the control is not on the default GUI, the name of the GUI must also be specified -- except on [v1.1.20+] when ControlID is a HWND, since each HWND is unique. See Remarks for details.
This doesn't belong to 'Bug Reports'!