Eigene Texteingabe programmieren, Einfügen funkt nicht, was läuft hier falsch?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
thosch
Beiträge: 324
Registriert: Mo 10. Jul 2017, 20:32

Eigene Texteingabe programmieren, Einfügen funkt nicht, was läuft hier falsch?

Beitrag von thosch »

Hallo,

Ich habe dieses Stück Quellcode. TMyEdit.ExecKeys wird im Hauptprogramm in einer Repeat Schleife aufgerufen, wobei analog der Crt Funktion Readkey genau ein Zeichen (WideChar) an Keys bergeben wird.

Ich kann den String nun normal schreiben, aber nicht korrekt neue Zeichen einfügen.

Wenn ich zum Beispiel "Das war ein Tag" das Wort "toller" zwischen "ein" und "Tag" hinzufügen will, wird das erste Zeichen "t" korrekt eingefügt und das näcste Zeichen an das Ende der Zeichenkette gesetzt.

Ich habe keine Erklärung dafür.

Code: Alles auswählen

//keyboard[] ist Boolean Array und enthält die VK_Codes die hier das Präfix KEY_ haben
//FStrXPos ist die aktuelle Zeichenposition
//CursorX ist die aktuelle Cursorposition, die wird in Pixeln gezählt
//Deshalb FCurorX * FontSize, wobei hier die Breite gemeint ist


procedure TmyEdit.ExecKeys(var Keys: WideString);
var i: integer; wc: WideChar;
begin
  //i := Length(Keys);
  //move(Keys[1],wc,i);
  if keyboard[key_back] then
  begin
    if FStrXPos >= 1 then
    begin
      system.Delete(FLine,FStrXPos-1,1);
      //system.Delete(Keys,FStrXPos-1,1);
      HideCursor;
      CursorLeft;                //FStrXPos nochmals prüfen
      ShowCursor;
      keyboard[key_back] := false;
    end;
    Paint;
  end;
  if keyboard[key_delete] then
  begin
    if FStrXPos >= 1 then
    begin
      system.Delete(FLine,FStrXPos,1);
      //system.Delete(Keys,FStrXPos,1);
      keyboard[key_delete] := false;
    end;
    Paint;
  end;
  if keyboard[key_insert] then begin ToggleInsmode;  keyboard[key_insert] := false; Paint; end else
  if keyboard[key_left] then begin CursorLeft;       keyboard[key_left] := false; Paint; end else
  if keyboard[key_right] then begin CursorRight;     keyboard[key_right] := false; Paint; end else
  if (key_code IN DecNums) or (key_code IN KeyChrs) or (key_code IN NumPads) or (key_code IN OemKeys) or (key_code = Key_Space) then
  //DecNums,KeyChrs,NumPads,OemKeys sind Mengen der KEY_XXX Codes
  if FStrXPos >= Length(FLine) then
  begin
    {if Length(keys) > 0 then }FLine := FLine + Keys;{[Length(Keys)]}
    HideCursor;
    CursorRight;
    ShowCursor;
    Paint;
  end
  else
  if FInsmode then begin
    
    system.Insert(Keys,FLine,FStrXPos);
    HideCursor;
    CursorRight;
    
    ShowCursor;
    Paint;
  end;
  //for i:=0 to 255 do keyboard[i] := false;
end;

procedure TmyEdit.CursorLeft;
begin
  if FStrXPos > 1 then Dec(FStrXPos);
  if FCursorX > 0 then
  begin
    Dec(FCursorX,FontSize);
    if FCursorX < 0 then FCursorX := 0;
  end;
end;

procedure TMyEdit.CursorRight;
begin
  if FStrXPos <= Length(FLine) then
  begin
    FStrXPos := FStrXPos + 1;            //Aktuelle Stringposition
    FCursorX := FCursorX + FontSize;     //Aktuelle Cursorposition
  end;
end;

Code: Alles auswählen

