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

VC++ 非客戶區按鈕實作:於標題列等區域新增自訂按鈕

     編輯:關於VC++

前言

在 Windows 程式開發中,有時候我們需要在視窗的非客戶區(Non-Client Area,例如標題列、邊框)放置按鈕並回應點擊事件。這類需求常見於自訂視窗外觀或需要在標題列額外提供功能鍵的場合。本文介紹一組封裝良好的類別 CNCButton 與 CNCButtonManager,分別負責按鈕繪製與管理、非客戶區訊息處理,讓您輕鬆在標題列等區域加入互動式按鈕。

核心原理:非客戶區訊息處理

Windows 透過特定訊息通知視窗非客戶區的狀態變化,主要涉及三個訊息:

  • WM_NCHITTEST:判斷滑鼠位於非客戶區的哪個部位(如標題列、縮放鈕、自訂按鈕區域)。
  • WM_NCACTIVATE:視窗啟用/停用狀態改變時觸發,需重繪非客戶區以反映狀態。
  • WM_NCPAINT:非客戶區需重繪時觸發,此處繪製自訂按鈕外觀。

CNCButtonManager 內部攔截上述訊息,協助判斷滑鼠是否懸停/點擊自訂按鈕,並觸發對應的 BN_CLICKED 通知訊息,讓開發者能像處理一般按鈕一樣在訊息對應表中回應事件。

快速上手:四步驟整合

1. 引入標頭檔

#include "NCButtonManager.h"
#include "NCButton.h"

2. 定義按鈕 ID

#define ID_BUTTON1 100
#define ID_BUTTON2 101
#define ID_BUTTON3 102

3. 宣告成員變數

於視窗類別(如 CMainFrame)中宣告按鈕與管理器實例:

// Implementation
public:
    CNCButton m_NcButton1;
    CNCButton m_NcButton2;
    CNCButton m_NcButton3;
    CNCButtonManager m_NcButtonManager;

4. 建立與設定按鈕

於 OnCreate 或初始化函式中建立按鈕、設定位置、尺寸、文字、提示、圖示,並加入管理器:

// 按鈕位置與大小(相對視窗左上角偏移)
POINT ptBtn1Offset = {120, 10};
POINT ptBtn2Offset = {20, 32};
POINT ptBtn3Offset = {190, 10};
SIZE sizeBtn1 = {60, 14};
SIZE sizeBtn2 = {16, 14};
SIZE sizeBtn3 = {16, 14};

// 建立按鈕
m_NcButton1.Create("", this->m_hWnd, ptBtn1Offset, sizeBtn1, ID_BUTTON1);
m_NcButton2.Create("", this->m_hWnd, ptBtn2Offset, sizeBtn2, ID_BUTTON2);
m_NcButton3.Create("", this->m_hWnd, ptBtn3Offset, sizeBtn3, ID_BUTTON3);

// 設定文字、工具提示、圖示
m_NcButton1.SetText("VC知識庫", "宋體", 12);
m_NcButton1.SetTooltip("VC知識庫歡迎您!");
m_NcButton2.SetButtonBitmap(IDB_PEN1, BTNBMP_NORMAL);
m_NcButton2.SetButtonBitmap(IDB_PEN2, BTNBMP_MOUSEOVER);
m_NcButton2.SetTooltip("pen");
m_NcButton3.SetButtonBitmap(IDB_PEN1, BTNBMP_NORMAL);
m_NcButton3.SetButtonBitmap(IDB_PEN2, BTNBMP_MOUSEOVER);
m_NcButton3.SetTooltip("pen");

// 註冊到管理器
m_NcButtonManager.AddButton(&m_NcButton1);
m_NcButtonManager.AddButton(&m_NcButton2);
m_NcButtonManager.AddButton(&m_NcButton3);

訊息轉發與回應

1. 轉發非客戶區訊息給管理器

覆寫 DefWindowProc,將訊息傳給 CNCButtonManager 處理:

LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    LRESULT lResult = CFrameWnd::DefWindowProc(message, wParam, lParam);
    if (!IsWindow(this->m_hWnd))
        return lResult;

    LRESULT lMyResult = m_NcButtonManager.DefWindowProc(this->m_hWnd, message, wParam, lParam);
    if (lMyResult != 0)
        return lMyResult;
    else
        return lResult;
}

2. 新增按鈕點擊處理函式

// 標頭檔宣告
void OnNcButton1Clicked();

// 實作
void CMainFrame::OnNcButton1Clicked()
{
    AfxMessageBox("VC知識庫歡迎您! www.vckbase.com");
}

3. 訊息對應表加入 BN_CLICKED

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    //{{AFX_MSG_MAP(CMainFrame)
    ON_BN_CLICKED(ID_BUTTON1, OnNcButton1Clicked)
    ON_BN_CLICKED(ID_BUTTON2, OnNcButton2Clicked)
    ON_BN_CLICKED(ID_BUTTON3, OnNcButton3Clicked)
    ON_WM_CREATE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

效果展示

非客戶區按鈕示意圖

總結

透過 CNCButton 與 CNCButtonManager,開發者無需手寫繁雜的非客戶區訊息處理邏輯,即可在標題列等區域加入功能完整、外觀可自訂的按鈕。此架構封裝良好,易於擴充(如加入按下狀態圖示、右鍵選單等),適合需要高度客製化視窗介面的專案。

本文配套原始碼可供下載參考。

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