Forum > CustomDrawn

[SOLVED] TEdit key press events in customdrawn LCLWidgetType

<< < (2/3) > >>

zeljko:

--- Quote from: lagprogramming on April 13, 2023, 05:03:06 pm ---When running an empty form in QT, are both OnFormUTF8KeyPress and OnFormKeyPress triggered when pressing a key? If the answer is yes, is OnFormUTF8KeyPress triggered before OnFormKeyPress?

--- End quote ---

1.Yes
2.Yes

Applies to Qt, Qt5 and Qt6 widgetsets.

lagprogramming:
Follow up to commit fa8f6ffa: LCL: Make AUTF8Char a var parameter in function LCLSendUTF8KeyPress. Issue...

lcl/interfaces/customdrawn/customdrawnprivate.pas has procedure CallbackKeyChar(AWindowHandle: TCDForm; AKeyData: Word; AChar: TUTF8Char);
The following code fixes the key events:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure CallbackKeyChar(AWindowHandle: TCDForm; AKeyData: Word; AChar: TUTF8Char);var  lTarget: TWinControl;  lCharCode: Word;begin  lTarget := AWindowHandle.GetFocusedControl();  {$ifdef VerboseCDEvents}   DebugLn(Format('CallbackKeyChar FocusedControl=%s:%s', [lTarget.Name, lTarget.ClassName]));  {$endif}   if lTarget = nil then Exit; // Fixes a crash  if Length(AChar) = 1 then    lCharCode := Byte(AChar[1])  else    lCharCode := 0;   if AChar<>'' then LCLSendUTF8KeyPress(lTarget, AChar, False);  if lCharCode <> 0 then LCLSendCharEvent(lTarget, lCharCode, AKeyData, True, False, True);   // If this is a interface control, send the message to the main LCL control too  if IsIntfControl(lTarget) then  begin    lTarget := lTarget.Parent;    if AChar<>'' then LCLSendUTF8KeyPress(lTarget, AChar, False);    if lCharCode <> 0 then LCLSendCharEvent(lTarget, lCharCode, AKeyData, True, False, True);  end;end;But before providing a patch I have a question. lcl/include/wincontrol.inc contains the following procedures:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TWinControl.KeyDown(var Key: Word; Shift: TShiftState);begin  if Assigned(FOnKeyDown) then FOnKeyDown(Self, Key, Shift);  if Key <> 0 then    DoCallKeyEventHandler(chtOnKeyDown, Key, Shift);end;
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TWinControl.KeyPress(var Key: char);begin  if Assigned(FOnKeyPress) then FOnKeyPress(Self, Key);end;
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TWinControl.KeyUp(var Key: Word; Shift : TShiftState);begin  if Assigned(FOnKeyUp) then FOnKeyUp(Self, Key, Shift);end;
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TWinControl.UTF8KeyPress(var UTF8Key: TUTF8Char);begin  if Assigned(FOnUTF8KeyPress) then FOnUTF8KeyPress(Self, UTF8Key);end;   Regarding the modified procedure CallbackKeyChar, before the comment line "// If this is a interface control, send the message to the main LCL control too" the value of AChar can be modified at line "if AChar<>'' then LCLSendUTF8KeyPress(lTarget, AChar, False);". Also the value of lCharCode can be modified too at line "if lCharCode <> 0 then LCLSendCharEvent(lTarget, lCharCode, AKeyData, True, False, True);".
   After the comment line the message is sent to the main LCL control only if AChar<>'' for LCLSendUTF8KeyPress and only if lCharCode <> 0 for LCLSendCharEvent. Is this the right behavior? This means that you can cancel sending the messages further to the LCL controls by modifying in one of the OnKey* events the value of AChar to '' or the value of lCharCode to 0. Look at the content of procedure TWinControl.KeyDown(var Key: Word; Shift: TShiftState); as it has that "if Key <> 0 then DoCallKeyEventHandler(chtOnKeyDown, Key, Shift);" line. Also, function TWinControl.DoKeyPress(var Message : TLMKey): Boolean; has an "if Char(CharCode) = #0 then Exit;" line.

lagprogramming:
The following patch fixes the bug.

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---diff --git a/lcl/interfaces/customdrawn/customdrawnprivate.pas b/lcl/interfaces/customdrawn/customdrawnprivate.pasindex bcf33be060..7a95139583 100644--- a/lcl/interfaces/customdrawn/customdrawnprivate.pas+++ b/lcl/interfaces/customdrawn/customdrawnprivate.pas@@ -288,7 +288,7 @@ end; procedure CallbackKeyChar(AWindowHandle: TCDForm; AKeyData: Word; AChar: TUTF8Char); var   lTarget: TWinControl;-  lCharCode: Word = 0;+  lCharCode: Word; begin   lTarget := AWindowHandle.GetFocusedControl();   {$ifdef VerboseCDEvents}@@ -296,17 +296,20 @@ begin   {$endif}    if lTarget = nil then Exit; // Fixes a crash-  if Length(AChar) = 1 then lCharCode := Word(AChar[1]);+  if Length(AChar) = 1 then+    lCharCode := Byte(AChar[1])+  else+    lCharCode:=0; -//  if lCharCode <> 0 then LCLSendCharEvent(lTarget, lCharCode, AKeyData, True, False, True);-  LCLSendUTF8KeyPress(lTarget, AChar, False);+  if AChar<>'' then LCLSendUTF8KeyPress(lTarget, AChar, False);+  if lCharCode <> 0 then LCLSendCharEvent(lTarget, lCharCode, AKeyData, True, False, True);    // If this is a interface control, send the message to the main LCL control too   if IsIntfControl(lTarget) then   begin     lTarget := lTarget.Parent;-//    if lCharCode <> 0 then LCLSendCharEvent(lTarget, lCharCode, AKeyData, True, False, True);-    LCLSendUTF8KeyPress(lTarget, AChar, False);+    if AChar<>'' then LCLSendUTF8KeyPress(lTarget, AChar, False);+    if lCharCode <> 0 then LCLSendCharEvent(lTarget, lCharCode, AKeyData, True, False, True);   end; end;

AlexTP:
Posted to bugtracker,
https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/40221

Josh:
Hi

Am i missing something, maybe its optimization.

You remove =0 in  lCharCode: Word = 0;

then set it to zero in
 if Length(AChar) = 1 then
    lCharCode := Byte(AChar[1])
  else
    lCharCode:=0;

Also why casting a word to byte?

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version