luciano_f 5 Posted 7 hours ago (edited) Click on Edit1 and press Enter to see Edit2 without the cursor. Some customers complain that the system loses its cursor. I don't know how to replicate this, so I created an application that simulates this incorrectly. See this example. I know how to solve the problem, which would be not displaying the fade-out screen. However, the idea of my example is just to simulate the problem. Suppose I don't know that it's the fade-out screen that's causing the problem. How could I solve it ? Going to another control and back is a terrible solution because the other control might have code in the OnExit example that would trigger it, among other problems. I tried using ProcessMessages or Update on the form, but I didn't find a solution. Can anyone help me ? Lost cursor.7z Edited 7 hours ago by luciano_f Share this post Link to post
PeterBelow 260 Posted 7 hours ago (edited) Loosing the caret tends to happen if you programmatical set the focus to a control in code that is itself triggered by a focus transition. An OnExit event is such a code location, as is OnEnter. The common solution is to delay setting the focus until the ongoing focus transition has completed. You can do that either by posting (not sending) a custom message to the form, doing the SetFocus in the handler for that message (you can pass a reference to the target control in the message lparam), or by using a TTimer with a short interval (e.g. 250 msecs). The timer starts disabled, you enable it if you need to change focus and do that in the OnTimer event, after first disabling the timer there. In this case you have to store a reference for the control to focus either in a private field of the form or in the Tag propertry of the timer. Edited 7 hours ago by PeterBelow Share this post Link to post
Anders Melander 2065 Posted 6 hours ago 19 minutes ago, luciano_f said: Some customers complain that the system loses its cursor. You mean the caret, right? The cursor is the one you move with the mouse. The caret is the blinking indicator that shows the current position in a text control. The caret should be shown automatically if an edit control has the focus (unless it's been explicitly hidden with HideCaret (it's hasn't in this case)) so my guess is that the sequence of actions you are doing (see Peter's answer) is causing VCL to think that the control has focus while Windows is of another opinion (and of course Windows is always right, in this case). One solution would be to simply not lose the focus by showing your fading form without activating it. See ShowWindow(SW_SHOWNA). Another is the PostMessage trick Peter mentioned. I wouldn't recommend the TTimer workaround - it's a lazy hack. const MSG_DO_STUFF = WM_USER; type TMyForm = class(TForm) private procedure MsgMyStuff(var Msg: TMessage); message MSG_DO_STUFF; end; ... procedure TMyForm.MsgMyStuff(var Msg: TMessage); begin ShowDialog('It works!'); end; procedure TMyForm.Edit1Exit(Sender: TObject); begin PostMessage(Handle, MSG_DO_STUFF, 0, 0); end; Share this post Link to post
luciano_f 5 Posted 6 hours ago How could I create a global code for the entire system using my colleagues' approaches? Something like this Procedure P_SetFocus(Control : TWinControl); Begin // How could you help? End; Share this post Link to post
Anders Melander 2065 Posted 6 hours ago 14 minutes ago, luciano_f said: How could I create a global code for the entire system using my colleagues' approaches? You can't. The "global" solution to doing something that causes problems is to stop doing something that causes problems. 1 Share this post Link to post
Remy Lebeau 1642 Posted 2 hours ago 4 hours ago, Anders Melander said: Another is the PostMessage trick Peter mentioned. Or TThread.ForceQueue(), eg: procedure TMyForm.Edit1Exit(Sender: TObject); begin TThread.ForceQueue(nil, procedure begin ShowDialog('It works!'); end ); end; Share this post Link to post
luciano_f 5 Posted 8 minutes ago Is there any way to know when a controller has lost its Caret ? Based on that, I could create code like this postmessage(handle, WM_NEXTDLGCTL, 0, 0); postmessage(handle, WM_NEXTDLGCTL, 1, 0); only when the problem occurs. Share this post Link to post