Windows学习笔记-13(MFC状态栏Status Bar)

一、状态栏概述

1.1 什么是状态栏

状态栏是Windows应用程序中常见的用户界面元素,通常位于窗口底部,用于显示应用程序状态信息、提示和指示器。在MFC中,状态栏由CStatusBar类封装,它是从CControlBar派生的控件栏。

1.2 状态栏的作用

  • 显示应用程序状态信息

  • 提供菜单项和工具栏按钮的提示信息

  • 显示系统状态(如Caps Lock、Num Lock)

  • 显示进度指示

  • 提供即时反馈

1.3 状态栏组件

  • 窗格(Panes):状态栏被划分为多个矩形区域

  • 指示器(Indicators):显示特定信息的窗格

  • 提示区域(Message Line):通常是最左边的窗格,显示动态信息

二、创建状态栏

2.1 使用MFC向导自动创建

在单文档/多文档应用程序中

使用MFC应用程序向导时,可以选择"初始状态栏"选项,向导会自动生成状态栏代码:

cpp 复制代码
// MainFrm.h
class CMainFrame : public CFrameWnd
{
protected:
    CStatusBar  m_wndStatusBar;
    // ...
};

// MainFrm.cpp
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    // ... 其他代码
    
    // 创建状态栏
    if (!m_wndStatusBar.Create(this) ||
        !m_wndStatusBar.SetIndicators(indicators,
            sizeof(indicators)/sizeof(UINT)))
    {
        TRACE0("Failed to create status bar\n");
        return -1;      // 未能创建
    }
    
    return 0;
}

2.2 手动创建状态栏

步骤1:定义指示器数组

在MainFrm.cpp中定义指示器数组:

cpp 复制代码
// 定义状态栏指示器
static UINT indicators[] =
{
    ID_SEPARATOR,           // 状态行指示器(消息区域)
    ID_INDICATOR_CAPS,      // 大写锁定指示器
    ID_INDICATOR_NUM,       // 数字锁定指示器
    ID_INDICATOR_SCRL,      // 滚动锁定指示器
};

步骤2:在OnCreate中创建

cpp 复制代码
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
    
    // 创建状态栏
    if (!m_wndStatusBar.Create(this))
    {
        TRACE0("Failed to create status bar\n");
        return -1;
    }
    
    // 设置状态栏样式
    m_wndStatusBar.SetIndicators(indicators, 
                                 sizeof(indicators)/sizeof(UINT));
    
    // 可选:设置状态栏窗格宽度
    // 第一个窗格(消息区域)可伸缩,其他固定宽度
    m_wndStatusBar.SetPaneInfo(0, ID_SEPARATOR, SBPS_STRETCH, 0);
    m_wndStatusBar.SetPaneInfo(1, ID_INDICATOR_CAPS, SBPS_NORMAL, 40);
    m_wndStatusBar.SetPaneInfo(2, ID_INDICATOR_NUM, SBPS_NORMAL, 40);
    m_wndStatusBar.SetPaneInfo(3, ID_INDICATOR_SCRL, SBPS_NORMAL, 40);
    
    return 0;
}

2.3 在对话框中创建状态栏

cpp 复制代码
// 对话框类声明
class CMyDialog : public CDialog
{
protected:
    CStatusBar m_wndStatusBar;
    
protected:
    virtual BOOL OnInitDialog();
    // ...
};

// 对话框初始化
BOOL CMyDialog::OnInitDialog()
{
    CDialog::OnInitDialog();
    
    // 创建状态栏
    if (!m_wndStatusBar.Create(this))
    {
        TRACE0("Failed to create status bar\n");
        return FALSE;
    }
    
    // 定义指示器
    static UINT indicators[] =
    {
        ID_SEPARATOR,
        ID_INDICATOR_CAPS,
        ID_INDICATOR_NUM,
    };
    
    // 设置指示器
    m_wndStatusBar.SetIndicators(indicators, 
                                 sizeof(indicators)/sizeof(UINT));
    
    // 调整对话框大小以容纳状态栏
    CRect rcClient;
    GetClientRect(&rcClient);
    
    CRect rcStatusBar;
    m_wndStatusBar.GetClientRect(&rcStatusBar);
    
    // 调整客户区
    rcClient.bottom -= rcStatusBar.Height();
    MoveWindow(&rcClient);
    
    // 定位状态栏
    m_wndStatusBar.SetWindowPos(NULL, 
                                0, rcClient.Height(),
                                rcClient.Width(), rcStatusBar.Height(),
                                SWP_NOZORDER | SWP_SHOWWINDOW);
    
    return TRUE;
}

