关于SpeedButton中使用下划线快捷键不响应的问题
2014-05-08 11:03
246 查看
在Windows应用程序,很多都有快捷键功能,这个Delphi也有,就是一个按钮上面有一个比如剪切(&X),这个时候剪切的快捷键就是Alt+X,这个功能有时候还是挺好用的,最近,公司中有同事,好些使用了SpeedButton,然后使用本方式整的快捷键,都不能用,于是问我,这个是神马问题,实际上确切的说,也不是不能用,而是在某些情况下不能用,比如说使用PageControl等一类控件,然后再TabSheet下面再放一个Panel,然后再Panel上放SpeedButton,这个时候,使用快捷键就会导致响应有问题,比如说TabSheet1中直接就有一个SpeedButton就在TabSheet1上,TabSheet2上的SpeedButton在Panel上,两个TabSheet的SpeedButton的快捷键都是Alt+A,此时按道理来说,应该快捷键,哪个TabSheet是激活状态,就应该响应那个TabSheet上的SpeedButton的快捷键事件,可是实际上,只要有Panel的那个SpeedButton页面激活过之后,就会一直响应那个页面的SpeedButton的快捷键激活。而且会导致混乱。
针对这个问题,啥办法呢,自然不能盲目的去整,Delphi比较好的一点就是VCL源码都带了,所以直接去VCL中去找答案就行了,通过跟踪发现Alt+X这类快捷键模式实际上是响应的Delphi的CM_DIALOGCHAR这个消息,然后查看TwinControl中的实现
procedure TWinControl.CMDialogChar(var Message: TCMDialogChar);
begin
Broadcast(Message);
end;
可知,他会向全局广播这个快捷消息,所有的控件都会获得这个消息,此时谁先获得,拦截处理之后,消息就不再继续。然后俺们看看SpeedButton的此消息处理过程
IsAccel函数,实际上就是根据Caption来判定是否和快捷键匹配的,如果匹配,并且Enabled并且可视,并且Parent可视,那么就会触发了,于是问题根源找到了,就是这个parent可视,因为TabSheet上的Parent一直是可视的,所以这个就会触发,但是Parent的TabSheet确实隐藏了,所以,就导致了这个乱了。既然找到问题所在,那么针对此消息
过程进行拦截处理就行了。实现过程如下:
再去使用,则触发正常
针对这个问题,啥办法呢,自然不能盲目的去整,Delphi比较好的一点就是VCL源码都带了,所以直接去VCL中去找答案就行了,通过跟踪发现Alt+X这类快捷键模式实际上是响应的Delphi的CM_DIALOGCHAR这个消息,然后查看TwinControl中的实现
procedure TWinControl.CMDialogChar(var Message: TCMDialogChar);
begin
Broadcast(Message);
end;
可知,他会向全局广播这个快捷消息,所有的控件都会获得这个消息,此时谁先获得,拦截处理之后,消息就不再继续。然后俺们看看SpeedButton的此消息处理过程
procedure TSpeedButton.CMDialogChar(var Message: TCMDialogChar); begin with Message do if IsAccel(CharCode, Caption) and Enabled and Visible and (Parent <> nil) and Parent.Showing then begin Click; Result := 1; end else inherited; end;
IsAccel函数,实际上就是根据Caption来判定是否和快捷键匹配的,如果匹配,并且Enabled并且可视,并且Parent可视,那么就会触发了,于是问题根源找到了,就是这个parent可视,因为TabSheet上的Parent一直是可视的,所以这个就会触发,但是Parent的TabSheet确实隐藏了,所以,就导致了这个乱了。既然找到问题所在,那么针对此消息
过程进行拦截处理就行了。实现过程如下:
TSpeedButton = class(Buttons.TSpeedButton) protected procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; end; procedure TSpeedButton.CMDialogChar(var Message: TCMDialogChar); var p: TWinControl; CanDlgChar: Boolean; begin CanDlgChar := False; p := Parent; while P <> nil do begin CanDlgChar := IsWindowVisible(P.Handle); if not CanDlgChar then Break; p := p.Parent; end; if CanDlgChar then with Message do if IsAccel(CharCode, Caption) and Enabled and Visible and (Parent <> nil) and IsWindowVisible(Parent.Handle) and Parent.Showing then begin Click; Result := 1; end else inherited; end;
再去使用,则触发正常
相关文章推荐
- 关于使用asihttprequest请求无响应问题
- 关于Cocos2D-X 3.10在android平台上使用外接键盘无法响应的问题
- 关于myeclipse无法使用ctrl+shift+f快捷键格式化代码的问题
- 关于父布局中,使用了动画,造成子布局onclick响应还在的问题
- 关于Android开发中使用System.exit(0)的问题(如写返回键响应时用到双击退出函数的时候)
- 关于Eclipse和IDEA使用快捷键格式化代码不起作用问题解决
- 关于使用androidannotations注解框架,不能生成带下划线子类问题
- 关于shm_open和shm_unlink的使用问题
- 关于使用navicat向sqlserver和mysql数据库导入excel的问题
- 关于打印时“激活和使用此控件”问题
- 关于使用eclipse开发安卓时布局界面XML的graphical layout没有显示的问题
- mfc中使用组合件消息响应问题
- 关于使用getDrawingCache()方法获取屏幕截图的问题
- 关于使用struts2时子窗体页面跳转后在父窗体打开的问题以及Session过期后的页面跳转问题
- 关于Codeblocks+wxWidgets的使用问题
- 关于SwipeRefreshLayout与ViewPage、ListView嵌套使用的几个问题
- 在 win7 中使用 vs2003 时,“在文件中查找”导致无响应的问题解决
- 1.关于Web.config之间不能使用&字符的问题
- 关于系统首页绘制问题(ext布局+c#后台加入数据)经html输出流输出响应client
- 关于django1.7.7使用ajax后出现“CSRF token missing or incorrect”问题的解决办法