关于:如何为没有焦点的控件添加键盘事件 之再问:如何控制4个方向键 ! (急急急) (300分)

  • 主题发起人 主题发起人 dirk
  • 开始时间 开始时间
D

dirk

Unregistered / Unconfirmed
GUEST, unregistred user!
上次一时手误,结束了问题,把分也发错了,现在这个贴子是继续上个帖子的,分数补上,
再兑现上个帖子中要的追加的200分,请在上个帖子中回答问题的朋友过来拿分,上个帖子:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1633404

正题:
我要写个控件,从TScrollBox继承而来,但是像TScrollBox这类控件,无法停留焦点,所以,
当4个方向键出现时,OwnerForm就直接把消息处理了,将焦点设置到了其他控件上,而我恰恰
需要对这4个键进行控制,于是我想到了TEdit控件,同样也是从TWinControl继承而来,它却
可以留住焦点,肯定是做了什么,但VCL源码又看不出什么(功力有限),请[blue]愿意帮忙的高手[/blue]
给点提示?

[blue]小雨哥[/blue]的第一方案:直接使用新的窗口进程,检查处理后再往老窗口进程走。
能否再具体一点点,因为现在很急,而我又没有这方面的经验(有时间我当然更愿意研究一下),
谢谢了!
 
type
ts = class(TScrollBox)
private
FOnkeyDown:TKeyEvent;
procedure CNKeydown(var Message: TMessage); message CN_KEYDOWN;
protected
procedure KeyDown(var Key: Word; Shift: TShiftState); override;

public
constructor Create(AOwner: TComponent); override;
published
property OnkeyDown:TKeyEvent read FOnkeyDown write FOnkeyDown;
end;
procedure ts.CNKeydown(var Message: TMessage);
begin
case TWMKey(Message).CharCode of
VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_TAB:
begin
Exit;//如果让他自己处理的话就会失去焦点,必须中断才能把消息传到WM_KeyDown
end;
else
inherited;
end;
end;

constructor ts.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
TabStop :=True;//使之能获得焦点
end;

procedure ts.KeyDown(var Key: Word; Shift: TShiftState);
begin
if Assigned(FOnkeyDown) then
begin
FOnkeyDown(Self,key,Shift);
end;
inherited;
end;
 
谢谢wr960204回答,你说的方法在上个帖子里已经解决了,现在的问题是 4 个方向键,
在form上放一个button,在click事件中创建ts对象,setfocus,再为其keydown赋值,
这样能响应除4个方向键外的所有(好像,没有一个一个试)键,但一按方向键,焦点就
跑到button上了,而keydown事件压根没反应,这就是我的问题,你试试。
 
把button换成speedbutton试一下
 
呵呵呵,我哭,kenny.hu,我可是要写一个控件也,难道还要求使用者不要用button或任一
可停留焦点的控件吗?[:(]
 
TScrollBox也是从TWinControl继承来的呀,肯定可以停留焦点的
 
怎么做?正如我上面说的,setfocus后,一按这 4 个方向键,焦点立即切走了,而且控件
还捕捉不到key事件,关键是这个:[blue]控件捕捉不到key事件[/blue]。
 
好办,我来给你搞定吧,正在研究中。。。
要是弄出来了,可要多给点分呀
 
当然。

我也在研究,现在正在研究TApplicationEvents,发现
procedure TFrm_Main.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
var
ss:word;
begin
if Msg.message =WM_KEYDOWN then
begin
if ActiveControl is TMyCM then
begin
if assigned(TMyCM(ActiveControl).OnKeyDown ) then
begin
ss:=38;
TMyCM(ActiveControl).OnKeyDown(ActiveControl,ss,[]);
Msg.message :=0;
end;
end;
end;
end;

是可以截下key消息的,但……

只能到中午啦,还没解决就只能暂时放弃,现在进度最重要了,以后再研究了。
 
to dirk

我已经搞定了,我发现TWinControl也存在这样的问题,所以我知道怎么办了
听我慢慢给你说,呵呵,记着请客吧
 
别慢慢说了,快说![:O]
 
我已经快来不及了![:O]
 
unit MyStrollBox;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TMyScrollBox = class(TScrollBox)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
procedure CreateParams(var Params: TCreateParams); override;
published
{ Published declarations }
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('yzhshi', [TMyScrollBox]);
end;

{ TMyScrollBox }

procedure TMyScrollBox.CreateParams(var Params: TCreateParams);
var
SaveInstance: THandle;
begin
inherited CreateParams(Params);

with Params do
begin
SaveInstance := WindowClass.hInstance;
GetClassInfo(WindowClass.hInstance, pChar('EDIT'), WindowClass);
WindowClass.hInstance := SaveInstance;
Style := Style + ES_READONLY;
end;
end;

end.

 
我不说了,经过我的实验
wr960204,的方法完全可行,我的方法和他的差不多

他的方法是没有问题的,我试过了
 
procedure TCustomEdit.CreateParams(var Params: TCreateParams);中含有
CreateSubClass(Params, 'EDIT');
将这句话放到TWinControl中就可以了,不过显得不伦不类?!
目前可以实现你的功能,但是在Strcollbox里面出现了一个光标?目前还没有办法删除这个。要不然,全都满足了。
 
to Dirk
看到我的话了吗?
 
题外话:
关于 CN_*** 系列消息
字面的意思可能是 Control Notify Message的意思

在VCL中对于窗口消息的处理,Borland显然作了手脚,
在消息循环中,得到的是WM_KEYDOWN消息,VCL将其加上一个整数,变成了CN_KEYDOWN
其他的CN_*消息也都是这么来的,所以先调用了CN_*的消息处理过程
之后交给了WM_*的消息处理过程,而在CN_*的处理过程中对消息进行了一些过滤
和特殊处理

这就是为什么TButton的继承不能通过WM_KEYDOWN来捕捉键盘方向键消息的原因了

解决的方法很简单,直接映射CN_*系列消息,就可以为所欲为了。。。:)
 
我上面已经处理了CNKeyDown,所以在你的OnkeyDown中可以截获到方向键的。
你最好试验了在说话
 
哦,谢谢各位,是的,wr960204的回答是对的,我刚才居然没有看到
procedure CNKeydown(var Message: TMessage); message CN_KEYDOWN;
这部分,我只看到
constructor ts.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
TabStop :=True;//使之能获得焦点
end;

procedure ts.KeyDown(var Key: Word; Shift: TShiftState);
begin
if Assigned(FOnkeyDown) then
begin
FOnkeyDown(Self,key,Shift);
end;
inherited;
end;
这部分,所以认为是不行的,真是冤枉好人,这个帖子的邮件通知我一封
也没收到,到是收到了上个帖子中wr960204的留言,和这里一样,我看了
一下,才注意到了CNKeydown,多谢!

wr960204老兄,是我没看清楚,不好意思!不过,奇怪的是,我记得我是把你贴
出的代码全部拷贝回去试的,所以就没怎么看代码,当时的确不行,好像没有
CNKeydown啊?唉,你要是早点出来回应我一下就好了。多谢!
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部