在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的此消息處理過程
TSpeedButton.CMDialogChar( Message IsAccel(CharCode, Caption) Enabled Visible <> ) Parent.Showing = ;
IsAccel函數,實際上就是根據Caption來判定是否和快捷鍵匹配的,如果匹配,並且Enabled並且可視,並且Parent可視,那麼就會觸發了,於是問題根源找到了,就是這個parent可視,因為TabSheet上的Parent一直是可視的,所以這個就會觸發,但是Parent的TabSheet確實隱藏了,所以,就導致了這個亂了。既然找到問題所在,那麼針對此消息
過程進行攔截處理就行了。實現過程如下:
TSpeedButton = CMDialogChar( Message: TCMDialogChar); TSpeedButton.CMDialogChar(== P <> = CanDlgChar = CanDlgChar Message IsAccel(CharCode, Caption) Enabled Visible <> ) IsWindowVisible(Parent.Handle) Parent.Showing = ;
再去使用,則觸發正常