1、相关类
CStatusBar -父类CControlBar,封装了关于状态栏的操作,也包括状态栏的创建
2、状态栏的使用
2.1创建状态栏 CStatusBar::CreateEx / CStatusBar::Create
BOOL CreateEx(
CWnd* pParentWnd, //指定状态栏的父窗口指针,通常都是指向程序的框架类窗口对象
DWORD dwCtrlStyle = 0 , //设置内嵌在状态栏上的CStatusBarCtrl对象创建时的扩展风格
DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, //状态栏的风格
UINT nID = AFX_IDW_STATUS_BAR //指定状态栏这个子窗口的ID,默认为AFX_IDW_STATUS_BAR
);
BOOL Create(
CWnd* pParentWnd, //指定状态栏的父窗口指针,通常都是指向程序的框架类窗口对象
DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, //状态栏的风格
UINT nID = AFX_IDW_STATUS_BAR //指定状态栏这个子窗口的ID,默认为AFX_IDW_STATUS_BAR
);
在程序的CMainFrame类的OnCreate函数中可见MFC自动创建状态栏的方法:
if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(
indicators,sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
SetIndicators函数的第一个参数indicators为一个静态数组,其定义在CMainFrame类的源文件中:
static UINT indicators[] =
{
ID_SEPARATOR, //提示行
ID_INDICATOR_CAPS, //Caps Lock键的状态指示器
ID_INDICATOR_NUM, //Num Lock键的状态指示器
ID_INDICATOR_SCRL, //Scroll Lock键的状态指示器
};
该数组中的后3个ID都是MFC预先定义好的字符串资源ID,在工程的资源窗口中的String Table的字串表中可见:

若要修改状态栏的外观,如添加或减少状态栏上的窗格,只需要在indicators数组中添加或减少相应的字符串资源ID即可;
2.2设置状态栏指示器(窗格)
CStatusBar::SetIndicators
2.3设置指示器(窗格)的宽度和风格
CStatusBar::SetPaneInfo
void SetPaneInfo(
int nIndex, //指定要设置其样式的窗格的位置索引
UINT nID, //为指定窗格重新设置的新ID
UINT nStyle, //窗格的样式:SBPS_NORMAL/SBPS_STRETCH/SBPS_DISABLED/SBPS_POPOUT/SBPS_NOBORDERS
int cxWidth //指定窗格的宽度
);
2.4设置指示器(窗格)的文本内容
CStatusBar::SetPaneText
BOOL SetPaneText(
int nIndex, //当前窗格在指示器数组(indicators)中的位置索引
LPCTSTR lpszNewText, //要在当前窗格中显示的文本
BOOL bUpdate = TRUE
);
若不知道当前窗格在指示器数组(indicators)中的位置索引,可利用CStatusBar::CommandToIndex
int CommandToIndex( UINT nIDFind ); //根据指定的资源ID获得相应的位置索引
本例将在状态栏上显示当前系统的时间和一个进度条控件:
1、显示系统时间
在程序资源窗口中的字串表中增加两个新的字符串资源:
![]()
将这两个新的字符串资源ID添加到CMainFrame类的源文件中的indicators数组中:
static UINT indicators[] =
{
ID_SEPARATOR,
IDS_TIMER,
IDS_PROGRESS,
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
利用CTime类的静态成员函数GetCurrentTime获取系统当前的时间对象;再调用CTime类的另一个成员函数Format对得到的时间对象进行格式化,得到一个包含格式化时间的字符串;调用SetPaneInfo函数修改窗格的显示宽度以装下将要显示的字符串文本;调用SetPaneText函数将该字符串显示到状态栏的窗格中;
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
CTime t=CTime::GetCurrentTime();
CString str=t.Format("%Y-%m-%d %H:%M:%S");
CClientDC dc(this);
CSize sz=dc.GetTextExtent(str);
m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx);
m_wndStatusBar.SetPaneText(1,str);
return 0;
}
此时在状态栏窗格中显示的时间是静止的,利用定时器每隔一秒就发送WM_TIMER消息,在消息响应函数OnTimer中重新获取一次系统当前时间并显示到状态栏窗格中,已达到显示动态时间的效果;
在CMainFrame类的OnCreate函数中埋下定时器:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
SetTimer(1,1000,NULL);
return 0;
}
为CMainFrame类添加WM_TIMER消息,生成消息响应函数OnTimer,在该函数中重新执行一次系统时间的获取并显示到状态栏窗格中:
void CMainFrame::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CTime t=CTime::GetCurrentTime();
CString str=t.Format("%Y-%m-%d %H:%M:%S");
CClientDC dc(this);
CSize sz=dc.GetTextExtent(str);
m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx);
m_wndStatusBar.SetPaneText(1,str);
CFrameWnd::OnTimer(nIDEvent);
}
2、进度条控件
要在程序中使用进度栏,首先需要构造一个CProgressCtrl对象,然后调用CProgressCtrl类的Create函数创建进度栏控件;
BOOL Create(
DWORD dwStyle, //进度栏控件的类型,窗口所有的类型+PBS_VERTICAL(进度栏垂直)/PBS_SMOOTH(进度栏连续)
const RECT& rect, //进度栏控件的大小、位置
CWnd* pParentWnd, //进度栏的父窗口
UINT nID //指定进度栏控件的ID
);
在程序的CMainFrame类中添加成员变量:CProgressCtrl m_progress