三、状态栏样式和特性

3.1 创建样式

cpp 复制代码
// 使用CreateEx创建具有特定样式的状态栏
BOOL CreateStatusBar()
{
    // 创建状态栏
    return m_wndStatusBar.CreateEx(this, 
        SBARS_SIZEGRIP,  // 包含大小调整手柄
        WS_CHILD | WS_VISIBLE | CBRS_BOTTOM,
        ID_VIEW_STATUS_BAR);
}

// 或者使用Create函数
BOOL CreateStatusBar()
{
    DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM;
    return m_wndStatusBar.Create(this, dwStyle, ID_VIEW_STATUS_BAR);
}

3.2 状态栏样式常量

样式常量 描述
SBARS_SIZEGRIP 包含大小调整手柄
CBRS_TOP 停靠在顶部
CBRS_BOTTOM 停靠在底部(默认)
CBRS_NOALIGN 父窗口调整大小时不重新定位

3.3 窗格样式常量

样式常量 描述
SBPS_NOBORDERS 无3D边框
SBPS_POPOUT 凸出边框
SBPS_NORMAL 正常(凹陷)边框
SBPS_DISABLED 禁用,不显示文本
SBPS_STRETCH 拉伸窗格,填满剩余空间
SBPS_OWNERDRAW 自绘窗格

四、状态栏操作

4.1 添加和配置窗格

cpp 复制代码
// 动态添加窗格
BOOL AddPane(UINT nID, int nWidth = 100, UINT nStyle = SBPS_NORMAL)
{
    // 获取当前指示器数量
    int nCount = m_wndStatusBar.GetStatusBarCtrl().GetParts(0, NULL);
    
    // 创建新的指示器数组
    UINT* pIndicators = new UINT[nCount + 2]; // +1 为新窗格,+1 为终止符0
    
    // 复制现有指示器
    for (int i = 0; i < nCount; i++)
    {
        UINT nIDCurrent = m_wndStatusBar.GetItemID(i);
        pIndicators[i] = nIDCurrent;
    }
    
    // 添加新指示器
    pIndicators[nCount] = nID;
    pIndicators[nCount + 1] = 0; // 终止符
    
    // 设置新的指示器数组
    BOOL bSuccess = m_wndStatusBar.SetIndicators(pIndicators, nCount + 1);
    
    delete[] pIndicators;
    
    if (bSuccess)
    {
        // 设置新窗格的宽度和样式
        m_wndStatusBar.SetPaneInfo(nCount, nID, nStyle, nWidth);
    }
    
    return bSuccess;
}

// 配置现有窗格
void ConfigurePane(int nIndex, UINT nID, int nWidth, UINT nStyle)
{
    m_wndStatusBar.SetPaneInfo(nIndex, nID, nStyle, nWidth);
}

// 获取窗格信息
void GetPaneInfo(int nIndex)
{
    UINT nID, nStyle;
    int nWidth;
    
    m_wndStatusBar.GetPaneInfo(nIndex, nID, nStyle, nWidth);
    
    TRACE(_T("Pane %d: ID=%d, Style=%d, Width=%d\n"), 
          nIndex, nID, nStyle, nWidth);
}

4.2 显示文本信息

cpp 复制代码
// 在指定窗格显示文本
void ShowMessage(LPCTSTR lpszMessage, int nPane = 0, BOOL bUpdate = TRUE)
{
    m_wndStatusBar.SetPaneText(nPane, lpszMessage);
    
    if (bUpdate)
    {
        m_wndStatusBar.UpdateWindow();
    }
}

// 格式化文本显示
void ShowFormattedMessage(int nPane, LPCTSTR lpszFormat, ...)
{
    CString strMessage;
    
    va_list args;
    va_start(args, lpszFormat);
    strMessage.FormatV(lpszFormat, args);
    va_end(args);
    
    m_wndStatusBar.SetPaneText(nPane, strMessage);
}

// 获取窗格文本
CString GetPaneText(int nPane)
{
    CString strText;
    m_wndStatusBar.GetPaneText(nPane, strText);
    return strText;
}

// 临时消息显示(定时消失)
void ShowTemporaryMessage(LPCTSTR lpszMessage, int nTimeout = 3000)
{
    // 保存当前消息
    static CString s_strSavedMessage;
    static int s_nSavedPane = 0;
    
    s_nSavedPane = 0; // 假设使用第一个窗格
    m_wndStatusBar.GetPaneText(s_nSavedPane, s_strSavedMessage);
    
    // 显示新消息
    m_wndStatusBar.SetPaneText(s_nSavedPane, lpszMessage);
    
    // 设置定时器恢复原消息
    SetTimer(ID_TIMER_RESTORE_MESSAGE, nTimeout, NULL);
}

// 处理定时器消息恢复原消息
void CMainFrame::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == ID_TIMER_RESTORE_MESSAGE)
    {
        KillTimer(ID_TIMER_RESTORE_MESSAGE);
        m_wndStatusBar.SetPaneText(0, s_strSavedMessage);
    }
    
    CFrameWnd::OnTimer(nIDEvent);
}

4.3 启用/禁用窗格

cpp 复制代码
// 启用或禁用窗格
void EnablePane(int nIndex, BOOL bEnable)
{
    UINT nID, nStyle;
    int nWidth;
    
    m_wndStatusBar.GetPaneInfo(nIndex, nID, nStyle, nWidth);
    
    if (bEnable)
    {
        nStyle &= ~SBPS_DISABLED;
    }
    else
    {
        nStyle |= SBPS_DISABLED;
    }
    
    m_wndStatusBar.SetPaneInfo(nIndex, nID, nStyle, nWidth);
}

// 显示/隐藏窗格
void ShowPane(int nIndex, BOOL bShow)
{
    // 通过设置宽度为0来隐藏窗格
    UINT nID, nStyle;
    int nWidth;
    
    m_wndStatusBar.GetPaneInfo(nIndex, nID, nStyle, nWidth);
    
    if (bShow)
    {
        // 恢复原始宽度(需要提前保存)
        static std::map<int, int> s_mapPaneWidths;
        
        if (s_mapPaneWidths.find(nIndex) != s_mapPaneWidths.end())
        {
            nWidth = s_mapPaneWidths[nIndex];
        }
        else
        {
            nWidth = 100; // 默认宽度
        }
    }
    else
    {
        // 保存宽度并设置为0
        static std::map<int, int> s_mapPaneWidths;
        s_mapPaneWidths[nIndex] = nWidth;
        nWidth = 0;
    }
    
    m_wndStatusBar.SetPaneInfo(nIndex, nID, nStyle, nWidth);
    m_wndStatusBar.Invalidate();
}
相关推荐
时代的凡人8 小时前
0208晨间笔记
笔记
今天只学一颗糖8 小时前
1、《深入理解计算机系统》--计算机系统介绍
linux·笔记·学习·系统架构
testpassportcn9 小时前
AWS DOP-C02 認證完整解析|AWS DevOps Engineer Professional 考試
网络·学习·改行学it
游乐码12 小时前
c#变长关键字和参数默认值
学习·c#
饭碗、碗碗香13 小时前
【Python学习笔记】:Python的hashlib算法简明指南:选型、场景与示例
笔记·python·学习
Wils0nEdwards13 小时前
初中化学1
笔记
魔力军13 小时前
Rust学习Day4: 所有权、引用和切片介绍
开发语言·学习·rust
wubba lubba dub dub75014 小时前
第三十六周 学习周报
学习
学编程的闹钟14 小时前
PHP字符串表示方式全解析
学习
Lbs_gemini060314 小时前
01-01-01 C++编程知识 C++入门 工具安装
c语言·开发语言·c++·学习·算法