定製應用程序外觀

本節主要學習了

1.      修改MFC AppWizard嚮導生成的框架程序外觀和大小,這既可以在窗口創建之前,也可以在窗口創建之後進行。

2.      修改程序窗口的圖標,光標,背景的方法。在創建窗口之前,通過設計窗口類來修改程序窗口的圖標,光標,背景;在窗口創建之後,通過SetClassLong函數修改窗口的圖標,光標和背景。

3.      實現一個動態變化的圖標的例子。

4.      工具欄和狀態欄編程。

5.      程序啓動畫面的創建。

 

BOOLCMainFrame::PreCreateWindow(CREATESTRUCT& cs)//這是一個虛函數

{

       if(!CFrameWnd::PreCreateWindow(cs) )

              returnFALSE;

       //TODO: Modify the Window class or styles here by modifying

       //  the CREATESTRUCT cs

       //1.在窗口創建之前修改窗口的默認外觀。

   /*cs.cx = 300;

       cs.cy= 200;

       cs.style&= ~FWS_ADDTOTITLE;  //改變將文檔標題添加到窗口標題上。可以讓窗口顯示自己設置的標題。

       //cs.style= cs.style & ~ FWS_ADDTOTITLE;

       //cs.style= WS_OVERLAPPEDWINDOW;

       //cs.style= WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE; //該成員的初始定義代碼。

       cs.lpszName= "xiaobai";*/

 

       //2.修改窗口的光標,圖標,背景

   //通過編寫自己的窗口類並註冊,然後讓隨後的窗口按照自己編寫的窗口類去創建。

 

       /*WNDCLASSwndclass;

       wndclass.cbClsExtra= 0;

       wndclass.cbWndExtra= 0;

       wndclass.hbrBackground= (HBRUSH)GetStockObject(BLACK_BRUSH);

       wndclass.hCursor= LoadCursor(NULL,IDC_HELP);

       wndclass.hIcon= LoadIcon(NULL,IDI_ERROR);

       wndclass.hInstance= AfxGetInstanceHandle();  //獲取當前應用程序的實例句柄。Afx開頭的函數都是應用程序框架類函數,也就是全局函數。

       wndclass.lpfnWndProc= ::DefWindowProc;

       wndclass.lpszClassName= "xiaobai";

       wndclass.lpszMenuName= NULL;

       wndclass.style= CS_HREDRAW | CS_VREDRAW;//這裏並不是窗口的類型,而是窗口類的類型。指定窗口類具有水平重繪和垂直重繪這兩種類型。

 

       RegisterClass(&wndclass);

       cs.lpszClass= "xiaobai"; */

 

       //cs.lpszClass= AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,0,0,LoadIcon(NULL,IDI_WARNING));

       cs.lpszClass= AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,0,0,0);

       //用來設定窗口的類型,光標,背景,圖標。返回值是註冊之後的類名。

       returnTRUE;

}

 

       //SetWindowLong(m_hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW);

   SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE) &~WS_MAXIMIZEBOX);//取消最大化

       //GWL就是GetWindowLong的縮寫。GWL_STYLE指定獲取窗口的類型。

 

BOOLCStyleView::PreCreateWindow(CREATESTRUCT& cs)

{

       //TODO: Modify the Window class or styles here by modifying

       //  the CREATESTRUCT cs

   //cs.lpszClass = "xiaobai"; //思考一下爲什在CMainFram中註冊的窗口類,在這裏還可以用。

       //在MFC程序中,如果要修改應用程序窗口的圖標,則應在框架類中進行,因爲在框架窗口中才有標題欄,所以才能修改位於該標題欄上的圖標

       //如果想要修改應用程序的背景和光標,就應該在視類中進行。

 

       //cs.lpszClass= AfxRegisterWndClass(CS_HREDRAW |CS_VREDRAW,LoadCursor(NULL,IDC_CROSS),(HBRUSH)GetStockObject(BLACK_BRUSH),0);

       cs.lpszClass= AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,0,0,0);//只給第一個參數賦值,其餘參數都爲0,會發現

       //背景是透明的,圖標光標都是默認的。

       returnCView::PreCreateWindow(cs);

}

 

       ON_MESSAGE(UM_PROGRESS,OnProgress)      //對於自定義消息來說,使用的是ON_MESSAGE宏實現這一功能。

END_MESSAGE_MAP()

 

static UINT indicators[] =    //標識提示行和狀態欄指示器的ID數組

{

       ID_SEPARATOR,// status line indicator 提示行

       IDS_TIMER,

       IDS_PROGRESS,

       ID_INDICATOR_CAPS,      //分別是Caps Lock,Num Lock,Scroll Lock鍵的狀態指示器。

       ID_INDICATOR_NUM,

       ID_INDICATOR_SCRL,

};

 

