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

VC++ 自繪按鈕實作釘子按鈕(Push Pin)效果

     編輯:VC 教學

需求

模仿 Visual Studio 屬性視窗標題列的「釘子」按鈕:點擊切換釘入/釘出狀態,圖片翻轉,並同步設定父視窗 `WS_EX_TOPMOST` 置頂/取消置頂。

實作步驟

  1. 新建 `CSButton` 繼承 `CButton`。
  2. 匯入兩張位圖資源:`IDB_PIN_UP`(未釘)、`IDB_PIN_DOWN`(已釘)。
  3. 成員變數:`CBitmap m_bmpUp, m_bmpDown; CDC m_memUp, m_memDown; BOOL m_pinned = FALSE;`

關鍵代碼

PreSubclassWindow - 載入位圖建立記憶體 DC


void CSButton::PreSubclassWindow() {
    m_pinned = FALSE;
    m_bmpUp.LoadBitmap(IDB_PIN_UP);
    m_bmpDown.LoadBitmap(IDB_PIN_DOWN);

    CDC* pDC = GetDC();
    m_memUp.CreateCompatibleDC(pDC);  m_memUp.SelectObject(&m_bmpUp);
    m_memDown.CreateCompatibleDC(pDC); m_memDown.SelectObject(&m_bmpDown);
    ReleaseDC(pDC);

    CButton::PreSubclassWindow();
    ModifyStyle(0, BS_OWNERDRAW); // 必須設為 OwnerDraw
}

DrawItem - 繪製按鈕狀態


void CSButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) {
    CRect rc = lpDIS->rcItem;
    CDC* pDC = CDC::FromHandle(lpDIS->hDC);

    // 背景
    CBrush br(::GetSysColor(COLOR_BTNFACE));
    pDC->FillRect(rc, &br);

    // 依狀態畫位圖
    CDC* pSrc = m_pinned ? &m_memDown : &m_memUp;
    pDC->StretchBlt(rc.left, rc.top, rc.Width(), rc.Height(),
        pSrc, 0, 0, 24, 21, SRCCOPY); // 24x21 為原圖尺寸

    // 同步父視窗置頂狀態
    GetParent()->SetWindowPos(m_pinned ? &CWnd::wndTopMost : &CWnd::wndNoTopMost,
        0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

OnLButtonDown - 切換狀態


void CSButton::OnLButtonDown(UINT nFlags, CPoint point) {
    m_pinned = !m_pinned;
    Invalidate(); // 觸發重繪
    CButton::OnLButtonDown(nFlags, point);
}

使用方式

  1. 對話框編輯器放置 Button,設定 ID 為 `IDC_PIN`,屬性勾選 Owner Draw。
  2. ClassWizard 關聯 `CSButton m_btnPin`。
  3. 執行即見釘子按鈕切換並控制視窗置頂。

進階優化

  • 使用 `CImageList` 管理多狀態圖片,支援高 DPI 縮放。
  • 加入 `BS_AUTOCHECBOX` 樣式配合 `GetCheck()` 狀態查詢。
  • 繪製時處理 `ODS_SELECTED`/`ODS_FOCUS` 顯示按下/焦點虛線框。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved