VC++中状态栏的动态编程Visual C++
摘 要 本文介绍了一种在Visual C++ 6.0中动态改变状态栏内的字符串并在状态栏中动态显示图标的方法。关键词 Visual C++,状态栏,CStatusBar 一、引言在应用程序的状态栏上显示一个不断变化的字符串,例如,当程序运行时在状态栏显示当前的系统时间,如再在状态栏上加上动画式图标将为您的程序增色不少。有一些文章也介绍过VC中状态栏的动态编程,可在具体实现的时候并不能让人满意。经过一定的研究,我这里提供一种动态改变状态栏的方法,可以很好地实现状态栏的动态改变,并在状态栏中加入动画图标。二、实现原理首先,在CMainFrame类中添加InitStatusBar函数用来对我们的状态栏进行初始化,利用CMainFrame类中的CStatusBar类成员变量m_wndStatusBar来实现对状态栏的控制。
在InitStatusBar函数中还将初始化一个CImageList类变量m_BarImage,用它在状态栏中显示图标。
还要在CMainFrame类中添加OnUpdateMyStatus函数用以响应状态栏更新消息,还可在CMainFrame类中添加OnTimer函数响应WM_TIMER消息,并在OnTimer函数体内改变将要显示的字符串和图标。三、具体实现
1.用Visual C++ 6.0创建一个单文档工程Test,确认在创建过程中选中了Initial status bar选项。在资源中插入一个新位图资源IDB_BITMAP1,用十种不同的颜色在位图中画十个大小为16×16的实心圆。
2.打开MainFrm.h,添加如下变量定义:// MainFrm.h : interface of the CMainFrame class///////////////////////////////////////////////////////////////////////////////class CMainFrame : public CFrameWnd{ ··· ···// Implementationpublic: CString TimeTextOld;//存储当前状态栏显示时间的变量 CString TimeText;// 存储当前时间的变量 int m_ImageNo;//存储状态栏显示的图标序号的变量 BOOL InitStatusBar(UINT *pIndicators,int nSize);//初始化状态栏函数 int m_MyPane;//状态栏中我们自己添加的窗格号 virtual ~CMainFrame();#ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const;#endif protected: // control bar embedded members CStatusBar m_wndStatusBar; CToolBar m_wndToolBar; // Generated message map functionsprotected: CImageList m_BarImage; //{{AFX_MSG(CMainFrame) afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnUpdateMyStatus(CCmdUI* pCmdUI);//更新MyPane窗格的函数 afx_msg void OnTimer(UINT nIDEvent);//WM_TIMER响应函数 //}}AFX_MSG DECLARE_MESSAGE_MAP()}; ··· ···///////////////////////////////////////////////////////////////////////////// 3.在CMainFrame类中添加BOOL CMainFrame::InitStatusBar(UINT *pIndicators, int nSize),在InitStatusBar函数中加入如下代码:BOOL CMainFrame::InitStatusBar(UINT *pIndicators, int nSize){ //在状态栏指示器中增加ID_INDICATOR_MY窗格 m_MyPane=nSize++; pIndicators[m_MyPane] =ID_INDICATOR_MY; //用位图资源IDB_BITMAP1创建CImageList对象,IDB_BITMAP1可以是一堆位图,笔者就是用十种颜色在IDB_BITMAP1中画了十个大小为16×16的实心圆 m_BarImage.Create (IDB_BITMAP1,16,16,RGB(192,192,192));//在InitStatusBar函数返回前用SetTimer(1, 300, NULL)安装定时器 SetTimer(1, 300, NULL); return m_wndStatusBar.SetIndicators(pIndicators, nSize); } 4.在CMainFrame类中添加WM_TIMER消息响应函数OnTimer(UINT nIDEvent),在OnTimer函数中加入:void CMainFrame::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default//获得当前时间并转换成CString变量TimeText,在更新状态栏时将TimeText字符串显示在状态栏上 CTime time=CTime::GetCurrentTime(); TimeText=time.Format(" %Y年%m月%d日 %A 当前时间 %X"); //显示的位图序号为秒数的个位数字 m_ImageNo=time.GetSecond()%10; //CFrameWnd::OnTimer(nIDEvent);} 5.在CMainFrame类中添加ID_INDICATOR_MY 的消息响应函数:OnUpdateMyStatus(CCmdUI* pCmdUI),在OnUpdateMyStatus(CCmdUI* pCmdUI)中添加:void CMainFrame::OnUpdateMyStatus(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here//TimeTextOld是当前状态栏中所显示的字符串,if条件语句是为防止状态栏被不必要地更新,这样只有在时间发生改变时才更新状态栏可避免闪烁 if(TimeText!=TimeTextOld) { //更新MyPane窗格中显示的字符串 pCmdUI->SetText(TimeText); TimeTextOld=TimeText; CDC* pDC = m_wndStatusBar.GetDC(); RECT m_PaneRect; CPoint m_PanePoint; //GetItemRect函数用来获得状态栏的位置信息 m_wndStatusBar.GetItemRect(m_MyPane, (LPRECT)&m_PaneRect); //将m_PaneRect矩形区域的左上角坐标赋给m_PanePoint m_PanePoint.x=m_PaneRect.left; m_PanePoint.y=m_PaneRect.top; //在状态栏m_PanePoint处显示第m_ImageNo号位图 m_BarImage.Draw(pDC,m_ImageNo,m_PanePoint,ILD_NORMAL); }} 6.在CMainFrame类的 CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)函数中添加代码如下:int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){ ··· ··· //用GetPaneInfo和SetPaneInfo函数重新设置状态栏ID_INDICATOR_MY的宽度为300象素 //nID,nStyle和nWidth为临时变量用来接收GetPaneInfo返回的数据 UINT nID,nStyle; int nWidth; m_wndStatusBar.GetPaneInfo(m_MyPane, nID, nStyle, nWidth); m_wndStatusBar.SetPaneInfo(m_MyPane, nID, nStyle, 300); return 0;}
摘 要 本文介绍了一种在Visual C++ 6.0中动态改变状态栏内的字符串并在状态栏中动态显示图标的方法。关键词 Visual C++,状态栏,CStatusBar 一、引言在应用程序的状态栏上显示一个不断变化的字符串,例如,当程序运行时在状态栏显示当前的系统时间,如再在状态栏上加上动画式图标将为您的程序增色不少。有一些文章也介绍过VC中状态栏的动态编程,可在具体实现的时候并不能让人满意。经过一定的研究,我这里提供一种动态改变状态栏的方法,可以很好地实现状态栏的动态改变,并在状态栏中加入动画图标。二、实现原理首先,在CMainFrame类中添加InitStatusBar函数用来对我们的状态栏进行初始化,利用CMainFrame类中的CStatusBar类成员变量m_wndStatusBar来实现对状态栏的控制。
在InitStatusBar函数中还将初始化一个CImageList类变量m_BarImage,用它在状态栏中显示图标。
还要在CMainFrame类中添加OnUpdateMyStatus函数用以响应状态栏更新消息,还可在CMainFrame类中添加OnTimer函数响应WM_TIMER消息,并在OnTimer函数体内改变将要显示的字符串和图标。三、具体实现
1.用Visual C++ 6.0创建一个单文档工程Test,确认在创建过程中选中了Initial status bar选项。在资源中插入一个新位图资源IDB_BITMAP1,用十种不同的颜色在位图中画十个大小为16×16的实心圆。
2.打开MainFrm.h,添加如下变量定义:// MainFrm.h : interface of the CMainFrame class///////////////////////////////////////////////////////////////////////////////class CMainFrame : public CFrameWnd{ ··· ···// Implementationpublic: CString TimeTextOld;//存储当前状态栏显示时间的变量 CString TimeText;// 存储当前时间的变量 int m_ImageNo;//存储状态栏显示的图标序号的变量 BOOL InitStatusBar(UINT *pIndicators,int nSize);//初始化状态栏函数 int m_MyPane;//状态栏中我们自己添加的窗格号 virtual ~CMainFrame();#ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const;#endif protected: // control bar embedded members CStatusBar m_wndStatusBar; CToolBar m_wndToolBar; // Generated message map functionsprotected: CImageList m_BarImage; //{{AFX_MSG(CMainFrame) afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnUpdateMyStatus(CCmdUI* pCmdUI);//更新MyPane窗格的函数 afx_msg void OnTimer(UINT nIDEvent);//WM_TIMER响应函数 //}}AFX_MSG DECLARE_MESSAGE_MAP()}; ··· ···///////////////////////////////////////////////////////////////////////////// 3.在CMainFrame类中添加BOOL CMainFrame::InitStatusBar(UINT *pIndicators, int nSize),在InitStatusBar函数中加入如下代码:BOOL CMainFrame::InitStatusBar(UINT *pIndicators, int nSize){ //在状态栏指示器中增加ID_INDICATOR_MY窗格 m_MyPane=nSize++; pIndicators[m_MyPane] =ID_INDICATOR_MY; //用位图资源IDB_BITMAP1创建CImageList对象,IDB_BITMAP1可以是一堆位图,笔者就是用十种颜色在IDB_BITMAP1中画了十个大小为16×16的实心圆 m_BarImage.Create (IDB_BITMAP1,16,16,RGB(192,192,192));//在InitStatusBar函数返回前用SetTimer(1, 300, NULL)安装定时器 SetTimer(1, 300, NULL); return m_wndStatusBar.SetIndicators(pIndicators, nSize); } 4.在CMainFrame类中添加WM_TIMER消息响应函数OnTimer(UINT nIDEvent),在OnTimer函数中加入:void CMainFrame::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default//获得当前时间并转换成CString变量TimeText,在更新状态栏时将TimeText字符串显示在状态栏上 CTime time=CTime::GetCurrentTime(); TimeText=time.Format(" %Y年%m月%d日 %A 当前时间 %X"); //显示的位图序号为秒数的个位数字 m_ImageNo=time.GetSecond()%10; //CFrameWnd::OnTimer(nIDEvent);} 5.在CMainFrame类中添加ID_INDICATOR_MY 的消息响应函数:OnUpdateMyStatus(CCmdUI* pCmdUI),在OnUpdateMyStatus(CCmdUI* pCmdUI)中添加:void CMainFrame::OnUpdateMyStatus(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here//TimeTextOld是当前状态栏中所显示的字符串,if条件语句是为防止状态栏被不必要地更新,这样只有在时间发生改变时才更新状态栏可避免闪烁 if(TimeText!=TimeTextOld) { //更新MyPane窗格中显示的字符串 pCmdUI->SetText(TimeText); TimeTextOld=TimeText; CDC* pDC = m_wndStatusBar.GetDC(); RECT m_PaneRect; CPoint m_PanePoint; //GetItemRect函数用来获得状态栏的位置信息 m_wndStatusBar.GetItemRect(m_MyPane, (LPRECT)&m_PaneRect); //将m_PaneRect矩形区域的左上角坐标赋给m_PanePoint m_PanePoint.x=m_PaneRect.left; m_PanePoint.y=m_PaneRect.top; //在状态栏m_PanePoint处显示第m_ImageNo号位图 m_BarImage.Draw(pDC,m_ImageNo,m_PanePoint,ILD_NORMAL); }} 6.在CMainFrame类的 CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)函数中添加代码如下:int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){ ··· ··· //用GetPaneInfo和SetPaneInfo函数重新设置状态栏ID_INDICATOR_MY的宽度为300象素 //nID,nStyle和nWidth为临时变量用来接收GetPaneInfo返回的数据 UINT nID,nStyle; int nWidth; m_wndStatusBar.GetPaneInfo(m_MyPane, nID, nStyle, nWidth); m_wndStatusBar.SetPaneInfo(m_MyPane, nID, nStyle, 300); return 0;}
但是大家在使用的时候要注意哈。
在OnCreate中修改:
if (!m_wndStatusBar.Create(this) ||
!InitStatusBar(indicators,sizeof(indicators)/sizeof(UINT)))
// !m_wndStatusBar.SetIndicators(indicators,
// sizeof(indicators)/sizeof(UINT)))
嘻嘻,不然,是不行的哦