Recent

Author Topic: [Solved] Preserving TEdit cursor position etc.  (Read 1440 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
[Solved] Preserving TEdit cursor position etc.
« on: September 24, 2021, 10:07:48 am »
I've got a form with a TEdit into which I occasionally want to enter text, and a frame into which monitoring information is being written asynchronously by a background thread via Synchronize() or QueueAsyncCall().

When monitoring information is written, the focus moves away from the TEdit. I can transfer it back using the form's ActiveControl property, but at that point the cursor is placed at the left of the text being entered and I presume that other state is destroyed.

Is there any way of saving the edit state? I've tried saving and restoring CaretPos without success.

MarkMLl
« Last Edit: September 24, 2021, 11:52:00 am by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Preserving TEdit cursor position etc.
« Reply #1 on: September 24, 2021, 10:18:48 am »
Hi!

The cursor position of  a Tedit can be read and set by Edit.selStart

Code: Pascal  [Select][+][-]
  1. var Cpos : integer;
  2. ...
  3. Cpos := Edit.SelStart;
  4. ...
  5. Edit.SelStart := Cpos;
  6.  

SelStart is zero based - to set the  cursor before the first char .

Winni

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Preserving TEdit cursor position etc.
« Reply #2 on: September 24, 2021, 10:41:13 am »
No change, the cursor always zips back to the left. Code looks something like this

Code: Pascal  [Select][+][-]
  1. procedure TFormPSTalk.MonitorHex(const message: string; sending: boolean);
  2.  
  3. var
  4.   i: integer;
  5.   savedControl: TWinControl;
  6. //  savedCaret: TPoint;
  7.   savedSelStart, savedSelLength: integer;
  8.  
  9. begin
  10.   savedControl := ActiveControl;
  11.   if ActiveControl = EditMessage then begin
  12. //    savedCaret := EditMessage.CaretPos;
  13.     savedSelStart := EditMessage.SelStart;
  14. //    savedSelLength := EditMessage.SelLength;
  15.   end;
  16.   for i := 1 to Length(message) do
  17.     MonitorHex(Ord(message[i]), sending);
  18.  
  19. (* Crude, but ensures that the final BCC or CRC byte of a message is always     *)
  20. (* displayed immediately. In practice since no interactive facilities are being *)
  21. (* used it looks as though the cursor is never displayed, which means we don't  *)
  22. (* have to waste time turning it off (which doesn't force an update).           *)
  23.  
  24.   FrameTerminalDisplay1.Cursor(true);
  25.   ActiveControl := savedControl;
  26.   if ActiveControl = EditMessage then begin
  27. //    EditMessage.CaretPos := savedCaret
  28.     EditMessage.SelStart := savedSelStart;
  29. //    EditMessage.SelLength := savedSelLength
  30.   end
  31. end { TFormPSTalk.MonitorHex } ;
  32.  

If I remove the monitoring stuff in the middle the cursor stays at the end of the text being edited.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Preserving TEdit cursor position etc.
« Reply #3 on: September 24, 2021, 10:51:24 am »
Maybe TRecall?
Specialize a type, not a var.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Preserving TEdit cursor position etc.
« Reply #4 on: September 24, 2021, 11:08:09 am »
Something like this?

Code: Pascal  [Select][+][-]
  1. var
  2.   recall: TRecall;
  3. ...
  4.     recall := TRecall.Create(TEdit.Create(nil), EditMessage);
  5. ...
  6.     recall.Destroy
  7.  

I get a runtime "Cannot assign a TEdit to a TEdit" at the Create :-(

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

balazsszekely

  • Guest
Re: Preserving TEdit cursor position etc.
« Reply #5 on: September 24, 2021, 11:18:50 am »
The following code works fine with Lazarus Trunk/FPC 3.2.0.
Code: Pascal  [Select][+][-]
  1. //...
  2.   TForm1 = class(TForm)
  3.     Edit1: TEdit;
  4.   private
  5.      FSelStart: Integer;
  6.      FSelLength: Integer;
  7.   public
  8.   end;  
  9.  
  10. //save state
  11.   FSelStart := Edit1.SelStart;
  12.   FSelLength := Edit1.SelLength;  
  13.  
  14. //restore state
  15.   Edit1.SetFocus;
  16.   Edit1.SelStart := FSelStart;
  17.   Edit1.SelLength := FSelLength;
  18.   Edit1.SelStart := FSelStart;
 

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Preserving TEdit cursor position etc.
« Reply #6 on: September 24, 2021, 11:36:08 am »
Hi!

Maybe empty the evnt queue:


Code: Pascal  [Select][+][-]
  1.  ActiveControl := savedControl;
  2.  application.processMessages;  /// <---- !!!!
  3. if ActiveControl = EditMessage then begin
  4.     EditMessage.SelStart := savedSelStart;
  5.   end

Winni

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Preserving TEdit cursor position etc.
« Reply #7 on: September 24, 2021, 11:51:43 am »
Still zips back to the left with Lazarus 2.0.12 and FPC 3.2.0.

Ditto trunk which identifies itself as 2.3.0 SVN r65280.

The important info that I should have included is that this is Debian x86_64 using gtk2.

I find that if I switch to Qt5 I don't get the problem (but there are other UI problems which make it an undesirable solution).

I suspect that this is something I'm going to have to live with, at least until gtk3 is usable.

I find that if I use Winni's suggestion of an APM before restoring the selection state it appears to work, but it definitely requires that restoration of gtk2 and even Qt5 benefits from it.

:-)

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Preserving TEdit cursor position etc.
« Reply #8 on: September 24, 2021, 01:15:58 pm »
Something like this?

Code: Pascal  [Select][+][-]
  1. var
  2.   recall: TRecall;
  3. ...
  4.     recall := TRecall.Create(TEdit.Create(nil), EditMessage);
  5. ...
  6.     recall.Destroy
  7.  

I get a runtime "Cannot assign a TEdit to a TEdit" at the Create :-(

MarkMLl
It should work with the existing instance?
Specialize a type, not a var.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Preserving TEdit cursor position etc.
« Reply #9 on: September 24, 2021, 02:09:06 pm »
It should work with the existing instance?

I'm stymied by the lack of examples. In any event it looks as though it's the APM which is key.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018