0

I've created a Delphi VCL app with a single TMemo control, and this is the code I have. I use it to detect Ctrl+somekey. For example, when I press Ctrl+x, it pops up the alert ctrl and the Ctrl+x's effect (cut) was cancelled.

function IsKeyDown(Key: Integer): Boolean;
begin
  Result := (GetAsyncKeyState(Key) and (1 shl 15) > 0);
end;

procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
begin
  if IsKeyDown(VK_CONTROL) then
  begin
    ShowMessage('ctrl');
    Key := #0;
  end;

end;

However, when I changed it a little bit to this:

function IsKeyDown(Key: Integer): Boolean;
begin
  Result := (GetAsyncKeyState(Key) and (1 shl 15) > 0);
end;

procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
begin
  if IsKeyDown(VK_CONTROL) and IsKeyDown(VK_MENU) then
  begin
    ShowMessage('ctrl+alt');
    Key := #0;
  end;

end;

It doesn't work anymore. What I need is to detect combinations like Ctrl+Alt+f. I know I can use a TActionList, but I just want to know why my code doesn't work.

Fajela Tajkiya
  • 629
  • 2
  • 10
  • 4
    Use `OnKeyDown` or `OnKeyUp` instead, which gives you both the actual key pressed plus the modifier keys (Ctrl, Alt, Shift). – Ken White Mar 23 '22 at 02:11
  • @KenWhite By my testing, it seems that in the key down and keep up event handler, it's not able to cancel the key event. Is that true? – Fajela Tajkiya Mar 23 '22 at 13:44
  • No, that's not true. You can set `Key := 0;` to discard (cancel) the key in either event. The key is defined as `var Key: Word` in the procedure definition. – Ken White Mar 23 '22 at 13:51
  • See the answer I just posted. Also, we can't grab your code from somewhere else. All relevant information needs to be here, in the question itself. – Ken White Mar 23 '22 at 14:48

1 Answers1

2

You should use OnKeyDown instead, which provides you with both the key value and the modifier keys. I've demonstrated how to capture both one modifier key and multiple modifier keys in the code below.

uses
  { Needed for virtual key codes in recent Delphi versions. }
  System.UITypes;  
                 

procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word; 
    Shift: TShiftState);
begin
  if (Key = vkX) and ([ssCtrl] = Shift) then
  begin
    Key := 0;
    ShowMessage('Got Ctrl+X');
  end
  else if (Key = vkZ) and ([ssCtrl, ssAlt] = Shift) then
  begin
    Key := 0;
    ShowMessage('Got Ctrl+Alt+Z');
  end;
end; 
Ken White
  • 123,280
  • 14
  • 225
  • 444
  • Thanks for your answer. I tested your code and I found that when I select some text in the TMemo and press Ctrl+x, I get the message `Got Ctrl+X`, but the selection got cut out and disappeared. Seems the statement `Key := 0;` doesn't take effect, right? – Fajela Tajkiya Mar 23 '22 at 15:03
  • It's being handled by a different message (WM_CUT) because it's a menu item on the default context (right-click) menu for the memo control. You'll also need to intercept that message (but that's a separate question that should be in a new post). FYI, there's also a WM_COPY and WM_PASTE message that are used as well, for the Ctrl+C and Ctrl+V key combinations. – Ken White Mar 23 '22 at 15:09