extern CStyleApp theApp;  //聲明這個變量是在外部的一個源文件中定義的

 

int CMainFrame::OnCreate(LPCREATESTRUCTlpCreateStruct)

{

       if(CFrameWnd::OnCreate(lpCreateStruct) == -1)

              return-1;

      

       if(!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP

              |CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||

              !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))     //MFC自動創建的工具欄和主菜單的資源ID是一樣的,也就是說,在MFC編程中,一個ID可以表示多種資源。

       {

              TRACE0("Failedto create toolbar\n");

              return-1;      // fail to create

       }

 

       if(!m_wndStatusBar.Create(this) ||

              !m_wndStatusBar.SetIndicators(indicators,

                sizeof(indicators)/sizeof(UINT)))

       {

              TRACE0("Failedto create status bar\n");

              return-1;      // fail to create

       }

 

       //TODO: Delete these three lines if you don't want the toolbar to

       //  be dockable

       m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);  //設置工具欄停靠的位置

       EnableDocking(CBRS_ALIGN_ANY);//上面的那個EnableDocking函數式工具欄對象的成員函數,目的是讓工具欄對象可以停靠,而這裏調用的是CFrameWnd對象的EnableDocking

                                     //成員函數,目的是讓主框架窗口可以被停靠。

       DockControlBar(&m_wndToolBar);//讓工具欄停靠在主框架窗口上。

 

       //在窗口創建之後修改窗口的樣式

       SetClassLong(m_hWnd,GCL_HICON,(LONG)LoadIcon(NULL,IDI_ERROR));

 

       //模擬動畫圖標(3中加載自定義圖標的方式)

   m_hIcons[0] =LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1));

       m_hIcons[1]= LoadIcon(theApp.m_hInstance,MAKEINTRESOURCE(IDI_ICON2));

       m_hIcons[2]= LoadIcon(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDI_ICON3));//AfxGetApp可以獲得當前應用程序對象的指針

 

       SetClassLong(m_hWnd,GCL_HICON,(LONG)m_hIcons[0]);

 

       SetTimer(1,1000,NULL);

 

       //創建自定義工具欄

       if(!m_newToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_RIGHT

              |CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||

              !m_newToolBar.LoadToolBar(IDR_TOOLBAR1))     //MFC自動創建的工具欄和主菜單的資源ID是一樣的,也就是說,在MFC編程中,一個ID可以表示多種資源。

       {

              TRACE0("Failedto create toolbar\n");

              return-1;      // fail to create

       }

       m_newToolBar.EnableDocking(CBRS_ALIGN_ANY);

       DockControlBar(&m_newToolBar);

 

       //在窗口中創建進度欄(思考一下在框架類中創建的進度欄怎嘛可以在視類窗口中顯示)

       //m_progress.Create(WS_CHILD| WS_VISIBLE | PBS_SMOOTH,CRect(100,100,200,120),this,123);   //創建水平的進度欄

       //m_progress.SetPos(50);  //設置進度欄上當前位置

 

       //m_progress.Create(WS_CHILD| WS_VISIBLE | PBS_VERTICAL,CRect(100,100,120,200),this,321);  ///創建垂直的進度欄

       //m_progress.SetPos(40);

 

       //在狀態欄的窗格中創建進度欄

       /*CRectrect;

       m_wndStatusBar.GetItemRect(2,&rect);

       m_progress.Create(WS_CHILD| WS_VISIBLE,rect,&m_wndStatusBar,123);

       m_progress.SetPos(50);*/    //這種方式並不能讓進度條在窗格中顯示。只有在窗口創建完,即OnCreate函數執行完

                                   //才能獲得窗口狀態欄上窗格的矩形區域。

 

       //SendMessage(UM_PROGRESS);  //發送消息在OnCreate函數沒有執行完,就去執行UM_PROGRESS消息的響應函數,

                                        //消息響應函數返回又回到OnCreate函數中執行到函數結束,這和上面的那段代碼其實

                                       //是一樣的效果

       m_wndStatusBar.SetPaneInfo(2,IDS_PROGRESS,SBPS_NORMAL,100);//設置窗格的寬度

       //PostMessage(UM_PROGRESS);//投遞消息,把消息投遞到消息隊列中,程序通過GetMessage函數按順序把消息一條一條的取出來

       //對於本程序,等程序執行完WM_CREATE消息後,纔去執行UM_PROGRESS消息

 

   myCtrl.Create(WS_CHILD |WS_VISIBLE | PBS_SMOOTH,CRect(100,100,200,120),this,123);

       intnLower,nUpper;

       myCtrl.GetRange(nLower,nUpper);

       myCtrl.SetStep((nUpper-nLower)/4);

       myCtrl.StepIt();

       //CG: The following line was added by the Splash Screen component.

       CSplashWnd::ShowSplashScreen(this);

       return0;

}

 

void CMainFrame::OnTimer(UINT nIDEvent)

{

       staticint index = 0;  //作爲一個靜態的局部變量,他將存放在程序的數據區中,而不是在棧中分配空間。

       SetClassLong(m_hWnd,GCL_HICON,(LONG)m_hIcons[index]);

       index= ++index%3;  //小技巧:如果希望把某個數值始終限制在一個範圍內,那麼最好的辦法就是進行取模運算(%)

 

       //在時鐘狀態欄指示器中顯示時間

       CTimet = CTime::GetCurrentTime();

       CStringstr = t.Format("%H:%M:%S");

       CClientDCdc(this);

       CSizesz=dc.GetTextExtent(str);  //獲得字符串的寬度和高度

 

       //intindex = 0;     //在不知道窗格的索引時,可以利用這個函數,根據窗格的ID來得到相應的索引。

       //index= m_wndStatusBar.CommandToIndex(IDS_TIMER);

   m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx);

       m_wndStatusBar.SetPaneText(1,str);

 

       intnLower,nUpper;

       m_progress.GetRange(nLower,nUpper);

       m_progress.SetStep((nUpper-nLower)/10);  //設置每次前進的步長

       m_progress.StepIt();  //讓進度欄的當前位置按照一定的步長前進

 

       CFrameWnd::OnTimer(nIDEvent);

}

 

//工具欄的顯示或隱藏

void CMainFrame::OnViewNewtoolbar()

{

       //TODO: Add your command handler code here

       /*if(m_newToolBar.IsWindowVisible())   //判斷工具欄是顯示還是隱藏了

       {

              m_newToolBar.ShowWindow(SW_HIDE);

       }

       else

       {

              m_newToolBar.ShowWindow(SW_SHOW);

       }

       RecalcLayout();

/*當標準工具欄或狀態欄隱藏或者顯示,或者窗口調整大小時,調用這個方法。

方法原型爲:virtualvoid RecalcLayout( BOOL bNotify = TRUE ); 

Parameters:   bNotify

Determines whether the active in-place itemfor the frame window receives notification of the layout change. If TRUE, theitem is notified; otherwise FALSE.

決定是否將焦點項目傳遞這個變化,如果是TRUE就通知子項目,否則,不傳遞。

這裏m_wndToolBar1是自己定義的一個工具欄,:OnViewToolbar1()是一個菜單項的消息響應函數。

當工具欄顯示時,點擊這個菜單項,工具欄隱藏,然後調用RecalcLayout這個方法,重新佈置窗口。

當工具欄隱藏式,點擊這個菜單項,工具欄顯示,然後調用RecalcLayout這個方法,重新佈置窗口。

       DockControlBar(&m_newToolBar);*/

 

       ShowControlBar(&m_newToolBar,!m_newToolBar.IsWindowVisible(),FALSE);

       //顯示或隱藏一個控件條 

       //pBar指向要顯示或隱含的控件條   

       //bShow如果爲TRUE ,指定控件條將顯示;如果爲FALSE,則隱藏。   

       //bDelay如果爲TRUE,延遲顯示控件條;如果爲FALSE,則立即顯示

}

 

//顯示或隱藏工具欄時,取消或顯示相應的菜單上的複選標記

void CMainFrame::OnUpdateViewNewtoolbar(CCmdUI*pCmdUI)

{

       pCmdUI->SetCheck(m_newToolBar.IsWindowVisible());

       //通過爲菜單項添加UPDATE_COMMAND_UI消息的響應,可以非常方便地爲該菜單項設置或取消複選標記。

}

 

//這種方法在窗口發生重繪時,進度條的顯示就會錯位,要在窗口重繪的消息響應函數中添加下面的代碼

void CMainFrame::OnProgress()

{

       CRectrect;

       m_wndStatusBar.GetItemRect(2,&rect);

       m_progress.Create(WS_CHILD| WS_VISIBLE | PBS_SMOOTH,rect,&m_wndStatusBar,123);

       m_progress.SetPos(50);

}

 

void CMainFrame::OnPaint()

{

       CPaintDCdc(this); // device context for painting

      

       CRectrect;

       m_wndStatusBar.GetItemRect(2,&rect);

       if(!m_progress.m_hWnd)  //根據m_progress對象的窗口句柄是否爲空判斷進度欄是否被創建

       {

           m_progress.Create(WS_CHILD | WS_VISIBLE |PBS_SMOOTH,rect,&m_wndStatusBar,123);

       }

       else

       {

              m_progress.MoveWindow(rect);//用SetWindowPos函數設置進度欄的位置比較麻煩,但功能比較多,例如它可以將程序窗口設置爲頂層窗口

       }

       m_progress.SetPos(50);

       //Do not call CFrameWnd::OnPaint() for painting messages

}

發佈了41 篇原創文章 · 獲贊 5 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章