状态栏编程

来源:互联网 发布:沥青抽提试验数据 编辑:程序博客网 时间:2024/06/05 04:40
系统生成的状态栏代码在MainFrame的OnCreate()中
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
}

indicators为状态栏指示器数组,在MainFrame中定义
static UINT indicators[] =
{
ID_SEPARATOR,           // 最左边的窗格
IDS_TIMER,         //自己添加的时间窗格
IDS_PROGRESS,   //自己添加的进度条窗格
ID_INDICATOR_CAPS,    // 大小写窗格
ID_INDICATOR_NUM,     // 数字窗格
ID_INDICATOR_SCRL,    // 滚动窗格
};

下面实现一个功能:在时间窗格显示系统时间:
先在MainFrame的OnCreate()中添加一个定时器:
SetTimer(1,1000,NULL);

再添加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("%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);
}

下面实现一个功能:在进度条窗格添加一个进度条
先在MainFrame头文件中添加一个进度条对象:
CProgressCtrl m_progress;

只有MainFrame的OnCreate()函数执行完成后,状态栏的初始化
工作才完成。而我们要将进度条放入状态栏的窗格中,那我们可以
通过PostMessage()来发送自定义消息来实现。
在MainFrame的OnCreate()中PostMessage(),
PostMessage(UM_PROGRESS);
发送消息到队列中后立即返回OnCreate()函数,
OnCreate()函数执行完毕后状态栏初始化完成,
接着处理OnProgress()来创建进度条


首先在MainFrame的头文件中自定义一条用户信息:
#define UM_PROGRESSWM_USER+1

接着MainFrame的头文件中声明自定义的消息响应函数:(红色部分)
protected:
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnTest();
afx_msg void OnViewNewtool();
afx_msg void OnUpdateViewNewtool(CCmdUI* pCmdUI);
afx_msg void OnPaint();
//}}AFX_MSG
afx_msg void OnProgress();

在MainFrame的源文件添加消息映射(红色部分)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_WM_TIMER()
ON_COMMAND(IDM_TEST, OnTest)
ON_COMMAND(IDM_VIEW_NEWTOOL, OnViewNewtool)
ON_UPDATE_COMMAND_UI(IDM_VIEW_NEWTOOL, OnUpdateViewNewtool)
ON_WM_PAINT()
//}}AFX_MSG_MAP
ON_MESSAGE(UM_PROGRESS,OnProgress)

函数实现:
void CMainFrame::OnProgress()
{
CRect rect;
m_wndStatusBar.GetItemRect(2,&rect);  //获得该窗格矩形区域
//在该矩形区域中创建进度条
m_progress.Create(WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
rect,&m_wndStatusBar,123);
//设置进度条初始值(进度位置,最大100)
m_progress.SetPos(50);
}

以上代码运行后正常,单如果拉大或缩小窗口就出问题了
进度条不在原先的窗格内了
窗口尺寸改变引发重绘,可以在MainFrame的OnPaint()
中加载进度条
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.Create(WS_CHILD | WS_VISIBLE ,//| PBS_SMOOTH,
rect,&m_wndStatusBar,123);
else
m_progress.MoveWindow(rect);   //移动进度条到新矩形中
m_progress.SetPos(50);

// Do not call CFrameWnd::OnPaint() for painting messages
}
这时候,就不用发送自定义的那条消息了。因为当窗口第一次显示时,
就会调用OnPaint函数,这样就得到了窗格区域创建进度条

要想进度条动起来,在OnTimer中加入代码:
m_progress.StepIt();


再实现一个功能,鼠标在窗口移动时,第一窗格记录坐标
为View添加OnMouseMove()响应函数:
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);
//方式1:
((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);

//方式2:
((CMainFrame*)GetParent())->SetMessageText(str);

//方式3:
((CMainFrame*)GetParent())->GetMessageBar()->SetWindowText(str);

//方式4:
GetParent()->GetDescendantWindow(AFX_IDW_STATUS_BAR)->SetWindowText(str);

CView::OnMouseMove(nFlags, point);
}