當 CListBox 項目文字過長超出控制項寬度時,如何像 Toolbar 那樣優雅地彈出提示視窗顯示完整內容?本文介紹一個設計精良、可高度重用的解決方案 —— CPopupText + CListBoxTipHandler 組合,並深度解析其核心架構與兩大關鍵技巧。
ShowDelayed) 與取消 (Cancel)。CPopupText。為何用 CSubclassWnd 而非繼承 CListBox?因為你可能已有自己的 CMyListBox,多重繼承麻煩且受限。CSubclassWnd 讓你以「組合」而非「繼承」方式,為任意現有列表框即插即用地添加提示功能。
// 對話框類別成員 CListBox m_wndList; CListBoxTipHandler m_tipHandler; // OnInitDialog 中初始化 m_tipHandler.Init(&m_wndList); // 就這麼簡單,魔法生效!
當滑鼠在列表項間移動,WM_MOUSEMOVE 正常;但滑鼠移出列表框外,系統不再發送訊息給列表框,提示視窗會殘留。解決方案:CListBoxTipHandler 代表列表框呼叫 SetCapture() 捕獲滑鼠。此後所有滑鼠訊息均導向處理器,一旦偵測座標超出列表框矩形,立即 ReleaseCapture() 並隱藏提示。
SWP_NOACTIVATE + SW_SHOWNA —— 保持父視窗焦點不閃爍定位提示視窗時使用 SetWindowPos(..., SWP_NOACTIVATE);顯示時用 ShowWindow(SW_SHOWNA) (Show No Activate)。關鍵在於不讓提示視窗成為活動視窗,否則對話框標題列會變灰 (失去焦點),造成視覺跳動與焦點混亂。
CListBoxTipHandler 提供兩個虛函數供覆寫:
OnGetItemInfo:取得指定索引項目的文字與矩形區域。IsRectCompletelyVisible:判斷項目矩形是否完整可見。覆寫這兩個函數,即可將提示功能擴展至 CComboBox、CListCtrl 等任何類列表控制項。(注意:CTreeCtrl 內建 ToolTip,無需此類。)

圖一:LCTest 範例程式,普通列表框獲得 Toolbar 風格提示能力
這套方案展現了經典 MFC 設計智慧:CSubclassWnd 解耦功能與控制項類型,CPopupText 封裝繪圖細節,虛函數預留擴展點。源碼簡潔、邏輯清晰,堪稱 MFC 可重用元件設計的教科書級範例。