標準 CToolTipCtrl 外觀固定 (矩形、黃底黑字),無法自訂形狀 (如氣球尖角)、標題、圖示、自訂顏色。CToolTipWnd 以無框視窗 (WS_POPUP) 手繪氣球外觀,提供豐富視覺效果。
class CToolTipWnd : public CWnd {
public:
BOOL Create(CWnd* pParent); // 建立視窗
void AddTool(CWnd* pTool, LPCTSTR pszText, COLORREF clrText = RGB(0,0,0)); // 新增工具
void SetDefTextColor(COLORREF clr); // 設定預設文字顏色
void RelayEvent(MSG* pMsg); // 轉發訊息 (在 PreTranslateMessage 調用)
protected:
// 內部處理 WM_TIMER 顯示/隱藏、WM_PAINT 繪製氣球、WM_MOUSEMOVE 追蹤
};
ToolTipWnd.cpp/.h。CToolTipWnd m_wndToolTip;。OnInitDialog/OnInitialUpdate 初始化:
m_wndToolTip.Create(this);
m_wndToolTip.AddTool(GetDlgItem(IDC_EDIT1), _T("輸入用戶名稱"), RGB(255,0,0));
m_wndToolTip.AddTool(GetDlgItem(IDC_BUTTON_OK), _T("確認送出"));
PreTranslateMessage 轉發訊息:
BOOL CMyDialog::PreTranslateMessage(MSG* pMsg) {
m_wndToolTip.RelayEvent(pMsg);
return CDialog::PreTranslateMessage(pMsg);
}
BOOL CToolTipWnd::Create(CWnd* pParent) {
return CreateEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW, // 置頂、不在工作列
AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)),
_T(""), WS_POPUP, 0,0,0,0, pParent->GetSafeHwnd(), NULL);
}
struct TOOLINFO {
CWnd* pWnd; // 關聯控制項
CString strText; // 提示文字
COLORREF clrText; // 文字顏色
CRect rect; // 控制項螢幕矩形 (更新時重算)
};
CArray m_tools;
RelayEvent 訊息分派
void CToolTipWnd::RelayEvent(MSG* pMsg) {
if (pMsg->message == WM_MOUSEMOVE || pMsg->message == WM_LBUTTONDOWN ||
pMsg->message == WM_RBUTTONDOWN || pMsg->message == WM_KEYDOWN) {
CPoint pt(pMsg->pt); // 螢幕座標
ScreenToClient(&pt);
// 檢查滑鼠是否在某工具控制項矩形內
for (int i=0; iGetWindowRect(&rectTool); // 即時更新
if (rectTool.PtInRect(pMsg->pt)) {
ShowToolTip(i, pMsg->pt); // 顯示對應提示
return;
}
}
HideToolTip(); // 不在任何工具區域,隱藏
}
}
OnPaint)
void CToolTipWnd::OnPaint() {
CPaintDC dc(this);
CRect rect; GetClientRect(&rect);
// 1. 建立氣球路徑 (圓角矩形 + 三角形尖角)
CRgn rgn;
// ... 計算路徑點,包含尖角指向控制項中心 ...
rgn.CreatePolygonRgn(points, nPoints, ALTERNATE);
dc.SelectClipRgn(&rgn);
// 2. 填充背景漸層/單色
dc.FillSolidRect(rect, RGB(255, 255, 200)); // 淺黃
// 3. 繪製邊框
dc.DrawEdge(&rect, EDGE_RAISED, BF_RECT);
// 4. 繪製文字
dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(m_clrCurrentText);
dc.DrawText(m_strCurrentText, &rect, DT_CENTER | DT_VCENTER | DT_WORDBREAK);
}
DrawText(..., DT_CALCRECT) 加上邊距與尖角空間。SetTimer(TIP_SHOW, 500, NULL) (0.5 秒)。SetTimer(TIP_HIDE, 5000, NULL) 自動隱藏。AnimateWindow (AW_SLIDE | AW_BLEND) 或手動漸變。TTI_INFO/TTI_WARNING/TTI_ERROR)。