【已解決】CMyButton 反應太慢

CMyButton 是一個 Owner-Drawn 的 CButton,最近在使用時發現:如果連續按的話,有時會沒有反應。

原本懷疑:
  1.  利用 OnSetCursor 攔截 Mouse Over 的狀態,如果 Mouse 停留在 Button 的區域內,會一直產生重繪的動作 (取消後問題仍在,故排除)
  2. 按下 Button 後執行的程式佔用太多的時間,導致第二次 Button click 來不及處理 (但使用標準的 CButton 則沒有問題,故排除)

後來用 Spy++ 攔截主視窗的 WM_COMMAND 訊息時發現:CButton 會依序產生 Button click 的訊息;但 CMyButton 如果連續按的話,第一次是 Button click,第二次則是 Double-click。

原來 Owner-Drawn 的 CButton 快速連續按的話會產生 Double-click (BN_DBLCLK notification code),而主視窗並未處理該 Double-click 事件,所以看起來就像按鍵沒有反應。

那為甚麼它會送出 Double-click message?如果 Windows Class Styles 有 CS_DBLCLKS 時 (注意:是 Class Styles,不是 Window Styles。前者跟視窗的行為有關,後者跟視窗的外觀有關),Control 就會接受 Double-click 並送出 Message

所以解決辦法就是把 CS_DBLCLKS 拿掉,那它就不會送出 Double-click 了。目前的做法是在 Subclass 之前利用 SetClassLongPtr 修改即可。(原本是使用 SetClassLong,為了相容 32-bit and 64-bit Windows 才改的)

void CMyButton::PreSubclassWindow()
{
 // TODO: Add your specialized code here and/or call the base class
 HWND hWnd = GetSafeHwnd();
 ULONG_PTR ulStyle = GetClassLongPtr(hWnd, GCL_STYLE);
 ulStyle &= ~CS_DBLCLKS;
 SetClassLongPtr(hWnd, GCL_STYLE, ulStyle);

 CButton::PreSubclassWindow();
}

當然在論壇 Disable double klicks 中也有人提到用 SetDoubleClickTime 修改 Double-click 的間隔時間,甚至縮短到 0 就無法產生 Double-click 了。問題這是一個系統層級的函式,修改後會造成其它程式也無法 Double-click,所以不是一個理想的解決辦法。

留言

這個網誌中的熱門文章

Linux 批次檔的寫法

【分享】如何顯示 Debug Message

[分享] Visual Studio 遠端偵錯