如何为没有焦点的控件添加键盘事件? (有新问题,十万火急) (100分)

  • 主题发起人 主题发起人 dirk
  • 开始时间 开始时间
[red]让TScrollBox可以排在Tab键的焦点切换列表中?[/red]
把TScrollBox的 TabStop 属性设为 True 即可.
 
哇!这么简单?

[:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D]

一直没有注意过这个属性,想不到竟有这个作用,谢谢xeen的提醒,哈哈哈!

[:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D][:D]
 
紧急求教:
这个问题原以为解决了技术问题,搁置了一段时间,现在要用到了,却发现又有了新问题:

TScrollBox 的 TabStop 属性设为 True 后,TScrollBox可以通过Tab键进入TScrollBox,
获得焦点,从而可以响应key事件,但是,我需要截获4个“方向箭头”键,而这4个键一按
就会离开TScrollBox,触发onexit事件,而TScrollBox无法捕捉到键值为 37~40(就是4个
方向键)的键,怎么办?我要通过在4个键来控制一些动作,而且必须是在TScrollBox自己
捕捉到的key事件中,不能用form的KeyPreview。

很急啊[:(!]
 
其实,这个又回到了前面。好象没有其他的办法了,只有钩了主窗口进程做工作了。
分析一下:消息总是先进入主窗口等待分配处理,Form 肯定比任何控件都先接到通知,
一旦接到通知后,Form 认为是自己要处理的消息,就会处理掉,并立即返回短路掉消息。
从而根本不会让控件知道已经有这样的消息来到过。所以,动刀子的地方,就非主窗口
进程莫属了。具体是否可以:1.直接使用新的窗口进程,检查处理后再往老窗口进程走。
2.接管 Form 的消息接收,处理同上。但由于是自己在做控件,第二种办法,其实就是
Application.OnMessage ,用在控件中好象不妥,那就只有钩了主窗口进程一条路了。
 
谢谢小雨哥,后来我想了想,像TScrollBox这类控件,无法停留焦点,所以,当4个方向键
出现时,OwnerForm就直接把消息处理了,将焦点设置到了其他控件上,但是像TEdit控件,
同样也是从TWinControl继承而来,它却可以留住焦点,肯定是做了什么,但VCL源码又看
不出什么(功力有限),有谁能给点提示吗?小雨哥的第一方案能否再具体一点点,因为现
在很急,而我又没有这方面的经验(有时间我当然更愿意研究一下),谢谢了!
 
很不好意思,问题还没解决,就不小心把帖子结了,请大家到
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1662068
来拿分吧,alaclp就没有了,呵呵呵,名字开头有个a就是占便宜。[8D]
 
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;
 
xeen,ok3333,zxbyh,wjsht,ego,小雨哥,kingdeezj,小笨苯,zjan521请到
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1662068
来拿分吧,kenny.hu已经来啦!
 
上面点到名的快去拿分吧,过几天我要结帖子啦![8D]
 
谢谢 dirk ,做个朋友吧,别提分不分的了。 :-)
wr960204 的方法你可以试试的。关于获得窗口进程的一般方法是:
1.写一个符合窗口进程格式的函数处理你的要求
procedure TYouControl.NewWndProc(var Msg: TMessage);
( VCL 中对窗口进程的定义是:
TWndMethod = procedure(var Message: TMessage) of object; )
2.获取原始的主窗口进程
OldWndProc:=GetWindowLong(OwnerForm.Handle, GWL_WNDPROC)
3.为主窗口指定一个新窗口进程
SetWindowLong(OwnerForm.Handle, GWL_WNDPROC, @NewWndProc))
 
谢谢小雨哥,已经用wr960204的方法搞定了。
 
咦?好奇怪,才发现,误结的帖子被恢复了,不知是哪为好心的版主啊?(不要是系统故障
就好了[8D])

好了,发分!分不多,还要的到
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1662068
去拿(三天后结,过期不候哦),wr960204的分另外给了!
 
呵呵呵,结不了[:(],看来系统是有问题了!
 
再结一次看看[;)]
 
算了,改天再结![:O]
 
多人接受答案了。
 
后退
顶部