delphivclcaretrichedit

RichEdit needs two clicks to change cursor (caret) position when changing the active form (Delphi)


Here's the setting (I'm using Delphi 7, not sure if this will happen in later/earlier versions):

Create a new project with two forms. Put a TMemo, a TRichEdit and a TButton on the first form. Set the Lines properties of both the TMemo and the TRichEdit to 123456. In the TButton's OnClick event handler put Form2.Show;

Run the application, click the button and the empty Form2 will show and get focus. Now click in the middle of the text "123456" of the TMemo in Form1 - the focus will change back to Form1 and the cursor (caret) will be in the middle of the text "123456" where you clicked as expected. Click on Form2 again to give it focus again. Now click in the middle of the text "123456" of the TRichEdit in Form1 - the focus will change back to Form1, but the cursor (caret) won't be in the middle of the text "123456" where you clicked, but on the second empty line of the RichEdit (or wherever it was previously). If you click a second time in the same place in the middle of the text "123456" of the TRichEdit, the cursor (caret) will now be moved there as expected.

So the TRichEdit control gets focus, but the cursor (caret) isn't moved as expected.

Note: This only happens when changing the focus from one form to another. Changing the focus from one control to a TRichEdit control in the same form doesn't exhibit this problematic behavior.

My question: How to avoid the need for this second click inside a TRichEdit and have the control behave like the TMemo in this regard.

Thanks in advance!


Solution

  • You can derive a new control, or subclass the richedit in any way you like, to intervene with the activation mechanism. Below sample interposer class sets the focus to the control before the mouse down message is posted when it is about to be activated by the left button of the mouse if the control is not already focused:

    type
      TRichEdit = class(comctrls.TRichEdit)
      protected
        procedure WMMouseActivate(var Message: TWMMouseActivate);
          message WM_MOUSEACTIVATE;
      end;
    
    procedure TRichEdit.WMMouseActivate(var Message: TWMMouseActivate);
    begin
      if (GetFocus <> Handle) and (Message.MouseMsg = WM_LBUTTONDOWN) then
        SetFocus;
      inherited;
    end;