Link to home
Start Free TrialLog in
Avatar of NetGeek
NetGeek

asked on

OnExit eats up mouseup event for new control when showing another window

The problem can be replicated easily.

place 3 tedits on a form.
write a showmessage('exit') in edit1's onexit event
run the program
give edit1 focus
use the mouse to give edit3 focus, click ok to the showmessage
observe how you can't write anything in edit3 now, until you click with the mouse somewhere on the form !
give edit2 focus, then use to the mouse to give edit3 focus
observe how you can type what you want in edit3 now  !

So far I've established that the problem lies in the fact that edit3 doesn't receive a mouseup-message when the old controls onExit event displays a window of any kind, i've tried it as well with showing a form of my own in the onExit event, same result. In fact, windows is under the impression that the mouse is held down over edit3 after you've clicked Ok to the showmessage

I guess it's a bug in Delphi/Windows but how to work around it ? I know i can force a WM_LBUTTONUP on edit3's onMouseDown event (since its the last event called in the process) but that's more than tedious, and not always applicable



Avatar of geobul
geobul

Hi,

Usually OnExit is used for validation purposes. When the entered value is wrong the code in the event shows a message and sets the focus back to the same control. Otherwise there is no message and everything is OK. Example:

procedure TForm1.Edit1Exit(Sender: TObject);
begin
  try
    StrToInt(Edit1.Text);
  except
    ShowMessage('Enter a valid integer');
    Edit1.SetFocus; // return the focus back
  end;
end;

I know that this is not a general solution but if you show a message/form then you have to change the focused control.

Regards, Geo
Avatar of NetGeek

ASKER

well, thanks, but that's no news

the problem is that i can't even changed the focused control as you suggest, because the WM_LBUTTONDOWN message isn't sent to the new control until AFTER the onExit event for the "old" control is finished, and *then* the focus changes.

Avatar of NetGeek

ASKER

Problem solved (at least it looks like it) !

in the onExit event, after the form/dialog has been shown, you simply add a WM_LBUTTONUP message for the new control to the queue. That way the intended control will have focus after alle the code in the onExit event has been run, and the  new control will behave as if the onExit event didn't display anything.

BTW. Use PostMessage and not SendMEssage !


Anybody think that solution is worth some points ?  ;)

Best regards
NetGeek


Avatar of Ferruccio Accalai
tried this with 2 different results:
procedure TForm1.Edit1Exit(Sender: TObject);
begin
MessageBox(Application.Handle,PChar('exit'),nil,mb_ok);
end;

Here the same result of ShowMessage...

procedure TForm1.Edit1Exit(Sender: TObject);
begin
MessageBox(Application.MainForm.Handle,PChar('exit'),nil,mb_ok);
end;

Here Lost the focus but the mouseup was sent...

Some news??
This behavior is quite normal. The OnExit is triggered by the MouseDown of the click. The OnExit opens a new modal window (the ShowMessage) which naturally receives the MouseUp (and ignores it).
Error...no MouseUp event with mainform.handle...
Avatar of NetGeek

ASKER

See my last comment :)

further testing shows that my solution must be the right one. When comparing the messages sent to the new activecontrol with the messages sent when the onExit event doesn't display anything you get exactly the same : Enter, MouseDown, MouseClick and finally MouseUp. Just like it is supposed to be :)

NetGeek
From within OnEnter/OnExit events, you should never call any code that results in changing focus because these events are called just when changing focus is taking place. That includes code showing a modal form (e.g. exception message).
Avatar of NetGeek

ASKER

well, Tondrej, if you can control it, and the application needs it, why not ?

I'm not really impressed with people who just say "you shouldn't...", I'm more of a "we'll find a way to do ..." kinda guy myself.

But if you know of a better way to validate input in one editbox, and either reject and return focus to the editbox, accept but warn the user and pass focus to the intended control, or accept without action, please let me know, I'm all ears. PS. the warning to the user can't be shown in the same window as the controls

NetGeek
I was trying to help you avoid unexpected problems, rather than impress you, NetGeek. Your solution may work if the newly focused control is a TEdit. With other controls, it may not work or it may have undesirable side effects.
OnExit may be fired by clicking outside the focused control, or pressing Tab or Alt-Tab keys, or by executing any code which changes focus. Think about it.
Good luck.
I, personally, don't make verification + warning in OnExit events but in 'OK' button click. I find this approach better for users because they do not always follow the logic of the Tab order when entering data on forms. Most of my users use the keyboard (Tab and Shift+Tab) for moving around, not the mouse. They hate pop-up windows warning them something until they are not ready to hit the button.

Regards, Geo
NetGeek,

Why not use the OnChange event to validate input? this way you know the user has no intent of focusing on another control but is typing something in. BTW what Delphi version are using? because I cannot replicate the situation (using ShowMessage) you explain but do understand what you're trying to tell us.

I also agree with geobul's last post. Either you handle the input and do not allow certain characters or format  e.g. using a maskedit. If a maskedit it not enough use the key press or OnChange events to manage input, that method really works well for me. Or you verify input after the users hits an OK or Save button.
Avatar of NetGeek

ASKER

hmm, I "could" get into a discussion about how I treat my users, but this question I posted was really about something else ;) Maybe we'll meet in a froum where developement theories are discussed ;)

personally I find it kinda annoying when I ask a specific question, and then get e-mail upon e-mail telling me that somebody has posted a comment, only to find out that the comment wasn't really relevant to my question.

Maybe the fault is mine, not having pointed out straight away that I'm well aware of the other issues involved in focus-change etc.

So, while I thank you for your time, I allow myself to ask this question to be deleted. In my eyes I actually managed to find the solution I was lokking for, my self.

Best regards
NetGeek
To All Experts,

A request has been made in Community Support to close this question:

http://www1.experts-exchange.com/questions/20655824/24-June-Please-delete-question.html

If there are no objection, after 72 hrs, a moderator will finalize this question by:

- Deleting the Q and refunding points

Please leave any recommendations here.

Best regards,

YensidMod
Community Support Moderator @Experts Exchange
Personally i think he is ungrateful.
His initial assumption that it is a Windows or Delphi error is wrong.
So a programmatic solution is not the best way to solve the problem,
but he rejects any other solution.

I do not mind deleting the question, but i would propose PAQ/refund.
ASKER CERTIFIED SOLUTION
Avatar of Chmod
Chmod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I think a SETFOCUS message is also needed for best performance.

PostMessage(ActiveControl.Handle,WM_SETFOCUS,0,0);
PostMessage(ActiveControl.Handle,WM_LBUTTONUP,0,0);