要在状态栏的窗格中显示进度栏,首先利用GetItemRect函数获得该窗格的区域大小:
void GetItemRect(int nIndex, LPRECT lpRect ) const;
nIndex:指定窗格的位置索引
lpRect:窗格的矩形区域
当程序窗口第一次显示时就会发送WM_PAINT消息,而且当程序的窗口尺寸发生变化需要重绘时也会发送WM_PAINT消息,故可在WM_PAINT消息的响应函数中判断,若程序还未创建进度栏则创建它,若已创建则将进度栏移动至目标窗格的矩形区域中;
为CMainFrame类添加WM_PAINT消息的响应函数:
void CMainFrame::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CRect rect;
m_wndStatusBar.GetItemRect(2,&rect); //获得状态栏中窗格的矩形区域
if(!m_progress.m_hWnd){ //判断当m_progress对象的句柄为NULL时,说明该对象还未创建,则创建进度栏
m_progress.Create(WS_CHILD|WS_VISIBLE,rect,&m_wndStatusBar,123); //创建进度栏
}else{
m_progress.MoveWindow(rect); //将进度栏移至目标矩形中
}
m_progress.SetPos(50); //设置进度栏的当前进度
// Do not call CFrameWnd::OnPaint() for painting messages
}
若要实现进度栏进度的动态增加,需要利用定时器,在WM_TIMER消息的响应函数OnTimer函数中实现:
void CMainFrame::OnTimer(UINT nIDEvent)
{
......
m_progress.StepIt();
CFrameWnd::OnTimer(nIDEvent);
}
CProgressCtrl::StepIt:使进度栏控件的进度按照一定的步长增加
CProgressCtrl::SetStep:设置进度栏每次增加的步长
CProgressCtrl::SetRange:设置进度栏的范围,默认为0~100
3、在状态栏上显示鼠标当前的位置
当在程序的客户区窗口移动鼠标时,将鼠标当前的坐标位置显示在状态栏的提示行上;
首先需要在程序的CStyleView类中添加WM_MOUSEMOVE消息的响应函数:

因为GetParent函数返回的为CWnd类型的指针,需要强制转换为CMainFrame类型的指针,故须在视图类的源文件中包含框架类的头文件:
#include "MainFrm.h"
在WM_MOUSEMOVE消息的响应函数中,实现状态栏对象的获取及在其窗格中的文本显示:
void CStyleView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CString str;
str.Format("x=%d,y=%d",point.x,point.y); //格式化鼠标坐标位置的信息
//通过调用GetParent函数获取视图类的父窗口即框架类窗口,将返回值强制转换后,调用框架窗口对象中的状态栏成员变量
((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);
CView::OnMouseMove(nFlags, point);
}
将鼠标当前位置信息显示到状态栏对象的提示行中的方法:
方法一:SetWindowText
框架类CMainFrame类的状态栏成员变量m_wndStatusBar默认在CMainFrame类的头文件中被定义为protected类型,须手动将其修改为public类型才能被调用;
方法二:CFrameWnd类的成员函数:SetMessageText
该函数的作用即为在ID为0的状态栏窗格(即提示行)设置一个字符串;因程序框架类CMainFrame类派生于CFrameWnd类,故这里可以直接用框架类对象调用该成员函数来设置状态栏文本;
void CStyleView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CString str;
str.Format("x=%d,y=%d",point.x,point.y);
//((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);
((CMainFrame*)GetParent())->SetMessageText(str);
CView::OnMouseMove(nFlags, point);
}
方法三:CFrameWnd类的成员函数:GetMessageBar
该函数返回状态栏对象的指针,故无须像方法一那样修改并调用CMainFrame类的保护成员变量m_wndStatusBar了,可直接调用SetWindowText函数设置状态栏的第一个窗格(提示行)的文本;
void CStyleView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CString str;
str.Format("x=%d,y=%d",point.x,point.y);
//((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);
//((CMainFrame*)GetParent())->SetMessageText(str);
((CMainFrame*)GetParent())->GetMessageBar()->SetWindowText(str);
CView::OnMouseMove(nFlags, point);
}
方法四:CWnd类的成员函数:GetDescendantWindow
该函数可通过指定的ID来获得当前窗口的所有子孙窗口,因状态栏属于框架类窗口,故先要得到框架类窗口的指针,然后根据状态栏的窗口ID调用该函数获得状态栏对象的指针
void CStyleView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CString str;
str.Format("x=%d,y=%d",point.x,point.y);
//((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);
//((CMainFrame*)GetParent())->SetMessageText(str);
//((CMainFrame*)GetParent())->GetMessageBar()->SetWindowText(str);
GetParent()->GetDescendantWindow(AFX_IDW_STATUS_BAR)->SetWindowText(str);
CView::OnMouseMove(nFlags, point);
}
原文:http://www.cnblogs.com/zhouwanqiu/p/6918657.html