首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

MFC 實現智能 ABC 風格頂層無標題視窗:手動拖曳移動 + 自繪 3D 邊框 + 位圖按鈕

     編輯:關於VC++

專案目標

複刻輸入法候選視窗 (智能 ABC) 風格:無標題列、無邊框、常駐頂層、可拖曳移動、自繪 3D 邊框與位圖按鈕。核心難點:無標題列如何移動視窗?

兩種移動實現對比

核心類別 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)。

執行效果

智能 ABC 風格視窗

作者疑問:Spy++ 找不到智能 ABC 視窗?

輸入法候選視窗可能屬於 IMM32 內部視窗類別,或以 WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_LAYERED 建立,且不在標準視窗列舉中。亦可能是 非 HWND 繪製 (DirectComposition/Win32k 內部)。若有深入了解者歡迎補充。

適用場景

  • 輸入法候選視窗、工具提示、桌面小工具、屏幕取色器
  • 任何需「無框、可拖曳、常駐頂層」的輕量視窗

完整原始碼請參考本文配套下載。核心技巧 SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, ...) 可直接移植至任何 CWnd 衍生類實現無標題拖曳。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案原理優/缺點
手動處理 WM_MOVE/LBUTTONUP自行計算位移、BitBlt 重繪控制精細,但代碼繁瑣、易閃爍
發送 WM_NCLBUTTONDOWN (HTCAPTION)欺騙系統以為點擊標題列,由系統處理移動迴圈極簡、系統級流暢、自動處理快照/重繪 (本文採用)