Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: XE8: Focusing issue in combination with OnExit event handler


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 6 - Last Post: Feb 2, 2016 8:31 AM Last Post By: Remy Lebeau (Te...
Jan Dijkstra

Posts: 206
Registered: 11/4/99
XE8: Focusing issue in combination with OnExit event handler  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 29, 2016 1:53 AM
I have the following problem:

In an OnExit event handler of a TEdit box, I want to inform the user of a problem with whatever was typed. I do this by calling up a Windows API MessageBox. After the user dismisses the message box, I call SetFocus on my edit box to refocus it. Something that is done extensively inside the VCL as well.

This, naturally, interrupts the sequence of events tied to changing the focus from one control to the next. And the VCL does not seem to cope with it. After the message box is dismissed, I end up with the form in a state of limbo.

The ActiveControl property correctly points to my edit box again, so SetFocus did it's job.

But, when I call the Windows API routine GetFocus (), it returns me a NULL handle.

When I type regular characters on the keyboard, nothing happens. Not even with KeyPreview on the form enabled and a KeyPress event handler attached. However, when I press the <tab> key, the form reacts by triggering my edit box it's OnExit event handler again.

In CBuilder 5 I had the same problem, but I could solve it there by clearing the csFocusing state in the ComponentState property of the ActiveControl in the OnExit event handler. In an OnExit event handler, ActiveControl points to whatever control is supposed to get the focus. However, in XE8 this trick no longer works.

Does anyone have an idea how to persuade the VCL to properly return the focus (thus including the actual Windows focus on an actual HWND, being the Handle of the edit box after the focus has been switched back and forth between the VCL and the Windows MessageBox ?

To be precise:

After returning from the Windows API message box, and calling SetFocus on my edit box in it's OnExit event handler, both ActiveControl AND FFocusedControl are set to my edit box. The problem is the actual HWND that has been set as the focused control. That one is NULL. So, to the Windows kernel, there is no control that has keyboard focus. And thus my keystrokes go nowhere.

Checking up on the various values in the OnExit handler reveals that, after calling the VCL's SetFocus member on my edit box, the HWND for the focused control is the Handle for my edit box. So, just before leaving the OnExit event handler, everything is set correctly. It's only AFTER the the OnExit event handler has returned that the HWND for the focus control gets cleared somewhere.

Edited by: Jan Dijkstra on Jan 29, 2016 2:05 AM
Hanno Nagland

Posts: 7
Registered: 7/7/01
Re: XE8: Focusing issue in combination with OnExit event handler  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 29, 2016 7:16 AM   in response to: Jan Dijkstra in response to: Jan Dijkstra
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: XE8: Focusing issue in combination with OnExit event handler [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 29, 2016 1:26 PM   in response to: Jan Dijkstra in response to: Jan Dijkstra
Jan wrote:

This, naturally, interrupts the sequence of events tied to changing
the focus from one control to the next. And the VCL does not seem
to cope with it.

Not so much the VCL, but Windows itself cannot cope with it properly. This
is not a new issue, people have been wrestling with this for years in every
Windows release. The short and long of it is - don't disrupt the sequence
of focus changes. Just don't do it. Period. A lot of things depends on
proper sequencing.

Does anyone have an idea how to persuade the VCL to properly return
the focus (thus including the actual Windows focus on an actual HWND,
being the Handle of the edit box after the focus has been switched
back and forth between the VCL and the Windows MessageBox ?

The OnExit event is not the best place to display a message box (or anything
else that requires focus). If you absolutely must use that event (and generally,
OnExit events should not be used to popup errors about unacceptable input),
then you need to delay the MessageBox() until control has returned to the
message queue first. Have OnExit call PostMessage() to post yourself a custom
message and then call MessageBox() in the message handler. Or have OnExit
enable a short TTimer and then call MessageBox() when it elapses. Either
way, focus is allowed to change correctly, and then you can change focus
back to the TEdit after MessageBox() has been dismissed.

--
Remy Lebeau (TeamB)
Jan Dijkstra

Posts: 206
Registered: 11/4/99
Re: XE8: Focusing issue in combination with OnExit event handler [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 1, 2016 12:28 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Jan wrote:

This, naturally, interrupts the sequence of events tied to changing
the focus from one control to the next. And the VCL does not seem
to cope with it.

Not so much the VCL, but Windows itself cannot cope with it properly. This
is not a new issue, people have been wrestling with this for years in every
Windows release. The short and long of it is - don't disrupt the sequence
of focus changes. Just don't do it. Period. A lot of things depends on
proper sequencing.

Does anyone have an idea how to persuade the VCL to properly return
the focus (thus including the actual Windows focus on an actual HWND,
being the Handle of the edit box after the focus has been switched
back and forth between the VCL and the Windows MessageBox ?

The OnExit event is not the best place to display a message box (or anything
else that requires focus). If you absolutely must use that event (and generally,
OnExit events should not be used to popup errors about unacceptable input),
then you need to delay the MessageBox() until control has returned to the
message queue first. Have OnExit call PostMessage() to post yourself a custom
message and then call MessageBox() in the message handler. Or have OnExit
enable a short TTimer and then call MessageBox() when it elapses. Either
way, focus is allowed to change correctly, and then you can change focus
back to the TEdit after MessageBox() has been dismissed.
--

Well, using PostMessage (or a timer for that matter) to let the focusing complete is not an option. When the focus is not allowed to leave the edit box, I don't want the OnEnter to fire on the control that was supposed to receive the focus upon leaving the edit box. And the VCL internally has a mechanism to handle that, provided I don't let the refocusing run it's course. In short, for this internal mechanism to work, I have to interrupt the focusing.

But your PostMessage remark did give me an idea. In the OnExit handler, I post myself a custom message. And in the WndProc handler, where I receive this message, I check if GetFocus () returns a NULL handle. If it does, I call the Windows API SetFocus routine on myself. This works like a charm.

Remy Lebeau (TeamB)

Edited by: Jan Dijkstra on Feb 1, 2016 12:30 AM
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: XE8: Focusing issue in combination with OnExit event handler [Edit][Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 1, 2016 11:15 AM   in response to: Jan Dijkstra in response to: Jan Dijkstra
Jan wrote:

Well, using PostMessage (or a timer for that matter) to let the
focusing complete is not an option.

Well, it is your ONLY option. You CANNOT steal the focus while focus in
already in the process of changing controls. You MUST let it play out correctly
or you WILL screw things up. If you don't want the next control's OnTer
to fire, you will have to disable it temporarily when you invoke your delayed
popup and then reenable it after the popup is dismissed.

--
Remy Lebeau (TeamB)
Jan Dijkstra

Posts: 206
Registered: 11/4/99
Re: XE8: Focusing issue in combination with OnExit event handler [Edit][Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 2, 2016 12:14 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Jan wrote:

Well, using PostMessage (or a timer for that matter) to let the
focusing complete is not an option.

Well, it is your ONLY option. You CANNOT steal the focus while focus in
already in the process of changing controls. You MUST let it play out correctly
or you WILL screw things up. If you don't want the next control's OnTer
to fire, you will have to disable it temporarily when you invoke your delayed
popup and then reenable it after the popup is dismissed.

That won't work. The VCL calls SetFocusedControl in response to a WM_SETFOCUS. It's SetFocusedControl that then generates the various OnEnter and OnExit event handlers, based on the parent hierarchy of both the old and the new focused control. Each OnEnter and OnExit can then stop the chain by shifting the focus again, to a different control. The VCL uses SendFocusMessage to check this. The entire chain of OnEnter and OnExit events is generated in response to a new control receiving the focus in the first place.

In order to stop the OnEnter in a manner you suggest would mean to stop shifting the focus alltogether. And if I do that, I don't get the OnExit event on the edit box where I do my input validation. Not to mention the fact that the only effective way of blocking the shift of the focus is to disable each and every control currently not having the focus.

The design of the VCL strongly suggest that focusing can be stopped by shifting the focus in an OnEnter or an OnExit event handler from any of the controls in the parent hierarchy route from old focused control to new focused control.

--
Remy Lebeau (TeamB)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: XE8: Focusing issue in combination with OnExit event handler[Edit][Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 2, 2016 8:31 AM   in response to: Jan Dijkstra in response to: Jan Dijkstra
Jan wrote:

The design of the VCL strongly suggest that focusing can be stopped
by shifting the focus in an OnEnter or an OnExit event handler from any
of the controls in the parent hierarchy route from old focused control
to new focused control.

I don't want to re-hash this discussion again. This has been discussed many
times before in the past. There are plenty of old posts in various online
archives where you can find past discussions, please search around for details.

--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02