| 方案 | 原理 | 優/缺點 |
| 手動處理 WM_MOVE/LBUTTONUP | 自行計算位移、BitBlt 重繪 | 控制精細,但代碼繁瑣、易閃爍 |
| 發送 WM_NCLBUTTONDOWN (HTCAPTION) | 欺騙系統以為點擊標題列,由系統處理移動迴圈 | 極簡、系統級流暢、自動處理快照/重繪 (本文採用) |
核心類別 CMainWnd : public CWnd
建立視窗
BOOL CMainWnd::CreateMainWnd() {
return CreateEx(0,
AfxRegisterWndClass(0,
LoadCursor(NULL, IDC_ARROW),
GetSysColorBrush(COLOR_ACTIVEBORDER)),
NULL, WS_POPUP, 0, 0, 300, 50, NULL, NULL);
}
WS_POPUP:無標題、無邊框、無系統選單
- 背景筆刷設為
COLOR_ACTIVEBORDER 符合系統配色
自繪 OnPaint:五個位圖按鈕 + 雙層 3D 邊框
void CMainWnd::OnPaint() {
CPaintDC dc(this);
CDC memDC; memDC.CreateCompatibleDC(&dc);
CBitmap* pOld;
// 依狀態繪製 5 個按鈕 (m_bBTState[5])
for (int i=0; i<5; ++i) {
pOld = memDC.SelectObject(m_bBTState[i] ? &m_BT1_1 : &m_BT1_2); // 簡化:實際各有專屬位圖
dc.BitBlt(m_rcBT[i].left, m_rcBT[i].top, m_rcBT[i].Width(), m_rcBT[i].Height(), &memDC, 0, 0, SRCCOPY);
}
// 雙層 3D 邊框 (模擬 WS_BORDER + WS_EX_CLIENTEDGE)
CRect rc; GetClientRect(&rc);
dc.Draw3dRect(&rc, RGB(192,192,192), RGB(0,0,0)); // 外層
rc.DeflateRect(1,1);
dc.Draw3dRect(&rc, RGB(255,255,255), RGB(144,144,144)); // 內層
memDC.SelectObject(pOld);
}
滑鼠移動 OnMouseMove:判定拖曳區域 + 發送移動訊息
void CMainWnd::OnMouseMove(UINT nFlags, CPoint point) {
// 有效拖曳區域:五個按鈕之外的客戶區
bool bInDragRegion = IsInDragRegion(point);
if (bInDragRegion) {
SetCursor(m_hCrossCursor); // 十字光標提示可拖曳
if (nFlags & MK_LBUTTON) {
POINT pt = point;
ClientToScreen(&pt);
// 關鍵:發送 WM_NCLBUTTONDOWN,wParam=HTCAPTION,lParam=打包螢幕座標
SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(pt.x, pt.y));
}
}
CWnd::OnMouseMove(nFlags, point);
}
左鍵按下 OnLButtonDown:按鈕命中測試
void CMainWnd::OnLButtonDown(UINT nFlags, CPoint point) {
for (int i=0; i<5; ++i) {
if (m_rcBT[i].PtInRect(point)) {
m_bBTState[i] = !m_bBTState[i]; // 切換狀態
InvalidateRect(m_rcBT[i]); // 只重繪該按鈕
break;
}
}
CWnd::OnLButtonDown(nFlags, point);
}
關閉熱鍵
資源加入 Accelerator:F12 → ID_APP_EXIT,或 OnKeyDown 處理 VK_F12 呼叫 PostMessage(WM_CLOSE)。
執行效果

作者疑問:Spy++ 找不到智能 ABC 視窗?
輸入法候選視窗可能屬於 IMM32 內部視窗類別,或以 WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_LAYERED 建立,且不在標準視窗列舉中。亦可能是 非 HWND 繪製 (DirectComposition/Win32k 內部)。若有深入了解者歡迎補充。
適用場景
- 輸入法候選視窗、工具提示、桌面小工具、屏幕取色器
- 任何需「無框、可拖曳、常駐頂層」的輕量視窗
完整原始碼請參考本文配套下載。核心技巧 SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, ...) 可直接移植至任何 CWnd 衍生類實現無標題拖曳。
- 上一篇文章: C++/C# 跨語言呼叫 COM 組件完整指南:四種組合模式全覆蓋 (VS2005 + VC6.0)
- 下一篇文章: ActiveSkin 4.3 在 VC++ 中實現軟體換膚:SkinForm/SkinFreeForm 兩種模式完整範例
Copyright ©
程式碼之家 All Rights Reserved