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

自繪視窗標題列與邊框:打造專屬介面風格(一)

     編輯:關於VC++

金山詞霸、QuickTime 等軟體擁有獨特介面風格。本文分享自繪非客戶區(標題列、邊框、系統按鈕、控制項)的核心技術與完整範例代碼。

核心概念:圖元素自繪

紅框標示區域皆需美工繪製位圖:標題列左/中/右、系統按鈕(一般/滑鼠進入/按下)、邊框左/右/下、底部狀態列等。圖素品質直接決定介面質感。

基礎繪圖技術

CBitmap* pBitmap = new CBitmap;
BITMAP BmpInfo;
CBitmap* pOldBitmap;
CDC* pDisplayMemDC = new CDC;
pDisplayMemDC->CreateCompatibleDC(pDC);
pBitmap->LoadBitmap(IDB_TITLE_LEFT);
pOldBitmap = (CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pBitmap->GetBitmap(&BmpInfo);
pDC->BitBlt(x, y, BmpInfo.bmWidth, BmpInfo.bmHeight, pDisplayMemDC, 0, 0, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject();
ReleaseDC(pDisplayMemDC);
delete pDisplayMemDC;
delete pBitmap;

座標轉換關鍵

螢幕座標 ↔ 視窗座標 ↔ 客戶區座標轉換必須熟練,否則繪圖位置會錯位。

完整實作:CTitleBarDlg 類別

需重寫的訊息函式

  • OnNcLButtonDown:非客戶區左鍵按下(處理系統按鈕點擊)
  • OnNcMouseMove:非客戶區滑鼠移動(按鈕懸停效果)
  • DefWindowProc:攔截 WM_MOVE、WM_PAINT、WM_NCPAINT、WM_NCACTIVATE 等觸發重繪

核心繪製函式 DrawTitleBar

BOOL CTitleBarDlg::DrawTitleBar(CDC* pDC)
{
    if (!m_hWnd) return FALSE;
    // 1. 計算標題列、按鈕、邊框矩形區域
    // 2. 依序繪製:標題列左/中/右、最小化/最大化/關閉按鈕、視窗標題文字
    // 3. 繪製左/右/下邊框(平鋪位圖)
    // 4. 釋放所有 GDI 物件
    // 完整代碼請參考下載專案,此處因篇幅略過
}

滑鼠移動處理

void CTitleBarDlg::OnNcMouseMove(UINT nHitTest, CPoint point)
{
    CDC* pDC = GetWindowDC();
    // 座標轉換:螢幕 → 視窗客戶區
    CRect rtWnd; GetWindowRect(&rtWnd);
    point.x -= rtWnd.left; point.y -= rtWnd.top;
    
    // 判斷滑鼠在哪個按鈕上,載入對應位圖並重繪
    if (m_rtButtExit.PtInRect(point)) { /* 載入關閉按鈕懸停圖 */ }
    else if (m_rtButtMin.PtInRect(point)) { /* 載入最小化懸停圖 */ }
    else if (m_rtButtMax.PtInRect(point)) { /* 載入最大化/還原懸停圖 */ }
    else { /* 載入一般狀態圖 */ }
    // 繪製按鈕區域...
    ReleaseDC(pDC);
    CDialog::OnNcMouseMove(nHitTest, point);
}

左鍵按下處理

void CTitleBarDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
    // 座標轉換同 OnNcMouseMove
    // 依點擊區域發送對應系統命令:
    // m_rtIcon -> 關於訊息
    // m_rtButtHelp -> WM_HELP
    // m_rtButtExit -> WM_CLOSE
    // m_rtButtMin -> SC_MINIMIZE
    // m_rtButtMax -> SC_MAXIMIZE / SC_RESTORE
    // 其他區域 -> Default() 保留視窗拖曳功能
}

DefWindowProc 觸發重繪

LRESULT CTitleBarDlg::DefWindowProc(UINT msg, WPARAM wParam, LPARAM lParam)
{
    LRESULT lr = CDialog::DefWindowProc(msg, wParam, lParam);
    if (!::IsWindow(m_hWnd)) return lr;
    
    if (msg == WM_MOVE || msg == WM_PAINT || msg == WM_NCPAINT || 
        msg == WM_NCACTIVATE || msg == WM_NOTIFY)
    {
        CDC* pDC = GetWindowDC();
        if (pDC) { DrawTitleBar(pDC); ReleaseDC(pDC); }
    }
    return lr;
}

執行結果

設計建議

  • 對話框屬性僅勾選 Title Bar,其餘取消
  • 訊息函式需手動加入(ClassWizard 不支援非客戶區訊息)
  • 測試環境:VC++ 6.0 + WinXP

單一視窗美化容易,多視窗統一風格較難。後續將探討子類化技術讓所有視窗共享風格、控制項美化與自動佈局。歡迎交流:QQ 34544052 / Email Song_0962@sina.com

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved