孙鑫vc++第九讲 状态栏 工具栏 进度条

CREATESTRUCT Structure
The CREATESTRUCT structure has the following form:

typedef struct tagCREATESTRUCT {
   LPVOID    lpCreateParams;
   HANDLE    hInstance;
   HMENU     hMenu;
   HWND      hwndParent;
   int       cy;
   int       cx;
   int       y;
   int       x;
   LONG      style;
   LPCSTR    lpszName;
   LPCSTR    lpszClass;
   DWORD     dwExStyle;
} CREATESTRUCT
由于单文档默认具有FWS_ADDTOTITLE属性,所以直接在PreCreateWindow函数中修改不能成功,应该先将该属性去掉。
代码:
   cs.style &= ~FWS_ADDTOTITLE;
    cs.lpszName = "xioxu";
    窗口创建之前在PreCreateWindow函数内修改窗体,窗口创建后可以用API函数SetWindowLong()修改。
    GetWindowLong()获取窗口信息。
    在OnCreate()函数中去处最大化小方框
      ::SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE) & ~ WS_MAXIMIZEBOX);
      MFC中的全局函数HINSTANCE AfxGetInstanceHandle( );用来获取应用程序当前运行实例的句柄。
    DefWindowProc
   The DefWindowProc function calls the default window procedure to provide default processing for any window messages that an application does not process. This function ensures that every message is processed. DefWindowProc is called with the same parameters received by the window procedure.
   
   LRESULT DefWindowProc(
     HWND hWnd,      // handle to window
     UINT Msg,       // message identifier
     WPARAM wParam,  // first message parameter
     LPARAM lParam   // second message parameter
   );
   
   在MainFrame中的PreCreateWindow中自己创建一个窗口类,然后注册,在此调用自己的窗口类看不出来,因为只改变了MainFrame的窗口,外边还有view窗口盖着,所以应该在view窗口中使用我们创建的窗口类。
   在view类的PreCreateWindow函数中将cs的lpszClass属性改变为我们创建类的名字就是使用了。
   BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
     {
      if( !CFrameWnd::PreCreateWindow(cs) )
       return FALSE;
      // TODO: Modify the Window class or styles here by modifying
     
      WNDCLASS wnd;
      wnd.cbClsExtra = 0;
      wnd.cbWndExtra = 0;
      wnd.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
      wnd.hCursor = LoadCursor(NULL,IDC_HELP);
      wnd.hIcon = LoadIcon(NULL,IDI_ERROR);
      wnd.hInstance = ::AfxGetInstanceHandle();//获取当前实例句柄
      wnd.lpfnWndProc = ::DefWindowProc;
      wnd.lpszClassName = "xioxu";
      wnd.lpszMenuName = NULL;
      wnd.style = CS_HREDRAW | CS_VREDRAW;
      
      ::RegisterClass(&wnd);
      
      return TRUE;
     }
     
     BOOL CDlgProView::PreCreateWindow(CREATESTRUCT& cs)
        {
         // TODO: Modify the Window class or styles here by modifying
         //  the CREATESTRUCT cs
            cs.lpszClass = "xioxu";
         return CView::PreCreateWindow(cs);
        }
   
    AfxGetInstanceHandle  
      HINSTANCE AfxGetInstanceHandle( );
      
      Return Value
      
      An HINSTANCE to the current instance of the application. If called from within a DLL linked with the USRDLL version of MFC, an HINSTANCE to the DLL is returned.

       AfxRegisterWndClass  
         LPCTSTR AFXAPI AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor = 0, HBRUSH hbrBackground = 0, HICON hIcon = 0 );
         由于上边的新写的窗口类只能改变MainFrame窗口的图标,所以新写一个类没有必要,系统提供了函数AfxRegisterWndClass来修改。在CMainFrame::PreCreateWindow中用 cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,0,0,LoadIcon(NULL,IDI_WARNING)); 可以修改图标,也只用修改图标就可以,修改其他的没有意义。
         在CDlgProView::PreCreateWindow 中
         cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,LoadCursor(NULL,IDC_CROSS),(HBRUSH)GetStockObject(BLACK_BRUSH),0);修改了光标和背景,修改图标没有意义。
         
         如果一个窗口已经创建,可以用
         SetClassLong
       The SetClassLong function replaces the specified 32-bit (long) value at the specified offset into the extra class memory or the WNDCLASSEX structure for the class to which the specified window belongs.
       
       Note  This function has been superseded by the SetClassLongPtr function. To write code that is compatible with both 32-bit and 64-bit versions of Windows, use SetClassLongPtr.
       
       DWORD SetClassLong(
         HWND hWnd,       // handle to window
         int nIndex,      // index of value to change
         LONG dwNewLong   // new value
       );
      修改窗口的光标、背景、图标。
   SetWindowLong可以改变一个窗口实例的窗口过程,它的作用范围仅仅是一个窗口.

      SetClassLong虽然操作的是一个窗口句柄,但作用却是对创建这个窗口的窗口类进行修改
      LoadIcon()函数如果加载的是系统标准图标,第一个参数必须为空,LoadCursor()一样。
      当使用自己的图标或其他资源时候,第一个参数要为当前实例句柄,AfxGetInstanceHandle()。由于LoadIcon第二个参数是个指向字符的指针,而我们只知道ID,所以系统提供了一个宏MAKEINTRESOURCE用来转换。
       MAKEINTRESOURCE
    The MAKEINTRESOURCE macro converts an integer value to a resource type compatible with the resource-management functions. This macro is used in place of a string containing the name of the resource.
    
    LPTSTR MAKEINTRESOURCE(
      WORD wInteger  
    );
    
   获取当前运行实例的几种方法:
      1. 使用AfxGetInstanceHandle()函数。
      2. MFC的App类中有一个全局对象theApp,而WinApp类有有成员变量
         m_hInstance -----Identifies the current instance of the application.
         所以我们可以如下方法获取
         先  extern CDlgProApp//(我们的App类) theApp;
         然后 theApp.m_hInstance
      3.  使用AfxGetApp 获取WinApp指针
        CWinApp* AfxGetApp( );
        
        Return Value
        
        A pointer to the single CWinApp object for the application.
        
        Remarks
        
        The pointer returned by this function can be used to access application information such as the main message-dispatch code or the topmost window.
       
  工具栏编程
    小技巧  在工具栏上插入分隔符,压住鼠标左键托动图标移动一点就自动插入了。要删除一个图标,把这个图标托到工具栏以外就好了。
    EnableDocking()函数是从CControlBar::EnableDocking派生而来,使得工具栏可以停靠在顶部或底部或其他。
     m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);//工具栏CControlBar::EnableDocking
       EnableDocking(CBRS_ALIGN_ANY); //CFrameWnd::EnableDocking 设定主框架窗口可以被停靠。
        DockControlBar(&m_wndToolBar); //使工具栏停靠在主框架窗口上。
        
     创建一个工具栏的步骤
      1.Create a toolbar resource.


   2.Create a toolbar resource.
   
   
   3.Construct the CToolBar object.
   
   
   4.Call the Create (or CreateEx) function to create the Windows toolbar and attach it to the CToolBar object.
   
   
   5.Call LoadToolBar to load the toolbar resource
   
   判断一个工具栏是否隐藏或显示可以调用CWnd::IsWindowVisible函数。显示隐藏工具栏也可以调用CWnd::ShowWindow.也可以用
