Undocumented behaviour of Edit control's gLabel

Report problems with documented functionality
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: Undocumented behaviour of Edit control's gLabel

28 Sep 2017, 21:08

Thanks, looks like the surefire way is to use +/-g in combination with sleep -1. edit: on second thought, sleep -1 is no good for me because my gEdit's need to be Critical, and sleep -1 forces an interruption.

But there is still another gotcha: inside the gEdit, when checking to see if the user entered a legal character/string, and if not, then correcting and updating the control to a legal value. Updating the control within its own glabel will then trigger itself again, and cannot be avoided with Critical since WM threads override Critical. edit: on further testing that doesn't seem to be the case, which in this case is bad because it means no amount of sleep can wait long enough for the WM to arrive. In that case I thought to do +/-g trick, however I'm not sure what happens when you turn off a glabel from within a glabel - whether ahk would allow the glabel to complete first or not.
Last edited by pneumatic on 30 Sep 2017, 02:33, edited 1 time in total.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Undocumented behaviour of Edit control's gLabel

29 Sep 2017, 00:48

In that case I thought to do +/-g trick, however I'm not sure what happens when you turn off a glabel from within a glabel - whether ahk would allow the glabel to complete first or not.
It is not a trick, it is (part of) the commands intended usage. The routine will not stop when you turn off the association between it and the control.
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: Undocumented behaviour of Edit control's gLabel

30 Sep 2017, 02:26

There is no reason why +g should work but the other method doesn't. Because, there is such a long delay before the WM arrives, +g should be occurring WELL BEFORE the WM arrives.

So what does this mean to the end user. It means if you want to stop the glabel from firing automatically, and your glabel must not be interrupted (i.e Critical), then the ONLY option available is to use this -g/+g trick , without knowing any reason why it actually works. And that to me is not confidence inspiring. Perhaps on a different version of windows, EN_CHANGE occurs more quickly or more slowly, and my program is broken on that machine.

If someone with intimate knowledge of the source code could explain why the +g works, given how long WM takes to arrive, that would be much appreciated. I suspect maybe +g takes itself a long time to associate the gsub with the control, perhaps longer than the EN_CHANGE is arriving. Or maybe a gsub has its own unique ID or something that gets changed on -g/+g , which stops the WM from being associated with that gsub. If it was the latter, that would give me peace of mind and I could sleep at night :|
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Undocumented behaviour of Edit control's gLabel

30 Sep 2017, 03:45

It seems like you don't understand the reason why something is happen and claim that something else is more logical, while being completely unwilling to learn by yourself.
Please look into these topics by yourself before jumping to conclusions.
Recommends AHK Studio
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: Undocumented behaviour of Edit control's gLabel

30 Sep 2017, 07:03

When I said "there is no reason why..." I just meant to say that it doesn't make sense given how WM arrives much later. I wasn't claiming to know the reason why it happens, in fact I asked for an expert to explain it. So I am still the dumb noob, don't worry about that :lol: but I hate to use something that "just works" without knowing the reason why.
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Undocumented behaviour of Edit control's gLabel

01 Oct 2017, 05:36

It will actually need an expert to ensure that the -g/+g method will work reliable in every case, because AHK's message processing is actually complicated stuff. All I can say is:
  • The GuiControl command actually updates the related control attributes immediately.
  • If an event triggering message is processsed while the control is missing a g-label, it will be 'ignored'.
Speaking of expectations, because of
Critical:
Unlike high-priority threads, events that occur during a critical thread are not discarded. For example, if the user presses a hotkey while the current thread is critical, the hotkey is buffered indefinitely until the current thread finishes or becomes noncritical, at which time the hotkey is launched as a new thread.

GUI Events, Threads, and Subroutines:
Clicking on a control while its g-label is already running from a prior click will have no effect and the event is discarded. To prevent this, use Critical as the subroutine's first line (however, this will also buffer/defer other threads such as the press of a hotkey).

G-Label Notifications (Secondary):
I: ... Also, specifying Critical as the g-label's first line ensures that all "I" notifications are received (otherwise, some might be lost if the script cannot keep up with them).
I expected that event triggering messages received while the g-label is running would be ignored if the g-label is not Critical. But that's only half the truth. AHK actually posts an AHK_GUI_EVENT (0x0414) message even if the g-label is currently running. If this message is processed after the g-label has finished, it will call the g-label again. In the following example I need a Sleep with a delay of at least 22 ms to reliably prevent the call of the g-label:

