Tastendruck per Message an TEdit senden

Rund um die LCL und andere Komponenten
watte
Beiträge: 13
Registriert: Di 3. Aug 2010, 20:57

Tastendruck per Message an TEdit senden

Beitrag von watte »

Hallo Freunde,

ich habe ein kleines Problem. Ich möchte den Text in einem Eingabefeld TEdit ( LCL ) mit Hilfe von z.B. KeyDown-Messages verändern. Für mein Projekt habe ich keine Tastatur. Nur eine Maus. Also habe ich jede Menge Buttons mit Buchstaben erstellt und beim Klick soll der entsprechende Buchstabe im Text-Feld erscheinen.
Ich habe es bereits mit ~.Perform und ~.Dispatch probiert. Leider ändert sich nichts am Eingabefeld. Ich hab schon so viel getüftelt, debuggt und probiert. Ich weiß nicht woran es liegt.

Ich benutze Linux und auch das Projekt soll später im Linux laufen. Möglicherweise muss man dort etwas anders machen?.

Hat jemand von Euch eine Idee, wie ich das genau machen muss?

DiBo33
Beiträge: 334
Registriert: Do 11. Okt 2007, 18:01

Re: Tastendruck per Message an TEdit senden

Beitrag von DiBo33 »

Ändere doch einfach den Text

Code: Alles auswählen

Edit.Text := Edit.Text + Eingabe;

watte
Beiträge: 13
Registriert: Di 3. Aug 2010, 20:57

Re: Tastendruck per Message an TEdit senden

Beitrag von watte »

Die Idee hatte ich schon.
Das Eingabe-Feld hat aber alle anderen Eigenschaften noch. Und somit kann auch ein Teil im Wort oder Text markiert sein. Text=Text + Zeichen fügt aber nur ein Zeichen hinten an. Wenn der Cursor mitten im Wort steht (z.B. per Mausklick dahin gesetzt), muss das Zeichen dort eingefügt werden.
Ideal wäre also eine Tasten-Message.

Im Delphi klappt das mit Eingabefeld.Perform( WM_KEYDOWN, Zeichen, 0). Im Lazarus funktioniert es nicht
Ich habe zwischenzeitlich auch mal Lazarus unter Windows probiert. Da funktioniert es auch nicht. Es schein also nicht am Betriebssystem zu liegen.

DiBo33
Beiträge: 334
Registriert: Do 11. Okt 2007, 18:01

Re: Tastendruck per Message an TEdit senden

Beitrag von DiBo33 »

Nimm SelText, dann ist es egal ob was markiert ist und wo der Cursor steht

Code: Alles auswählen

Edit1.SelText := Taste;
Edit1.SetFocus;

watte
Beiträge: 13
Registriert: Di 3. Aug 2010, 20:57

Re: Tastendruck per Message an TEdit senden

Beitrag von watte »

Danke für den Tipp.

Aber auf diese Weise muss ich ja das halbe Edit-Feld neu programmieren. Was ist mit den Tasten Cursor links und rechts, Backspace, Delete usw.... ;) Das brauch ich auch noch.
Es muss doch eine Möglichkeit mit Messages geben. Schließlich bekommt das Edit-Feld die normalen Tastendrücke auch per Message. Man muss wahrscheinlich nur vorher etwas anderes Senden, oder es funktioniert ganz und gar über eine andere Message?.

Kennt sich jemand mit Lazarus intern oder Messages aus ??

carli
Beiträge: 657
Registriert: Sa 9. Jan 2010, 17:32
OS, Lazarus, FPC: Linux 2.6.x, SVN-Lazarus, FPC 2.4.0-2
CPU-Target: 64Bit

Re: Tastendruck per Message an TEdit senden

Beitrag von carli »

Es gibt unter Linux schon gewisse Hilfsprogramme, die eine klickbare Tastatur zeichnen.
Es gibt 2 Möglichkeiten, eine Tastatur vorzugaukeln:
1. der LCL (das einfachere) WM_-Events feuern
2. Mit X11 Tastendrücke feuern (würde auch mit allen anderen Programmen dann gehen)

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Tastendruck per Message an TEdit senden

Beitrag von Socke »

Ich habe zwar nicht wirklich viel Ahnung von Messages, aber versuch mal bitte Folgendes:

Code: Alles auswählen

