我有一个有趣的问题经常被问到,但我发现他们给出的解决方案不起作用......
我在Win 7上使用Delphi XE3。
我一直都知道在FormKeyDown或FormKeyPress中,您可以将Key设置为0或#0以指示键已被处理(因此,对于无效按键,它不应发出“ding”声音。)< / p>
我做了以下事情:
我成功检测到Alt + T并将Key设置为0. Form OnKeyPress和Form OnKeyUp不会触发。这对我来说并不奇怪,因为我把Key设置为0。
令人惊讶的是,它在OnKeyDown完成后仍会发出“叮”声。
我怎么能阻止它这样做呢?
在某些调试中,似乎有一条消息WM_SYSKEYDOWN导致这种情况发生。
谢谢!
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (key=ord('T')) and (shift=[ssAlt]) then
key:=0;
end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
showmessage('keypress');
end;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
showmessage('keyup');
end;
end.
object Form1: TForm1
Left = 267
Top = 163
Caption = 'Form1'
ClientHeight = 565
ClientWidth = 654
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
KeyPreview = True
OldCreateOrder = False
Position = poScreenCenter
ShowHint = True
OnKeyDown = FormKeyDown
OnKeyPress = FormKeyPress
OnKeyUp = FormKeyUp
PixelsPerInch = 96
TextHeight = 13
end
答案 0 :(得分:2)
从WM_SYSCHAR
消息转换后,从已发布的队列中删除WM_SYSKEYDOWN
消息(因此称为'ding')。
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
Msg: TMsg;
begin
if (key=ord('T')) and (shift=[ssAlt]) then begin
PeekMessage(Msg, 0, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE);
key:=0;
end;
end;
您无法在表单级别处理WM_SYSCHAR
(除非将其发布到表单本身),因为VCL没有“SysKeyPreview”功能。但是,如果您不希望它“T”不是“T”,并且这与应用程序中的所有/大多数表单相关,您可能会发现在应用程序级别处理消息更方便。这也不需要设置KeyPreview
。
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
begin
if Msg.message = WM_SYSCHAR then begin
if Char(Msg.wParam) in ['f','F','g','t','T'] then
Handled := True;
end;
end;
注意,如果您对这些密钥没有任何特殊处理,您最好放弃“叮”,否则用户将缺乏这些密钥组合不起任何作用的反馈。
答案 1 :(得分:0)
出于向后兼容的原因,我不得不使我的小巧,简单 工具应用程序以响应“ ALT-N”,“ ALT-S”,“ ALT-E”和“ ALT-D”按键。 如果我在FormKeyDown中处理这些问题,它会发出令人讨厌的“哔”或“叮”声。 问题是通过使用FormShortCut事件解决的。
procedure TForm1.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
{Instead of FormKeyDown event, use FormShortCut event.
Form's KeyPreview can be set to False or True.}
begin
if (GetKeyState(VK_MENU) < 0) then
case Msg.CharCode of
Ord('N'): Label1.Caption := 'ALT-N';
Ord('S'): Label1.Caption := 'ALT-S';
Ord('E'): Label1.Caption := 'ALT-E';
Ord('D'): Label1.Caption := 'ALT-D';
end
end;