Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Wahre Position des Cursors im Memo (https://www.delphipraxis.net/140279-wahre-position-des-cursors-im-memo.html)

martinf16 15. Sep 2009 03:07


Wahre Position des Cursors im Memo
 
Hallo!

Zum Bestimmen der Position, an der sich ein Cursor im Memo Feld befindet kenne ich zwei Möglichkeiten:

Delphi-Quellcode:
SendMessage(Memo1.Handle, EM_LINEFROMCHAR, Memo1.Selstart, 0)
und
Delphi-Quellcode:
charetPos(X,Y)
Das funktioniert auch alles ganz gut, bis zu dem Punkt, wo es im Memo einen Zeilenumsprung gibt. Geht die erste Zeile des Memos über 2 "Zeilen", da sie länger als eine Zeile ist, geben mir beide Möglichkeiten einen "falschen" Wert zurück. Ich möchte den Wert haben, der auch bei memo1.lines[i] als i verwendet wird.

Also als Beispiel:

Delphi-Quellcode:
Lines im Memo                       Ergebnisse  Ergebnis sollte sein:
1: Dieser String bricht um, da er   Line = 1     Line = 1
   zu lang ist.                     Line = 2     Line = 1
2: Dieser String bricht nicht um.   Line = 3     Line = 2
3: Dieser String bricht nicht um.   Line = 4     Line = 3
Ich hoffe, ihr könnt mir helfen. Vielen Dank!

himitsu 15. Sep 2009 03:44

Re: Wahre Position des Cursors im Memo
 
Im Notfall ab Memo1.SelStart rückwärts die Zeilenumbrüche zählen:

- entweder direkt in Memo1.Text nach #13 und #10 ausschauhalten und diese entsprechend bis Position SelStart zählen

- oder
Delphi-Quellcode:
i2 := Memo1.SelStart;
i := 0;
While (i < Memo1.Lines.Count) and (i2 >= Length(Memo1.Lines[i]) + Length(sLineBreak)) do
  Inc(i);
falls ich jetzt gut geraten hab, dürfte nun in i die Zeile stehen

[edit]
achso, daß ist auch in .Lines so drinnen :shock:
ist mir noch nie aufgefallen

also dann bleibt ja nur noch die erste Möglichkeit :gruebel:

Lannes 15. Sep 2009 07:15

Re: Wahre Position des Cursors im Memo
 
Hallo,

Zitat:

Zitat von martinf16
Ich möchte den Wert haben, der auch bei memo1.lines[i] als i verwendet wird.

die beiden Möglichkeiten arbeiten doch richtig, es ist genau der Wert den du für Lines benötigst.

Code:
Lines im Memo                       Ergebnisse  
1: Dieser String bricht um Line = 0     Memo.Lines[0] -> 'Dieser String bricht um'
   in diese Zeile          Line = 1     Memo.Lines[1] -> 'in diese Zeile'
2: kein Umbruch            Line = 2     Memo.Lines[2] -> 'kein Umbruch'
3: kein Umbruch            Line = 3     Memo.Lines[3] -> 'kein Umbruch'
Wenn man feststellen will ob eine Zeile einen automatischen Umbruch hat, hilft das:
Delphi-Quellcode:
i := 0;
if Memo.Text[Length(Memo.Lines[i])+1] <> #13 then
  ShowMessage('Zeile hat automatischen Umbruch');
Zwischen den automatisch umgebrochenen Zeilen befindet sich kein #13#10

martinf16 15. Sep 2009 22:45

Re: Wahre Position des Cursors im Memo
 
Zitat:

Zitat von Lannes
die beiden Möglichkeiten arbeiten doch richtig, es ist genau der Wert den du für Lines benötigst.

Also bei mir irgendwie nicht, da werden die umgebrochenen Zeilen leider als meherere Zeilen mitgezählt, die ich ja nicht zählen möchte.

Zitat:

Zitat von Lannes
Zwischen den automatisch umgebrochenen Zeilen befindet sich kein #13#10

Das wusste ich noch nicht, damit lässt sich ja eine Funktion zusammenbauen, wie es himitsu vorgeschlagen hat.

Ich dachte nur, dass es vielleicht unabhängig von einer selbstgebastelten Funktion eine Möglichkeit gibt durch SendMessage oder was auch immer den Wert direkt abzufragen..

Lannes 16. Sep 2009 15:06

Re: Wahre Position des Cursors im Memo
 
Hallo,

also möchtest Du die Zeile im Zustand WordWrap = False.

Zitat:

Zitat von martinf16
...damit lässt sich ja eine Funktion zusammenbauen ...

Da gibt es mehrere Möglichkeiten, such Dir eine aus, im Ergebnis sind alle gleich:

- Über den Zeichenindex harte Umbrüche vor und nach Selstart suchen
Delphi-Quellcode:
function GetNoWordWrapSelLinesI(aMemo: TMemo): String;
var a,e : Integer;
    s : String;
begin
  s := aMemo.Text;
  a := aMemo.SelStart;
  e := a;
  while (a >= 1) and (s[a] <> #10) do
    dec(a);
  while (e <= Length(s)) and (s[e] <> #13) do
    inc(e);
  Result := Copy(s,a +1, e - a -1);
end;
-mit EM_LINEINDEX und EM_LINEFROMCHAR
Delphi-Quellcode:
function GetNoWordWrapSelLinesII(aMemo: Tmemo): String;
var a,e : Integer;
    s : String;

  function GetLineEnd: Integer;
  begin
    Result := aMemo.Perform(EM_LINEINDEX, e, 0) + Length(aMemo.Lines[e]) +1;
  end;

begin
  with aMemo do
    begin
    s := Text;
    a := SendMessage(Handle, EM_LINEFROMCHAR, SelStart, 0);
    e := a;
    while (a > 0) and (s[Perform(EM_LINEINDEX, a, 0)-1] <> #13) do
     dec(a);
    while (e < Lines.Count -1) and
          (s[GetLineEnd] <> #13) do
      inc(e);
    a := Perform(EM_LINEINDEX, a, 0) +1;
    e := GetLineEnd;
    Result := Copy(s,a,e-a);
    end;
end;
WordWrap temporär aufheben
Delphi-Quellcode:
function GetNoWordWrapSelLinesI(aMemo: Tmemo): String;
var SelStartTmp, SelLengthTmp, LineIndex : Integer;
    OldWordWrap : Boolean;
begin
  Result := '';
  with aMemo do
    begin
    SelStartTmp := SelStart;
    SelLengthTmp := SelLength;
    Lines.BeginUpdate;
    OldWordWrap := WordWrap;
    WordWrap := False;
    SelStart := SelStartTmp;
    LineIndex := SendMessage(Handle, EM_LINEFROMCHAR, SelStart, 0);
    Result := Lines[LineIndex];
    WordWrap := OldWordWrap;
    SelStart := SelStartTmp;
    SelLength := SelLengthTmp;
    Lines.EndUpdate;
    end;
end;

himitsu 16. Sep 2009 15:11

Re: Wahre Position des Cursors im Memo
 
Delphi-Quellcode:
S := Copy(Memo1.Text, 1, Memo1.SelStart);
Line := 0;
for i := 1 to Length(S) do
  if S[i] = #10 then Inc(Line);

Progman 16. Sep 2009 15:26

Re: Wahre Position des Cursors im Memo
 
In einem Delphi beiliegenden Beispiel (RTF-Editor) wird das folgendermaßen gelöst:
Delphi-Quellcode:
//Editor ist ein TRichEdit
procedure TMainForm.UpdateCursorPos;
var
  CharPos: TPoint;
begin
  CharPos.Y := SendMessage(Editor.Handle, EM_EXLINEFROMCHAR, 0,
    Editor.SelStart);
  CharPos.X := (Editor.SelStart -
    SendMessage(Editor.Handle, EM_LINEINDEX, CharPos.Y, 0));
  Inc(CharPos.Y);
  Inc(CharPos.X);
  StatusBar.Panels[0].Text := Format('Line: %3d  Col: %3d', [CharPos.Y, CharPos.X]);
end;
Wäre mal zu testen, ob das auch mit TMemo geht. Habs noch nicht probiert.

Lannes 17. Sep 2009 07:55

Re: Wahre Position des Cursors im Memo
 
Hallo,

abgesehen davon das EM_EXLINEFROMCHAR nur im RichEdit unterstützt wird,
liefert der Code auch im RichEdit den Zeilenindex unabhängig von der Art der Umbrüche.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:13 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz