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:
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:
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;
procedure TWinControl.KeyPress(var Key: char);
begin
if Assigned(FOnKeyPress) then FOnKeyPress(Self, Key);
end;
procedure TWinControl.KeyUp(var Key: Word; Shift : TShiftState);
begin
if Assigned(FOnKeyUp) then FOnKeyUp(Self, Key, Shift);
end;
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.