zoukankan      html  css  js  c++  java
  • 状态栏

    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
    ");
        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);
    }
    
  • 相关阅读:
    C,LINUX,数据结构部分
    LINUX应用开发工程师职位(含答案)
    INT32 System_UserKeyFilter(NVTEVT evt, UINT32 paramNum, UINT32 *paramArray)
    屏幕调试
    1.ARM嵌入式体系结构与接口技术(Cortex-A8版)
    NT9666X调试log
    DemoKit编译过程错误
    selenium 代理设置
    pandas 轮询dataframe
    Spring 定时任务
  • 原文地址:https://www.cnblogs.com/zhouwanqiu/p/6918657.html
Copyright © 2011-2022 走看看