TWebEdit.OnKeyPress not accepting Key change other than #0

An OnKeyPress handler for a TWebEdit control should allow to change the character the user entered, like so:

procedure TForm1.WebEdit1KeyPress(Sender: TObject; var Key: Char);
begin
 if Key='a' then Key := #0 // eat all 'a's
 else Key := 'b'           // make all others 'b'
end;

This is:

  • When the user enters an 'a', this should be supressed. This works as expected.
  • When the user enters any other character, this should be changed to 'b', which does not work. Instead, the entered character shows up in the edit.

Here is a temporary user side fix until it gets fixed by TMS:

procedure TForm1.WebEdit1KeyPress(Sender: TObject; var Key: Char);
Var
 KeyStr,Txt : String;
 SelStart,SelLen : Integer;
Begin
 If WebEdit1.ReadOnly or (Length(WebEdit1.Text)>=WebEdit1.MaxLength) then
  Begin
   Key := #0;
   Exit;
  End;

  // Do something with Key. May even return a string
  KeyStr := MyEvaluationFunction(Key);

 If KeyStr='' then Key := #0
 Else if (Key<>KeyStr[1]) or (Length(KeyStr)>1) then
  Begin
   Key := #0;
   Txt := WebEdit1.Text;
   SelStart := WebEdit1.SelStart;
   WebEdit1.Text := Copy(Txt, 1, SelStart) + KeyStr + Copy(Txt, SelStart + WebEdit1.SelLength + 1, MaxInt);
   WebEdit1.SelStart := SelStart + Length(KeyStr);
   WebEdit1.SelLength := 0;
  End;
End;

It is a JavaScript limitation that for the keypress event, the key can't be programmatically changed. So you need indeed to resort to inserting the key directly in the edit control.

Oha, this is a real shortcoming then. Of course this is to all our best...

That having realized, I elaborated a little further on a user side "bug" fix. The previous version had an issue with scrolling the text when the input area overflows, but I found a good enough solution for that. It's not perfect, but does it for me. You guys may investigate further into some edge cases regarding the scrolling and provide an official fix.

Procedure TForm1.WebEdit1KeyPress(Sender : TObject; Var Key : Char);
Var
 KeyStr,Txt   : String;
 SelStart     : Integer;
 InputElement : TJSHTMLInputElement;
 Edit         : TWebEdit;
Begin
 Edit := Sender as TWebEdit;
 If Edit.ReadOnly or (Length(Edit.Text)>=Edit.MaxLength) then
  Begin
   Key := #0;
   Exit;
  End;

 // Do something with the character in Key. May even return a string
 KeyStr := MyKeyCharFunc(Key);

 If KeyStr='' then Key := #0
 Else if (Key<>KeyStr[1]) or (Length(KeyStr)>1) then
  Begin
   // Fix for broken function TControl.HandleDoKeyPress(Event: TJSKeyBoardEvent): Boolean
   // See: https://support.tmssoftware.com/t/twebedit-onkeypress-not-accepting-key-change-other-than-0/24069/2
   // According to TMS support, this is a browser/jacascript shortcoming, aka security feature
   Key := #0;
   Txt := Edit.Text;
   SelStart := Edit.SelStart;
   Edit.Text := Copy(Txt, 1, SelStart) + KeyStr + Copy(Txt, SelStart + Edit.SelLength + 1, MaxInt);
   SelStart := SelStart + Length(KeyStr);
   Edit.SelStart := SelStart;
   Edit.SelLength := 0;

   // Access the underlying input element
   InputElement := TJSHTMLInputElement(Edit.ElementHandle);

   // Scroll text to the left, if necessary
   {$IFDEF PAS2JS}
    // Compiler honey
    If InputElement=Nil then;
    // Scroll text left
    ASM
     InputElement.scrollLeft = InputElement.scrollWidth;
    END;
   {$ENDIF}
  End
 // Else default key processing
End;
1 Like