var
  LineStr: WideString;
  ChrCode: WideString;  //Weil myKeypressed Rückgabetyp WideString, vorher String aber liest Unicode

  LineStr := ''; ChrCode := '';
  Input := TMyEdit.Create(nil);
  
  Input.BoundsRect := Rect(20,20, 20*DefaultFontSize, DefaultFontSize + 20);
  //Ich verwende TFPCustomCanvas aus FCLImage zur Grafikausgabe
  //habe mir dazu eigenes Canvasobjekt abgeleitet und BoundsRecht entspricht ClipRect von TFPCustomCanvas
  
  Input.Paint;
  
  repeat


     //LineStr := myReadKey;

     Input.ShowCursor;

     if myKeypressed then
     begin
       ChrCode := myReadKey; //RückgabeTyp bisher WideString

       LineStr := ChrCode;   //nur jeweils ein Zeichen, String wird in Input.ExecKeys gebildet
       
       Input.ExecKeys(LineStr);
       Input.printLengthChrsToXY(0,0);  //eine Testroutine zum Debuggen
     end; { von visKeypressed }
     
  until keyboard[key_escape];
Kenn von Euch jemand helfen?

Will so eine Eingabe mal selber schreiben. Ist ja supere dass Lazarus das alles wunderbar kann, aber irgendjemand musste das ja auch mal so programmieren wie ich das jetzt tue.

.

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Eigene Texteingabe programmieren, Einfügen funkt nicht, was läuft hier falsch?

Beitrag von six1 »

...kurz überflogen:
Nach jeder Eingabe wird CursorLeft; ausgeführt.
Eine Eingabe und tschwups ist der Cursor wieder links.
Gruß, Michael

thosch
Beiträge: 324
Registriert: Mo 10. Jul 2017, 20:32

Re: Eigene Texteingabe programmieren, Einfügen funkt nicht, was läuft hier falsch?

Beitrag von thosch »

Müsste meine FStrXPos dann nicht auf den Anfang springen? Wenn ich aber Zeichen einfügen will wird FStrXPos bis auf Stringlänge erhöht, obwohl ich doch IF Anweisungen habe, die prüfen, ob "Entf" oder "Backsp" gedrückt ist.

Wenn ich also ein Zeichen eingebe werden diese Tasten nicht gedrückt und ich prüfe doch auch, ob ich eines der darstellbaren Zeichen gedrückt habe. Da dürfte doch nach meinem bisherigen Verständnis FStrXPos auch nur dieses eine Mal inkrementiert werden und nicht bis zum Stringende, wie es unerwünschter Weise aber passiert.


Das Zeichen, das ich eingegeben habe, wird in der myReadKey Funktion sofort wieder false gesetzt.

Code: Alles auswählen

function myReadKey:widestring;
begin
        result:='';


        if (keyboard[key_a]) and (not doubleKeyboard[key_a]) then begin
                key_code:=key_a;
                if keyboard[KEY_LSHIFT] or keyboard[KEY_RSHIFT] then result:='A' else result:='a';
                doubleKeyboard[key_a]:=true;
                exit;
        end;
        if not keyboard[key_a] then doubleKeyboard[key_a]:=false;



        if (keyboard[key_b]) and (not doubleKeyboard[key_b]) then begin
                key_code:=key_b;
                if keyboard[KEY_LSHIFT] or keyboard[KEY_RSHIFT] then result:='B' else result:='b';
                doubleKeyboard[key_b]:=true;
                exit;
        end;
        if not keyboard[key_b] then doubleKeyboard[key_b]:=false;



        if (keyboard[key_c]) and (not doubleKeyboard[key_c]) then begin
                key_code:=key_c;
                if keyboard[KEY_LSHIFT] or keyboard[KEY_RSHIFT] then result:='C' else result:='c';
                doubleKeyboard[key_c]:=true;
                exit;
        end;
        if not keyboard[key_c] then doubleKeyboard[key_c]:=false;


...
DoubleKeyboard ist ein Hilfsarray für besseres Handling.

keyboard[key_xxx] wird in der Message Hauptschleife auf false gesetzt.

Code: Alles auswählen


        if (theMessage=wm_keydown) or (theMessage=wm_syskeydown) then begin
                                                keyboard[loword(wPar)]:=true;
                                      end;
        if (theMessage=wm_keyup)or (theMessage=wm_syskeyup)   then begin
                                            keyboard[loword(wPar)]:=false;
                                      end;

 

Antworten