为什么快捷方式在我的 Delphi 程序中不起作用?
Why the shortcut doesn't work in my Delphi program?
我在 Delphi 10.4 中编写了一个程序。 UI 的主要部分只是一个 TMemo。当用户在其中输入内容时,应用程序会自动将 TMemo 中的文本复制到剪贴板。它看起来像这样:
这个自动复制部分效果很好。但是,我还想让用户通过快捷方式更改深色主题或浅色主题。我启用了深色主题和浅色主题。
代码如下所示:
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.
然而,当我按下 ctrl+d 时,没有任何反应。我尝试调试它,发现 ctrl+d 永远不会触发操作的快捷方式。为什么会这样?如何解决?我以前用过快捷键功能,很管用。
尝试 Word('D')
,或常量 vkD
,而不是 Word('d')
。快捷方式使用虚拟键码,字母使用大写值表示为虚拟键。在编辑控件中键入大写或小写字母使用相同的虚拟键,当键转换为文本字符时,当前的 shift 状态决定字母的大小写。
另请注意,VCL 在 Vcl.Menus
单元中有自己的 ShortCut()
function (and also TextToShortCut()
) 用于创建 TShortCut
值,因此您无需编写自己的函数。
参见 Representing Keys and Shortcuts, especially Representing Shortcuts as Instances of TShortCut。
此外,您的 TAction
显然在设计时放置在窗体上,因此您应该使用对象检查器简单地分配它的 ShortCut
,而不是在代码中。然后这些细节将由框架自动为您处理。
我在 Delphi 10.4 中编写了一个程序。 UI 的主要部分只是一个 TMemo。当用户在其中输入内容时,应用程序会自动将 TMemo 中的文本复制到剪贴板。它看起来像这样:
这个自动复制部分效果很好。但是,我还想让用户通过快捷方式更改深色主题或浅色主题。我启用了深色主题和浅色主题。
代码如下所示:
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.
然而,当我按下 ctrl+d 时,没有任何反应。我尝试调试它,发现 ctrl+d 永远不会触发操作的快捷方式。为什么会这样?如何解决?我以前用过快捷键功能,很管用。
尝试 Word('D')
,或常量 vkD
,而不是 Word('d')
。快捷方式使用虚拟键码,字母使用大写值表示为虚拟键。在编辑控件中键入大写或小写字母使用相同的虚拟键,当键转换为文本字符时,当前的 shift 状态决定字母的大小写。
另请注意,VCL 在 Vcl.Menus
单元中有自己的 ShortCut()
function (and also TextToShortCut()
) 用于创建 TShortCut
值,因此您无需编写自己的函数。
参见 Representing Keys and Shortcuts, especially Representing Shortcuts as Instances of TShortCut。
此外,您的 TAction
显然在设计时放置在窗体上,因此您应该使用对象检查器简单地分配它的 ShortCut
,而不是在代码中。然后这些细节将由框架自动为您处理。