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

實現類似 VC 屬性視窗釘選按鈕:CSButton 類別完整實作

     編輯:關於VC++

Visual C++ 屬性視窗標題列的「釘選」按鈕(保持視窗置頂/取消置頂)是實用的 UI 元素。本文展示如何從 CButton 衍生 CSButton 實現此功能,包含雙態位圖切換、視窗 Z-Order 控制完整邏輯。

實作步驟概覽

  1. 建立對話框基礎專案
  2. 新增 CSButton 類別繼承 CButton
  3. 匯入兩張位圖資源:IDB_BITMAP1(釘下)、IDB_BITMAP2(未釘下)
  4. 成員變數:CBitmap bitmap, bitmap2; BOOL m_state; CDC memdc, memdc2;

核心程式碼實現

PreSubclassWindow - 初始化位圖與相容 DC

void CSButton::PreSubclassWindow() {
    m_state = FALSE;
    bitmap.LoadBitmap(IDB_BITMAP1);
    bitmap2.LoadBitmap(IDB_BITMAP2);
    
    CDC *pDC = GetDC();
    memdc.CreateCompatibleDC(pDC);
    memdc.SelectObject(&bitmap);
    memdc2.CreateCompatibleDC(pDC);
    memdc2.SelectObject(&bitmap2);
    
    CButton::PreSubclassWindow();
}

DrawItem - 根據狀態繪製對應位圖

void CSButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
    CRect client = lpDrawItemStruct->rcItem;
    CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    
    CBrush brush;
    brush.CreateSolidBrush(::GetSysColor(COLOR_BTNFACE));
    pDC->FillRect(client, &brush);
    
    if (m_state) {
        // 釘下狀態:視窗置頂
        pDC->StretchBlt(client.left, client.top, client.Width(), client.Height(),
                        &memdc, 0, 0, 24, 21, SRCCOPY);
        GetParent()->SetWindowPos(&CWnd::wndTopMost, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);
    } else {
        // 未釘下狀態:視窗取消置頂
        pDC->StretchBlt(client.left, client.top, client.Width(), client.Height(),
                        &memdc2, 0, 0, 24, 21, SRCCOPY);
        GetParent()->SetWindowPos(&CWnd::wndNoTopMost, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);
    }
}

OnLButtonDown - 狀態切換邏輯

void CSButton::OnLButtonDown(UINT nFlags, CPoint point) {
    m_state = !m_state;  // 切換狀態
    CButton::OnLButtonDown(nFlags, point);
}

關鍵技術點解析

  • 雙緩衝 DC:memdc/memdc2 預先載入位圖,DrawItem 直接 StretchBlt 繪製,效能最佳
  • 視窗 Z-Order 控制:SetWindowPos 搭配 wndTopMost/wndNoTopMost 實現置頂切換
  • Owner Draw 機制:按鈕需設定 BS_OWNERDRAW 樣式(可在資源編輯器或 PreSubclassWindow 中設定)
  • 位圖尺寸固定:範例使用 24×21 像素,實際專案需依設計圖調整

擴充建議

  • 加入工具提示顯示當前狀態說明
  • 支援鍵盤空白鍵切換(處理 WM_KEYDOWN)
  • 提供 GetState()/SetState() 公開介面供外部控制
  • 使用圖片清單 (CImageList) 取代雙 CDC 簡化資源管理

總結

CSButton 以不足 50 行核心程式碼完整實現釘選按鈕功能,展示了 MFC 自繪按鈕結合視窗操作的經典模式。原始碼結構清晰,可直接整合專案或作為其他雙態按鈕開發的參考範本。

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