uses lmessages; // oder so ähnlich
Eingabefeld.Perform(LM_KEYDOWN, Zeichen, 0);
Eingabefeld.Perform(LM_KEYUP, Zeichen, 0);
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

watte
Beiträge: 13
Registriert: Di 3. Aug 2010, 20:57

Re: Tastendruck per Message an TEdit senden

Beitrag von watte »

Danke für den Tipp, socke!

Aber wie ich oben bereits geschrieben habe, bringen weder Perform noch Dispatch irgend etwas.
Ich habe auch schon den normalen Ablauf (Tastendruck über Tastatur) probiert. Wenn die Behandlung der Messages LM_KEY~ oder CN_KEY~ stattfindet, ist das Zeichen bereits im Eingabefeld angekommen. Das wird irgendwo anders bereits behandelt. :(

Beim Anhängen über Text:=Text + Zeichen oder SelText:=Zeichen, werden die internen Werte für SelStart, SelLength sowas von durcheinander gewürfelt, das man diese Werte nicht mehr zum feststellen der Cursorposition und des evtl. selektierten Bereiches nutzen kann. Es ist einfach schrecklich! :shock:

DiBo33
Beiträge: 334
Registriert: Do 11. Okt 2007, 18:01

Re: Tastendruck per Message an TEdit senden

Beitrag von DiBo33 »

So schlimm ist das doch gar nicht, du gibst allen Buttons als Tag den ASCI-Code der gew. Taste und als OnClick die Prozedur BtnClick.

Code: Alles auswählen

procedure TForm1.BtnClick(Sender: TObject);
var
  pos: integer;
begin
  pos := Edit1.SelStart;
  with TButton(Sender) do begin
    case Tag of
      8: begin  // BckSp
        dec(pos);
        Edit1.SelStart := pos;
        Edit1.SelLength := 1;
        Edit1.SelText := '';
      end;
      37: begin // Left
        dec(pos);
      end;
      39: begin // Right
        inc(pos);
      end;
      36: begin // Pos1
        pos := 0;
      end;
      35: begin // Ende
        pos := Length(Edit1.Text);
      end;
      else begin
        Edit1.SelText := chr(Tag);
        inc(pos);
      end;
    end;
  end;
  Edit1.SetFocus;
  Edit1.SelLength := 0;
  Edit1.SelStart := pos;
end;

watte
Beiträge: 13
Registriert: Di 3. Aug 2010, 20:57

Re: Tastendruck per Message an TEdit senden

Beitrag von watte »

Vielen Dank DiBo33!

Allerdings funktioniert es bei mir nicht sauber. Ich kann zwar mit dem Cursor hin und her. Aber wenn ich dann (Cursor weiter vorn) wieder Zeichen drücke, wird alles hinterm Cursor (obwohl nicht selektiert) überschrieben. :( Auch wenn ich den Cursor mit Maus weiter vorn im Wort einsetze, wird alles hinterm Cursor beim nächsten Zeichen überschrieben.

Möglicherweise ist es ja nur bei mir so, oder?

DiBo33
Beiträge: 334
Registriert: Do 11. Okt 2007, 18:01

Re: Tastendruck per Message an TEdit senden

Beitrag von DiBo33 »

Gerade mal ein TestProg geschrieben, bei mir wird nix überschrieben, alle Buttons reagieren wie beim Tastendruck.

Laz:0.9.31.29983M, FPC:2.4.2, i386-linux-gtk 2, Ubuntu10.10

watte
Beiträge: 13
Registriert: Di 3. Aug 2010, 20:57

Re: Tastendruck per Message an TEdit senden

Beitrag von watte »

Ich habe 0.9.30 auf Ubuntu 10.10, 64bit.

Aber daran liegt es nicht. Ich habe es jetzt in Windows XP 32bit mit 0.9.28 (anderer PC) und auf Ubuntu 10.10 Netbook i386 mit 0.9.29 getestet. Das gleiche Problem! Der Selektiert immer (ohne es anzuzeigen) von Cursorposition bis Ende Text, beim nächsten Zeichen: ..alles ab Cursor überschieben...
Gestern hatte ich auch noch ein 0.9.31 auf meinem PC (Ubuntu 10.10, 64bit), habe es heute aber durch das 0.9.30 von SourceForge ersetzt. Dachte mit nem Release liegt man immer gut.
Mit dem 0.9.31er hatte ich auch schon die Spinnerei mit dem intern selektierten Zeichen.

Da war ja auch der Grund warum ich eine Message senden wollte. Damit die internen Routinen den Text modifizieren... :(

DiBo33
Beiträge: 334
Registriert: Do 11. Okt 2007, 18:01

Re: Tastendruck per Message an TEdit senden

Beitrag von DiBo33 »

Hast du auch am Ende der Procedure SelLength auf 0 gesetzt?

SetFocus, SelStart und SelLength müssen genau in der Reihenfolge aufgefufen werden wie ich es bei mir gemacht habe.

SetFocus, fokusiert das Eingabefeld und ruft SelAll auf.

Edit: Setze auch mal AutoSelect und AutoSize des Edits auf false.

watte
Beiträge: 13
Registriert: Di 3. Aug 2010, 20:57

Re: Tastendruck per Message an TEdit senden

Beitrag von watte »

Ja, ich habe Deinen Code! - Nichts dran verändert!

Ich habe aber zwischenzeitlich noch etwas herausgefunden...:

Wenn:
der Cursor an der 2. Position steht, wird 1 Zeichen überschrieben (nichts selektiert dargestellt)
der Cursor an der 3. Position steht, wird 2 Zeichen überschrieben (nichts selektiert dargestellt)
der Cursor an der 4. Position steht, wird 3 Zeichen überschrieben (nichts selektiert dargestellt)
usw.

Ich teste immer "12345678". Dann bin ich bisher immer zwischen 4 und 5 gegangen und habe ein Zeichen gedrückt. Dann wurde immer "5678" durch das eingegebene Zeichen ersetzt.
Heute habe ich das mit AutoSelect und AutoSize hinzugefügt und getestet. Bin, durch Zufall, mit den Cursor an die Position zwischen 2 und 3 gegangen und es wurde nur 3 und 4 => "34" durch das Zeichen ersetzt:
Vorher "12|345678" => "z" klicken => danach "12z|5678" ( | soll symbolisiert den Cursor ).

watte
Beiträge: 13
Registriert: Di 3. Aug 2010, 20:57

Re: Tastendruck per Message an TEdit senden

Beitrag von watte »

Ich habe gerade festgestellt, dass TEdit funktioniert. Aber Comboboxen funktionieren nicht.

Ich hänge mal ein wenig Quellcode an, falls jemand probieren will...

-> einfach ein neues Projekt erstellen und dann meine Unit1 benutzen.
-> starten...


- A,B,C,D,E,F,G,H über Buttons Klicken
ComboBox zeigt "ABCDEFGH"
- Cursor an Position zwischen C und D stellen
ComboBox zeigt "ABC|DEFGH" ( | ist Cursor )
- Dann einen Button Klicken ( ich nehme mal "U" )
ComboBox zeigt bei mir "ABCU|GH" ( | ist Cursor ) 3 Zeichen werden überschrieben. Könnte das ein BUG sein?

Code: Alles auswählen

unit Unit1; 
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { private declarations }
    Combo: TComboBox;
  public
    { public declarations }
  end; 
 
var
  Form1: TForm1; 
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  if Sender is TButton then
  begin
    Combo.SelText:=chr( TButton(Sender).Tag );
    Combo.SelStart:=Length( Combo.Text );
    Combo.SelLength:=0;
  end;
end;
 
procedure TForm1.FormCreate(Sender: TObject);
var
  x,y: integer;
  btn: TButton;
  b: Byte;
begin
  Combo:=TComboBox.Create(Self);
  Combo.Left:=4;
  Combo.Top:=4;
  Combo.Width:=200;
  Self.InsertControl( Combo );
  //
  for y:=0 to 2 do
    for x:=0 to 7 do
    begin
      b:=65+(y*8)+x;
      btn:=TButton.Create(Self);
      btn.Tag:=b;
      btn.Caption:=chr(b);
      btn.OnClick:=@Button1Click;
      btn.Width:=24;
      btn.Height:=24;
      btn.Left:=(x*28)+4;
      btn.Top:=(y*28)+50;
      Self.InsertControl(btn);
    end;
 
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
var
  ctl: TControl;
  l: integer;
begin
  for l:=0 to ControlCount-1 do
  begin
    ctl:=Controls[l];
    if (ctl<>nil) then ctl.Free;
  end;
end;
 
end.

Antworten