Delphi对键盘控制的两个bug?(100分)

  • 主题发起人 主题发起人 凝铁衣
  • 开始时间 开始时间

凝铁衣

Unregistered / Unconfirmed
GUEST, unregistred user!
昨天我发现Delphi两个令人费解的问题(delphi4/5):
新建一个应用,设置mainform的keypreview:=true,
编写formkeydown事件:
if key = vk_tab then showmessage('tab key down');//检测是否按下了TAB键
编写formkeyup事件:
if key = vk_lwin then showmessage('lwin key down');//检测是否按了左边的win95键
结果不管我按TAB键还是左边的win95键都不触发上面的两个事件,而用按其它任意键均能
正常触发以上两个事件,难道这是delphi的bug?
 
if key = vk_tab then showmessage('tab key down')改为
if ssalt in shift then
showmessage('alt is down');
事件不变!
呵,剩下的这个不知道!关注!
 
我说的是vk_tab不是指alt键,我发现tab键可以触发keyup事件,但不会触发keydown事件,
而win95键恰巧相反,它只触发keydown事件,而不会触发keyup事件
 
不是bug,你说的对,就是这样的!
 
我觉得是系统设定的吧1
 
可以为什么要这样呢?
 
:(,不知道!
 
不知道这是不是属于特殊键即(控制)键的例子。。。
 
这个问题是这样的:

每一个按键的消息TForm都是接受到了的,只是在消息处理循环中被其父辈TWinControl的
TWinControl.CNKeyDown当作SPECIALKEY处理掉了。请参考下面的程序:

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 FormCreate(Sender: TObject);
private
{ Private declarations }
procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
procedure WmKeyDown(var Message: TMessage); message WM_KEYDOWN;
procedure CNKeyDown(var Message: TWMKeyDown); message CN_KEYDOWN;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if key = vk_tab then showmessage('FormKeyDown: tab key down');//检测是否按下了TAB键
if key = vk_lwin then showmessage('FormKeyDown: lwin key down');//检测是否按了左边的win95键
end;

procedure TForm1.WmKeyDown(var Message: TMessage);
begin
inherited;
if Message.wParam = vk_tab then showmessage('WmKeyDown: tab key down');//检测是否按下了TAB键
if Message.wParam = vk_lwin then showmessage('WmKeyDown: lwin key down');//检测是否按了左边的win95键
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage:=AppMessage;
end;

procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
Handled:=False;
if Msg.message=WM_KeyDown then
begin
if Msg.wParam = vk_tab then showmessage('AppMessage: tab key down');//检测是否按下了TAB键
if Msg.wParam = vk_lwin then showmessage('AppMessage: lwin key down');//检测是否按了左边的win95键
end;
end;

procedure TForm1.CNKeyDown(var Message: TWMKeyDown);
begin
inherited;
if Message.CharCode = vk_tab then showmessage('CNKeyDown: tab key down');//检测是否按下了TAB键
if Message.CharCode = vk_lwin then showmessage('CNKeyDown: lwin key down');//检测是否按了左边的win95键
end;

end.

这个时候按下TAB键,就只会出现
AppMessage: tab key down
CNKeyDown: tab key down
两条消息。

如果将程序作一点小改动,屏蔽掉父辈的CNKeyDown处理
procedure TForm1.CNKeyDown(var Message: TWMKeyDown);
begin
// inherited;
if Message.CharCode = vk_tab then showmessage('CNKeyDown: tab key down');//检测是否按下了TAB键
if Message.CharCode = vk_lwin then showmessage('CNKeyDown: lwin key down');//检测是否按了左边的win95键
end;

这个时候再按下TAB键,就会出现所有的消息:
AppMessage: tab key down
CNKeyDown: tab key down
FormKeyDown: tab key down
WmKeyDown: tab key down

vk_lwin的情况自己测试一下吧。
至于TWinControl.CNKeyDown可以参考(Delphi5)Controls.pas:Line 6872,好好研究一下吧,呵呵!
 
MMzt说得很对,Tab键比较特殊,一般都在窗体上切换焦点,是Twincontrol自动处理了
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部