CFrameWnd::ShowControlBar显示隐藏。
   
   CFrameWnd::RecalcLayout  
        virtual void RecalcLayout( BOOL bNotify = TRUE );
        
      重新排放框架窗口中的个窗口位置。当要用菜单显示隐藏工具栏的时候要调用这个函数。
      if(m_newToolBar.IsWindowVisible())
     {
            m_newToolBar.ShowWindow(SW_HIDE);
     }
     else
     {
      m_newToolBar.ShowWindow(SW_SHOW);
     }
     RecalcLayout();
     DockControlBar(&m_newToolBar);//因为假如这时候toolbar没有停靠就会出问题。
    上边的问题在于隐藏在显示的时候永远是停靠,而没有放到原来位置。
    
    直接用CFrameWnd::ShowControlBar不存在此问题
    ShowControlBar(&m_newToolBar,!m_newToolBar.IsWindowVisible(),FALSE);不存在此问题。
    要使菜单项目加上复选标记,需要让这个项目响应UPDATE_COMMAND_UI消息,通过CCmdUI::SetCheck()设置复选标记。
      pCmdUI->SetCheck(m_newToolBar.IsWindowVisible());
      
    状态栏的编程
      看MFC例子
        1. CStatusBar  m_wndStatusBar;
        2.static UINT indicators[] =
      {
       ID_SEPARATOR,           // status line indicator
       ID_INDICATOR_CAPS,
       ID_INDICATOR_NUM,
       ID_INDICATOR_SCRL,
      };//状态栏上要显示的项目,都是字符串资源,自己要想在状态栏上显示别的可以在此添加。
        3. 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
      }
      
    获取系统时候可以用CTime::GetCurrentTime ,然后用CTime::Format
        CString Format( LPCTSTR pFormat ) const;
        
        CString Format( UINT nFormatID ) const;
        
        Return Value
        
        A CString that contains the formatted time.获得一个时间字符串。
       
    设置状态栏某一窗格的文字,CStatusBar::SetPaneText。设置状态栏某一窗格宽度,CStatusBar::SetPaneInfo。
 PS:   以后一定要养成判断时候把常量放前边的习惯,刚调了半天最后才发现这个问题。
   
  进度栏的编程  CProgressCtrl
     CProgressCtrl::CProgressCtrl
    CProgressCtrl( );
    
    Remarks
    
    Constructs a CProgressCtrl object.
    
    After constructing the CProgressCtrl object, call CProgressCtrl::Create to create the progress bar control.
 
  CProgressCtrl m_progre;
  m_progre.Create(PBS_SMOOTH | WS_VISIBLE,CRect(80,90,300,120),this,123);
    m_progre.SetPos(50);
    
  获取状态栏上某一窗格大小CStatusBar::GetItemRect,需要注意在OnCreate函数中,这时候状态栏位置尚未确定,所以不能得到它的位置,所以需要自定义消息。而且在OnCreate函数中部能用SendMessage发送消息,因为它直接到了消息执行函数,要用PostMessage()将消息放到消息队列。
  自定义消息
    系统提供宏WM_USER以下通常都是系统保留值,所以自定义消息通常如下步骤
   1. 在头文件中   
       #define UM_MSG WM_USER+21;
   2.消息映射函数声明
      //{{AFX_MSG(CMainFrame)
      ……
      //}}AFX_MSG
      afx_msg void OnProgress();
      DECLARE_MESSAGE_MAP()   
   3.消息映射
        对于消息来说是用ON_MESSAGE宏
        对于命令来说是用ON_COMMAND宏
       此处为消息
        BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    //{{AFX_MSG_MAP(CMainFrame)
         ……
    //}}AFX_MSG_MAP
    ON_MESSAGE(UM_PROGRESS,OnProgress)
    END_MESSAGE_MAP()
   4.消息处理函数编写
      void CMainFrame::OnProgress()
      {
       CRect rect;
       m_wndStatusBar.GetItemRect(2,&rect);
      
       m_progre.Create(WS_CHILD | PBS_SMOOTH | WS_VISIBLE,rect,&m_wndStatusBar,123);
          m_progre.SetPos(50);
      }
   需要注意,由于要把进度条放到了状态栏上,所以需要把进度条的Create函数中将知识父窗口的指针设为状态栏指针。
   移动一个窗口用CWnd::MoveWindow。还有一个SetWindowPos。
   进度条的渐进通过CProgressCtrl::SetStep和CProgressCtrl::StepIt使用。
   
  给状态栏左边最长的上边写文字:
   CString str;
      str.Format("x = %d, y = %d",point.x,point.y);
   1.  ((CMainFrame *)GetParent())->m_wndStatusBar.SetPaneText(0,str);
    2.  ((CMainFrame *)GetParent())->m_wndStatusBar.SetWindowText(str);
  3.   ((CMainFrame *)GetParent())->SetMessageText(str);
  CFrameWnd::SetMessageText
         Call this function to place a string in the status-bar pane that has an ID of 0. This is typically the   leftmost, and longest, pane of the status bar.
       
    4.((CMainFrame *)GetParent())->GetMessageBar()->SetWindowText(str);
        CFrameWnd::GetMessageBar
      Call this member function to get a pointer to the status bar.
    5.CWnd::GetDescendantWindow  查找一个子孙窗口通过一个窗口ID
    Specifies whether the window to be returned can be temporary. If TRUE, only a permanent window can be returned; if FALSE, the function can return a temporary window. For more information on temporary windows see Technical Note 3.
   即位true返回的是一个永久对象,否则返回的是一个临时对象。

       状态栏的窗口ID
        CStatusBar::Create
     BOOL Create( CWnd* pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, UINT nID = AFX_IDW_STATUS_BAR );
     看出系统默认ID为AFX_IDW_STATUS_BAR。
     由于状态栏并不在view窗口上,所以要这样使用:
     GetParent()->GetDescendantWindow(AFX_IDW_STATUS_BAR)->SetWindowText(str);
     
     
     启动画面的编写
        操作:
         project ->add to project ->components and controls->visual v++ components->Splash screen.
         
         后增加了一个位图,一个类CSplashWnd,通过修改这个类中的OnCreate函数中SetTimer的时间延长显示启动窗口的时间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值