在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中的实现spa
procedure TWinControl.CMDialogChar(var Message: TCMDialogChar);
begin
Broadcast(Message);
end;code
可知,他会向全局广播这个快捷消息,全部的控件都会得到这个消息,此时谁先得到,拦截处理以后,消息就再也不继续。而后俺们看看SpeedButton的此消息处理过程blog
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;
再去使用,则触发正常it