Memo - Cursorposition als Koordinaten für Komponente

Rund um die LCL und andere Komponenten
Antworten
GU_Meyer
Beiträge: 66
Registriert: Mo 21. Apr 2014, 10:22

Memo - Cursorposition als Koordinaten für Komponente

Beitrag von GU_Meyer »

Hallo,
in einem simplen Memo möchte ich sowas wie ein Kontexmenü implementieren. Allerdings reicht mir vorerst die Anzeige eines Edits. Alles nicht die Frage. Sondern: Wie komme ich in einem Memo von der aktuellen Cursorposition auf eine Koordinate (Y), die ich als Edit1.Top setzen kann? Mit Memo1.CaretPos.Y kriege ich ja nur die aktuelle Zeilennummer. Mit SendMessage(EM_LINEFROMCHAR,....) kriege ich ebenfalls nur die aktuelle Zeilennummer. Der Versuch, über die Zeilennummer, die Größe des verwendeten Fonts (Font.Size) und dem Wert von Memo1.Top die nötige Position zu berechnen schläft ebenfalls fehl. Kennt ein Memo diese Koordinaten nicht?

Danke schon mal und Gruss
GU_Meyer

sstvmaster
Beiträge: 575
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Memo - Cursorposition als Koordinaten für Komponente

Beitrag von sstvmaster »

Entweder: Im Memo mit OnMouseDown bekommst du x+y Koordinaten
Oder: PopupMenu auf das Form Legen und Memo Popup zuweisen
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Memo - Cursorposition als Koordinaten für Komponente

Beitrag von Michl »

Windows only geht sowas hier:

Code: Alles auswählen

uses ..., messages, LCLType, LCLIntf;    
...
procedure TForm1.Memo1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
var
  ClientAreaCoordinates: LongWord;
  MemoTextHeight: LongWord;
  CaretPoint: TPoint;
  R: TRect;
  DC: HDC;
  OldFont: HGDIOBJ;
  Flags: LongWord;
begin
  DC := GetDC(Memo1.Handle);
  try
    R := Rect(0, 0, 10000, 10000);
    OldFont := SelectObject(DC, HGDIOBJ(Memo1.Font.Reference.Handle));
    Flags := DT_CALCRECT or DT_EXPANDTABS or DT_SINGLELINE or DT_NOPREFIX;
    DrawText(DC, PChar('Ag'), 2, R, Flags);
    SelectObject(DC, OldFont);
    MemoTextHeight := R.Bottom - R.Top;
  finally
    ReleaseDC(Memo1.Handle, DC);
  end;
  ClientAreaCoordinates := SendMessage(Memo1.Handle, EM_POSFROMCHAR, Memo1.SelStart, 0);
  CaretPoint.x := LoWord(ClientAreaCoordinates);
  CaretPoint.y := HiWord(ClientAreaCoordinates);
  CaretPoint := ScreenToClient(Memo1.ClientToScreen(CaretPoint));
  Edit1.Left := CaretPoint.x;
  Edit1.Top := CaretPoint.y + MemoTextHeight;
end;

Systemübergreifend würde ich ein Control nehmen, was ein Kontextmenü von Haus aus kann, z.B. TSynEdit etc.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

sstvmaster
Beiträge: 575
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Memo - Cursorposition als Koordinaten für Komponente

Beitrag von sstvmaster »

TMemo hat doch ein Kontextmenü????
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

GU_Meyer
Beiträge: 66
Registriert: Mo 21. Apr 2014, 10:22

Re: Memo - Cursorposition als Koordinaten für Komponente

Beitrag von GU_Meyer »

sstvmaster hat geschrieben:Entweder: Im Memo mit OnMouseDown bekommst du x+y Koordinaten

Wäre eine Möglichkeit. Gefällt mir allerdings nicht so gut.

sstvmaster hat geschrieben:Oder: PopupMenu auf das Form Legen und Memo Popup zuweisen

Gefällt mir schon besser, Ist aber auch noch nicht ganz das, was ich will.

Trotzdem Danke
Gruss
GU_Meyer

GU_Meyer
Beiträge: 66
Registriert: Mo 21. Apr 2014, 10:22

Re: Memo - Cursorposition als Koordinaten für Komponente

Beitrag von GU_Meyer »

Michl hat geschrieben:Windows only geht sowas hier:

Code: Alles auswählen

uses ..., messages, LCLType, LCLIntf;    
...
procedure TForm1.Memo1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
var
  ClientAreaCoordinates: LongWord;
  MemoTextHeight: LongWord;
  CaretPoint: TPoint;
  R: TRect;
  DC: HDC;
  OldFont: HGDIOBJ;
  Flags: LongWord;
begin
  DC := GetDC(Memo1.Handle);
  try
    R := Rect(0, 0, 10000, 10000);
    OldFont := SelectObject(DC, HGDIOBJ(Memo1.Font.Reference.Handle));
    Flags := DT_CALCRECT or DT_EXPANDTABS or DT_SINGLELINE or DT_NOPREFIX;
    DrawText(DC, PChar('Ag'), 2, R, Flags);
    SelectObject(DC, OldFont);
    MemoTextHeight := R.Bottom - R.Top;
  finally
    ReleaseDC(Memo1.Handle, DC);
  end;
  ClientAreaCoordinates := SendMessage(Memo1.Handle, EM_POSFROMCHAR, Memo1.SelStart, 0);
  CaretPoint.x := LoWord(ClientAreaCoordinates);
  CaretPoint.y := HiWord(ClientAreaCoordinates);
  CaretPoint := ScreenToClient(Memo1.ClientToScreen(CaretPoint));
  Edit1.Left := CaretPoint.x;
  Edit1.Top := CaretPoint.y + MemoTextHeight;
end;

Systemübergreifend würde ich ein Control nehmen, was ein Kontextmenü von Haus aus kann, z.B. TSynEdit etc.


Oh, das muss ich mir genauer angucken. Aber nciht mehr heute Abend (Grund dafür siehe meine Antwort an sstvmaster
Dankeschön
Gruss
GU_Meyer

GU_Meyer
Beiträge: 66
Registriert: Mo 21. Apr 2014, 10:22

Re: Memo - Cursorposition als Koordinaten für Komponente

Beitrag von GU_Meyer »

sstvmaster hat geschrieben:TMemo hat doch ein Kontextmenü????

Das ist richtig. Das würde ich sogar nehmen. Aber so richtig gefällt mir das auch nicht. Jetzt hatte ich gerade (Vielleicht kennt ja jemand den "Moment, ich bring nur schnell das Baby ins Bett, schnarch ihm kurz was vor, damit es richtig fest schläft....*zwei-Stunden-später*...wieder wach"-Effekt?) die Idee, dass ich nicht ganz nur ein Kontextmenü suche, sondern eine Mischung aus Kontextmenü und Intellisense. Das Kontextmenü von TMemo ist schon mal gut, ich möchte es aber direkt an die Zeile, die bearbeitet wird, "ketten".

Gruss
GU_Meyer

Antworten