TMemo Text per Drag&Drop an Mausposition einfügen [gelöst]

Rund um die LCL und andere Komponenten
Antworten
MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

TMemo Text per Drag&Drop an Mausposition einfügen [gelöst]

Beitrag von MmVisual »

Hallo,

Ich möchte gerne per Drag&Drop einen Text in ein TMemo an der Position einfügen wo man die Maus los lässt.
Mit TMemo.SelLength = 0 / TMemo.SelText kann man den Text einfügen, das Problem ist jedoch, dass ich nicht heraus gefunden habe wie ich den SelStart Parameter anhand der Maus Koordinate setzen kann.

Meine Versuche:

Code: Alles auswählen

procedure TfrmMain.memDebugSQLDragDrop(Sender, Source: TObject; X, Y: Integer);
Var p: TPoint;
  lParam, i: Integer;
Const EM_CHARFROMPOS = 215;
begin
  If Source <> tvDatenbank Then Exit;
  If Not Assigned(tvDatenbank.Selected) Then Exit;
  p.x := X;
  p.y := Y;
  lParam := Integer(@p);
  i := memDebugSQL.Perform(EM_CHARFROMPOS, 0, lParam);
  memDebugSQL.SelStart := i;
  memDebugSQL.SelLength := 0;
  memDebugSQL.SelText := tvDatenbank.Selected.Text;
end;


i ist immer 0, egal wohin ich den Mauszeiger ziehe. Weiß jemand wie man das richtig macht?
Der Code sollte unter Windows und Linux funktionieren, die Unit "Windows" ist nicht im Formular eingebunden, daher habe ich die Zeile "Const EM_CHARFROMPOS" manuell eingegeben.

Dankeschön!

Viele Grüße Markus
Zuletzt geändert von MmVisual am Mo 18. Nov 2019, 00:45, insgesamt 1-mal geändert.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: TMemo Text per Drag&Drop an Mausposition einfügen

Beitrag von Warf »

Erst mal Integer(@p); ist falsch. Der benötigte typ ist LPARAM nicht Integer. Wenn du deine Anwendung für 64 bit Kompilierst geht das ganz gewaltig in die Hose. Mein tipp: Benutz den typen der verlangt wird, nicht den von dem du denkst das er richtig sein könnte

Das ist aber nicht der fehler. Wenn man mal in die Dokumentation schaut: Link
lParam
The coordinates of a point in the control's client area. The coordinates are in screen units and are relative to the upper-left corner of the control's client area.

Rich edit controls: A pointer to a POINTL structure that contains the horizontal and vertical coordinates.
Edit controls: The LOWORD contains the horizontal coordinate. The HIWORD contains the vertical coordinate.

Es handelt sich bei TMemo um ein EditControl, also ist ein Pointer auf eine TPoint struktur eh komplett falsch, was du wirklich willst ist einen LongInt zusammengebaut aus der X-Koordinate als unteres WORD und der Y Koordinate als oberes WORD. Zum erstellen des LParams gibt es die Funktion MakeLParam in der Windows Unit, welche die X und Y Koordinate zu einem Longword zusammenfügt.

Außerdem, zu dem Rückgabewert, der ist nicht nur ein Integer, sondern ein LPRESULT, dessen oberes WORD die Zeile und dessen unteres WORD den tatsächlichen Index (nicht die spalte) angibt:
Edit controls: The LOWORD specifies the zero-based index of the character nearest the specified point. This index is relative to the beginning of the control, not the beginning of the line. If the specified point is beyond the last character in the edit control, the return value indicates the last character in the control. The HIWORD specifies the zero-based index of the line that contains the character. For single-line edit controls, this value is zero. The index indicates the line delimiter if the specified point is beyond the last visible character in a line.

Bei mir funktioniert das hier super:

Code: Alles auswählen

i := LOWORD(SendMessage(Memo1.Handle, EM_CHARFROMPOS, 0, MakeLParam(X, Y)));

Gibt den Index des Characters über dem der Cursor hovert

PS: Das ist alles natürlich windows only. Wenn du es cross plattform haben willst würde ich dir Empfehlen TSynEdit zu nehmen, das kann sowas (umrechnen von Koordinaten zu Character positionen und umgekehrt) von haus aus

PPS: ich hab grade mal das ganze mit Perform angeschaut, und mit Perform scheint auch das nicht zu funktionieren, was wenn man da mal in die Doc schaut: Link auch nicht verwunderlich ist. Perform führt nicht die Message auf Systemebene aus, Perform tut so als wäre die Message aufgetreten und ruft den Handler auf. Wird also innerhalb von der LCL behandelt, somit fällt der WinAPI call weg der dir das ergebnis gibt. Also musst du wohl SendMessage benutzen. (Was ja auch sinn ergibt, SendMessage ist ein Windows konzept, also macht es keinen Sinn das auf der Cross Platform abstraktionsebene der LCL zu implementieren)

PPPS: Wenn man nach "delphi EM_CHARFROMPOS" googlet (bzw. habe ge duckduckgo'ed) ist das ersten Ergebnis das hier: Link was die frage beantworetet. (Bei WinAPI fragen lohnt es sich nach delphi zu googlen)

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: TMemo Text per Drag&Drop an Mausposition einfügen

Beitrag von MmVisual »

Dann nehme ich lieber TSynEdit (=memDebugSQL). Da wäre dann gleich ein SQL Hilighter dabei, was mir noch entgegen kommt.

Code: Alles auswählen

procedure TfrmMain.memDebugSQLDragDrop(Sender, Source: TObject; X, Y: Integer);
Var p: TPoint;
begin
  If Source <> tvDatenbank Then Exit;
  If Not Assigned(tvDatenbank.Selected) Then Exit;
  p.x := X;
  p.y := Y;
  memDebugSQL.MoveCaretIgnoreEOL(memDebugSQL.PixelsToLogicalPos(p));
  memDebugSQL.SelText := tvDatenbank.Selected.Text;
end


Dankeschön, hat funktioniert!

VG Markus
EleLa - Elektronik Lagerverwaltung - www.elela.de

Antworten