Home > OS >  Why the shortcut doesn't work in my Delphi program?
Why the shortcut doesn't work in my Delphi program?

Time:11-01

I've written a program in Delphi 10.4. The main part of the UI is just a TMemo. When the user types something in it, the app will automatically copy the text in the TMemo to clipboard. It looks like this:

enter image description here

This auto copy part works well. However, I also want to let the user change dark theme or light theme by a shortcut. I enabled a dark theme and a light theme.

enter image description here

The code looks like this:

unit Unit1;

interface

uses
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
    System.Classes, Vcl.Graphics,
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Clipbrd, System.Actions,
    Vcl.ActnList, Vcl.Themes;

type
    TForm1 = class(TForm)
        txt: TMemo;
        ActionList1: TActionList;
        act_change_theme: TAction;
        procedure txtChange(Sender: TObject);
        procedure act_change_themeExecute(Sender: TObject);
        procedure FormCreate(Sender: TObject);
    private
        { Private declarations }
    public
        { Public declarations }
    end;

var
    Form1: TForm1;

var
    is_dark: Boolean;

implementation

{$R *.dfm}

function ShortCut(Key: Word; Shift: TShiftState): TShortCut;
begin
    Result := 0;
    if HiByte(Key) <> 0 then
        Exit; // if Key is national character then it can't be used as shortcut
    Result := Key;
    if ssShift in Shift then
        Inc(Result, scShift); // this is identical to " " scShift
    if ssCtrl in Shift then
        Inc(Result, scCtrl);
    if ssAlt in Shift then
        Inc(Result, scAlt);
end;

procedure TForm1.act_change_themeExecute(Sender: TObject);
begin
    if is_dark then
    begin
        TStyleManager.TrySetStyle('Windows', false);
        is_dark := false;
    end
    else
    begin
        TStyleManager.TrySetStyle('Carbon', false);
        is_dark := true;
    end;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
    is_dark := false;
    act_change_theme.ShortCut := ShortCut(Word('d'), [ssCtrl]);
end;

procedure TForm1.txtChange(Sender: TObject);
begin
    try
        Clipboard.AsText := txt.Lines.GetText;
    except
        on E: Exception do
    end;

end;

end.

However, when I press ctrl d, nothing happened. I tried to debug it and I found that ctrl d never triggers the action's shortcut. Why this happened? How to fix it? I've used the shortcut function in the past and it worked.

CodePudding user response:

Try Word('D'), or the constant vkD, instead of Word('d'). Shortcuts use virtual key codes, and letters are represented as virtual keys using their capital values. Typing an Uppercase or Lowercase letter into an edit control uses the same virtual key, it is the current shift state that determines the case of the letter when the key is translated into a text character.

Also note that the VCL has its own ShortCut() function (and also TextToShortCut()) in the Vcl.Menus unit for creating TShortCut values, so you don't need to write your own function.

See Representing Keys and Shortcuts, especially Representing Shortcuts as Instances of TShortCut.

Also, your TAction is clearly placed on the Form at design-time, so you should simply assign its ShortCut using the Object Inspector, rather than in code. Then these details would be handled for you automatically by the framework.

  • Related