Code: Select all

#NoEnv
SetBatchLines, -1
LabelCounter := 0

Gui, Add, Edit, w400 vEdit gEditLabel
Gui, Add, ListView, wp, Count|CurrentValue
Gui, Show, , Test
Return

GuiClose:
ExitApp

EditLabel:
GuiControlGet, Edit
GuiControl, , Edit, %Edit%*
LV_Modify(LV_Add("", ++LabelCounter, Edit), "Vis")
; Sleep, 22 ; if uncommented, the label won't be called again on my system
Return
So again, never expect that something will not happen. Test it!
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Undocumented behaviour of Edit control's gLabel

01 Oct 2017, 06:10

Good info just me :thumbup:. I see the same behaviour with / without the sleep. We could do something like this,

Code: Select all


; Needs to be 0 initially
lock:=0	; All script actions which changes the content of the edit should increment this value before doing it.

EditLabel:
	if lock {
		--lock ; Lock should only be decremented here.
		return
	}
	lock++	
	GuiControlGet, Edit
	GuiControl, , Edit, %Edit%*
	LV_Modify(LV_Add("", ++LabelCounter, Edit), "Vis")
Return
In this case we do not turn off the association between the label and the control.
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Undocumented behaviour of Edit control's gLabel

03 Oct 2017, 09:22

Another surprising finding which might be worth to be known:

I tested with multi-line edit controls because of
EN_CHANGE notification code

The EN_CHANGE notification code is not sent when the ES_MULTILINE style is used and the text is sent through WM_SETTEXT.
That's true, but while testing I noticed that multi-line edit controls are sending two EN_CHANGE notifications whenever you replace existing content. The first is sent after the original content has been removed, the second after the new content has been added. So the g-label might be called two times, and because the edit has been updated in the meantime, both times with the same content. Single-line edit controls send only one notification:

Code: Select all

#NoEnv
Gui, Margin, 20, 20
Gui, Add, Edit, w400 r1 vEDS hwndHEDS gEditLabel
Gui, Add, Edit, w400 r1 vEDM hwndHEDM gEditLabel +Multi -VScroll -WantReturn
Gui, Add, ListView, w400 r10, Source|Control|Content
Gui, Show, , Test
OnMessage(0x0111, "OnWmCommand") ; WM_COMMAND
Return

GuiClose:
ExitApp

EditLabel:
   GuiControlGet, ED, , %A_GuiControl%
   LV_Modify(LV_Add("", "Label", A_GuiControl, ED), "Vis")
Return

OnWmCommand(W, L) {
   Global HEDS, HEDM
   If ((L = HEDS) || (L = HEDM)) && ((W >> 16) = 0x0300) { ; EN_CHANGE
      GuiControlGet, ED, , %L%
      LV_Add("", "Msg", L = HEDS ? "EDS" : "EDM", ED)
   }
}
Once upon a time I believed that edit control events are easy to handle with AHK.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Undocumented behaviour of Edit control's gLabel

26 Nov 2017, 05:28

When the Edit control processes WM_SETTEXT, it sends EN_CHANGE to the GUI via WM_COMMAND. Because it is sent, not posted, the notification is processed before WM_SETTEXT returns. However, AutoHotkey processes EN_CHANGE (and other events) by posting an AHK_GUI_ACTION message to the queue. When the message loop eventually resumes, the message is processed and the g-label is called. Unless you do something to cause the message loop to run (such as call Sleep or 'Wait), this usually happens either at the message-check interval (if the thread is interruptible) or when the thread exits and the program returns to idling (or a prior Sleep/'Wait).

Setting a variable immediately before and immediately after changing the text won't work because the AHK_GUI_ACTION message is still sitting in the queue, waiting to be processed.

By contrast, if you remove the g-label, AHK_GUI_ACTION will not be posted. You can remove the g-label immediately before changing the text and restore it immediately after, since the EN_CHANGE notification is processed and discarded before Gui Add, UpDown/GuiControl/ControlSetText returns.

v2 uses an internal flag to suppress/ignore events generated by Edit.Value:= or Edit.Text:=. I will change the UpDown creation code to also set this flag, since the idea is that the event should be raised only by external changes, not by the GUI API.

I will not change v1.

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 19 guests