窗口創建之前修改:
要改變一個框架窗口的外觀和大小,我們應該在CMainFrame這個類當中的PReCreateWindow函數當中完成。PreCreateWindow這個函數有一個參數cs,這個參數的類型為CREATESTRUCT這個結構體。
如果要想改變窗口的外觀和大小,我們只需要去修改CREATESTRUCT這個結構體當中,相應的成員變量值。
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs){if( !CFrameWnd::PreCreateWindow(cs) )return FALSE;// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT cscs.cx=300;//高度設為300cs.cy=200;//寬度設為200
cs.style=WS_OVERLAPPEDWINDOW;//改變窗口標題的必要步驟(MSDN查閱window styles)cs.lpszName="比他帥";//改變窗口標題return TRUE;}
窗口創建之后修改:
用SetWindowLong(設置窗口類型)在窗口創建之后,改變窗口的外觀在窗口創建之后,改變外觀??梢栽贑MainFrame這個類當中的OnCreate去編寫代碼。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){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)){TRACE0("Failed to create toolbar/n");return -1; // fail to create}
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}
// TODO: Delete these three lines if you don't want the toolbar to// be dockablem_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);EnableDocking(CBRS_ALIGN_ANY);DockControlBar(&m_wndToolBar);
//獲取原有窗口的類型,在這樣的基礎上,進行修改SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE) & ~WS_MAXIMIZEBOX);//GetWindowLong獲取指定窗口信息,& ~WS_MAXIMIZEBOX取反與操作,作用是去掉WS_MAXIMIZEBOX//WS_MAXIMIZEBOX最大化框變灰.(MSDN查閱window styles)return 0;}
=======================================================
窗口創建之前:
對于窗口的圖標,光標和背景,是在設計窗口類的時候指定的,窗口類的設計和注冊,是由MFC底層代碼自
動幫助我們完成的,我們不能也不應該修改MFC的底層代碼。
那么要如何才能改變窗口的圖標,光標和背景呢?雖然不能修改MFC的底層代碼,但是我們可以編寫自己的窗口類,進行注冊,讓隨后的窗口按照我們自己編
寫的窗口類去創建。
下面可以在CMainFrame這個類當中的PreCreateWindow函數當中,編寫自己的窗口類。BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs){if( !CFrameWnd::PreCreateWindow(cs) )return FALSE;// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT cs
WNDCLASS wndcls;wndcls.cbClsExtra=0;//類額外的內存,我們不需要wndcls.cbWndExtra=0;//窗口額外的內存,我們也不需要wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);//背景,獲取一個黑色的背景畫刷wndcls.hCursor=LoadCursor(NULL,IDC_HELP);//光標wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);//圖標
wndcls.hInstance=AfxGetInstanceHandle();//全局函數AfxGetInstanceHandle獲取當前應用程序的句柄
wndcls.lpfnWndProc=::DefWindowProc;//窗口過程,這里我們不想改變任何東西,所以用了缺省的DefWindowProc,這里要用全局的api函數,以免混淆
wndcls.lpszClassName="sunxin.org";//類的名字wndcls.lpszMenuName=NULL;//菜單的名字wndcls.style=CS_HREDRAW | CS_VREDRAW;//窗口類的類型,水平重畫,垂直重畫
RegisterClass(&wndcls);//注冊窗口類cs.lpszClass="sunxin.org";//啟用自己設計的窗口類return TRUE;}
編譯后,發現光標和背景沒有改變(框架窗口CMainFrame只能改變圖標)。要想改變他們必須在view類的PreCreateWindow函數中改變。BOOL CStyleView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT cscs.lpszClass="sunxin.org";//啟用自己設計的窗口類return CView::PreCreateWindow(cs);}
綜上,在MFC程序中,如果想要修改應用程序的圖標,則應該在框架類中修改,因為框架類才有標題欄,所以才能修改位于該標題欄上的圖標;如果想要修改應用程序的背景和光標,應該在視類窗口中改變。
-----------------------------------------------------------------
我們發現只修改那么點東西,就要重寫窗口類,挺麻煩的。為了方便我們,MFC就提供了全局函數AfxRegisterWndClass用來直接修改它們。
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs){if( !CFrameWnd::PreCreateWindow(cs) )return FALSE;// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT cs
cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,0,0,LoadIcon(NULL,IDI_WARNING));//4個參數分別為窗口類的類型,光標,背景,圖標return TRUE;}
BOOL CStyleView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT cscs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,LoadCursor(NULL,IDC_HELP),(HBRUSH)GetStockObject(BLACK_BRUSH),0);//4個參數分別為窗口類的類型,光標,背景,圖標return CView::PreCreateWindow(cs);}
----------------------------------------------------------------
窗口創建之后修改:
在窗口創建之后(CMainFrame里的OnCreate函數),修改它的圖標
利用全局API函數SetClassLong,它可以改變WNDCLASSEX成員變量的值DWord SetClassLong(
HWND hWnd, //要改變的窗口句柄int nIndex, //索引值(要改變的光標,圖標......)LONG dwNewLong //所設置的新的值);
在CMainFrame里的OnCreate函數SetClassLong(m_hWnd,GCL_HICON,(LONG)LoadIcon(NULL,IDI_ERROR));
------------------------------------------
在窗口創建之后(在view類增加消息處理WM_CREATE),修改光標和背景int CStyleView::OnCreate(LPCREATESTRUCT lpCreateStruct){if (CView::OnCreate(lpCreateStruct) == -1)return -1;// TODO: Add your specialized creation code hereSetClassLong(m_hWnd,GCL_HBRBACKGROUND,(LONG)GetStockObject(BLACK_BRUSH));//修改背景SetClassLong(m_hWnd,GCL_HCURSOR,(LONG)LoadCursor(NULL,IDC_HELP));//修改光標return 0;}
============================================
就是運用預先準備好的圖標,然后每隔一段時間,顯示一副新的圖標。讓這幾個圖標不斷來回循環的顯示,這樣就形成了動畫的效果。
這個功能,我們利用定時器,和函數SetClassLong完成。我們每隔一秒鐘,調用一次SetClassLong,SetClassLong可以在窗口創建之后,去改變窗口的圖標。這樣每隔一秒鐘顯示下一副圖標,形成動畫的效果。
1.先準備3副圖標,把這3副圖標放在程序(不是vc而是你寫的程序)的res里面。2.在VC里面選擇"插入"->"資源"。之后找到那3副圖標,全部導入。
3.定義一個圖標句柄數組,用來存放3副圖標的句柄。在CMainFrame增加成員變量。變量類型HICON,名稱m_hIcons[3],權限為private
4.在CMainFrame的OnCreate上,加載這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));//利用全局函數獲取當前應用程序對象指針,然后獲取內部數據成員
SetTimer(1,1000,NULL);//設置定時器
//AfxGetInstanceHandle()//因為要用我們自己的圖標,所以利用全局函數AfxGetInstanceHandle設置為程序當前的實例句柄
//MAKEINTRESOURCE(IDI_ICON1)//MAKEINTRESOURCE,將資源ID號轉換為字符指針類型
5.在CMainFrame增加消息處理WM_TIMERvoid CMainFrame::OnTimer(UINT nIDEvent){// TODO: Add your message handler code here and/or call defaultstatic int index=0;//定義一個索引,初始為0SetClassLong(m_hWnd,GCL_HICON,(LONG)m_hIcons[index]);index=++index%3;//取模,我們需要它在0到2之間不停變化,以實現圖標的轉換CFrameWnd::OnTimer(nIDEvent);}
//要把一個值始終保持在一個范圍內,最好的辦法,就是取模(取余)//取余運算;0除3余0;1除3余1;2除3余2 ;3除3余0。
=====================================================================
工具欄(CToolBar)的編程
創建工具欄有2種方式:(第一種)1.Create a toolbar resource.創建工具欄資源
2.Construct the CToolBar object.構建CToolBar的對象
3.Call the Create (or CreateEx) function to create the Windows toolbar調用Create或者CreateEx創建工具欄,并且和CToolBar對象關聯起來。
4.Call LoadToolBar to load the toolbar resource. 調用LoadToolBar加載工具欄資源
(第二種)1.Construct the CToolBar object.構造CToolBar對象
2.Call the Create (or CreateEx) function to create the Windows toolbar and attach it to the
CToolBar object.調用Create或者CreateEx創建工具欄,并且和CToolBar對象關聯起來。
3.Call LoadBitmap to load the bitmap that contains the toolbar button images.調用LoadBitmap加載一個工具欄位圖(.bmp)的圖象
4.Call SetButtons to set the button style and associate each button with an image in the
bitmap.調用SetButtons設置按鈕的樣式,和位圖的每一幅圖象關聯
-----------------------------------------
創建自己的工具欄(CToolBar)
1.在資源編輯器"插入"一個工具欄,創建3個工具欄資源(按鈕)
2.構建CToolBar的對象在CMainFrame增加成員變量,類型CToolBar,名稱m_newToolBar,權限為protected
3.調用Create或者CreateEx創建工具欄,并且和CToolBar對象關聯起來。4.調用LoadToolBar加載工具欄資源在CMainFrame的OnCreate函數中處理::
拷貝以下的代碼::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)){TRACE0("Failed to create toolbar/n");return -1; // fail to create}
拷貝代碼后修改代碼::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)){TRACE0("Failed to create toolbar/n");return -1; // fail to create}
m_newToolBar.EnableDocking(CBRS_ALIGN_ANY);//讓工具欄可以??緿ockControlBar(&m_newToolBar);//讓工具欄??吭谥骺蚣艽翱谏?/strong>
m_wndToolBar要改為m_newToolBarCBRS_TOP改為CBRS_RIGHT//將工具欄停靠在右邊LoadToolBar(IDR_MAINFRAME)改為LoadToolBar(IDR_TOOLBAR1)
----------------------------
接上程序,在"查看"上面新建一個菜單(標記菜單),讓工具欄顯示或者隱藏
1.在"查看"上面增加一個菜單項,ID為IDM_VIEW_NEWTOOL,標題為"新的工具欄"2.對新建的菜單項進行命令響應(COMMAND)
3.利用函數ShowControlBar顯示,隱藏工具欄void ShowControlBar( CControlBar* pBar, BOOL bShow, BOOL bDelay );
第二個參數bShow,BOOL型If TRUE, specifies that the control bar is to be shown. If FALSE, specifies that the control
bar is to be hidden.如果為真顯示工具欄,為假隱藏
方法2void CMainFrame::OnViewNewtool(){// TODO: Add your command handler code hereShowControlBar(&m_newToolBar,!m_newToolBar.IsWindowVisible(),FALSE);//IsWindowVisible如果窗口可視的話返回真,我們因為要把它隱藏起來,所以用邏輯非操作符!}
4.給菜單項加上復選標記首先是為菜單項進行命令響應(UPDATE_COMMAND_UI)
void CMainFrame::OnUpdateViewNewtool(CCmdUI* pCmdUI){// TODO: Add your command update UI handler code herepCmdUI->SetCheck(m_newToolBar.IsWindowVisible());//IsWindowVisible為真就打上標記}
=========================================================================================
在狀態欄上添加時間顯示
1.定義字符串資源,在資源編輯器的String_Table中添加IDS_TIMER,標題為時鐘IDS_PROGRESS, 標題為進度欄
2.在CMainFrame的static UINT indicators[](指示器數組ID_SEPARATOR的后面)添加IDS_TIMER,
IDS_PROGRESS。
3.在狀態欄上顯示系統時間,在CMainFrame的OnCreate函數中:
//CTime::GetCurrentTime//Returns a CTime object that represents the current time.返回一個CTime對象,表明當前系統時間
CTime t=CTime::GetCurrentTIme();//獲取當前系統時間,它返回一個CTime對象CString str=t.Format("%H:%M:%S");//將當前系統時間格式化(獲取表示時間的字符串對象)
CClientDC dc(this);CSize sz=dc.GetTextExtent(str);//作用見下面的解釋(1)
m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx);//作用見下面的解釋(1)m_wndStatusBar.SetPaneText(1,str);//將表示時間的字符串對象,輸出到狀態欄
//BOOL SetPaneText( int nIndex, LPCTSTR lpszNewText, BOOL bUpdate = TRUE );//參數分別為,狀態欄面板的索引,字符串文本
//解釋(1)//調整顯示寬度,因為編譯后發現窗格太小,并沒用足夠位置顯示到時鐘的秒數//利用函數void SetPaneInfo( int nIndex, UINT nID, UINT nStyle, int cxWidth );設置窗格信息
//CClientDC dc(this);//CSize sz=dc.GetTextExtent(str);//得到字符串顯示(表示時間)的寬度//m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx);//設置窗格信息
4.讓時間動態顯示把步驟3的代碼放在OnTimer函數上
---------------------------------------------------------------
創建一個進度欄(CProgressCtrl)
1.在CMainFrame增加成員變量,類型CProgressCtrl,名稱為m_Progress,權限為protected
2.創建進度欄,在CMainFrame::OnCreate()中m_Progress.Create(WS_CHILD | WS_VISIBLE,CRect(100,100,200,120),this,123);
3.設置進度欄位置(利用CProgressCtrl::SetPos),在CMainFrame::OnCreate()中m_Progress.SetPos(50);
4.創建垂直進度欄m_Progress.Create(WS_CHILD | WS_VISIBLE | PBS_VERTICAL,CRect(100,100,120,200),this,123);
5.進度欄放在狀態欄窗格
首先要獲取要放置窗格的矩形區域(利用CStatusBar::GetItemRect函數);然后將窗格的區域大小,作為我們進度欄的區域大小。
//以上即為實現代碼,但是放在OnCreate函數中不能實現:因為OnCreate()返回前狀態欄的位置還沒有確定
//,所以無法獲得各個子窗格位置,只能用自定義消息辦法響應。
自定義消息1)在MainFrm.h添加(class CMainFrame : public CFrameWnd前面添加)#define UM_PROGRESS WM_USER+1 //WM_USER加多小隨你,這樣就可以判斷為自定義消息
消息響應函數原形的聲明2)在MainFrm.h中添加(DECLARE_MESSAGE_MAP()前面添加)afx_msg void OnProgress();
消息映射3)MainFrm.cpp中添加(END_MESSAGE_MAP()前面添加)ON_MESSAGE(UM_PROGRESS,OnProgress)
實現消息響應函數4)void CMainFrame::OnProgress(){CRect rect;m_wndStatusBar.GetItemRect(2,&rect);//獲取狀態欄要放置窗格的矩形區域m_Progress.Create(WS_CHILD | WS_VISIBLE,rect,&m_wndStatusBar,123);m_Progress.SetPos(50);}
在OnCreate()函數中發送消息5)PostMessage(UM_PROGRESS);//注意不要用SendMessage();因為SendMessage是將消息直接發送給消息響應函數,處理完畢之后,SendMessage函數才返回。PostMessage是將消息發送給消息隊列,然后立即返回。之后,程序通告GetMessage取出消息。
當窗口尺寸發生改變,狀態欄的舉行區域也要發生變化,所以當窗口尺寸發生改變時,重新獲取窗格的區域我們知道,當窗口尺寸發生改變會發送WM_PAINT消息.只需要在WM_PAINT的響應函數當中添加剛才的代碼6)把OnCreate()中的PostMessage()刪除使之失效.在CMainFrame增加消息處理WM_PAINT
void CMainFrame::OnPaint(){CPaintDC dc(this); // device context for painting// TODO: Add your message handler code hereCRect rect;m_wndStatusBar.GetItemRect(2,&rect);//獲取狀態欄要放置窗格的矩形區域if(!m_Progress.m_hWnd)m_Progress.Create(WS_CHILD | WS_VISIBLE,rect,&m_wndStatusBar,123);elsem_Progress.MoveWindow(rect);m_Progress.SetPos(50);// Do not call CFrameWnd::OnPaint() for painting messages}
--------
讓進度欄前進在void CMainFrame::OnTimerm_Progress.StepIt();
--------------------------------------------------------------------------------------------
將鼠標移動的坐標,適時顯示到狀態欄上
1.捕獲鼠標移動的消息在view類增加消息處理添加WM_MOUSEMOVE
2.在OnMouseMove()中void CStyleView::OnMouseMove(UINT nFlags, CPoint point){// TODO: Add your message handler code here and/or call defaultCString str;str.Format("x=%d,y=%d",point.x,point.y);//要輸出坐標到狀態欄,先將它初始化
((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);//m_wndStatusBar變量要改為公用public
CView::OnMouseMove(nFlags, point);}
//記得要包含CMainFrame頭文件。#include "MainFrm.h"//m_wndStatusBar變量要改為公用public
======================================================================================
給程序增加啟動畫面
"工程"->"增加到工程"->"Component and Control"(組件和控件)->"Visual C++ Components"(vc組件)->Splash screen
我們發現。。。系統自動增加了CSplashWnd類而且在資源編輯器給我們增加了一副位圖(Bitmap),就是該啟動畫面
在CSplashWnd::OnCreate()中有SetTimer(1,750,NULL);設置750ms的啟動畫面顯示間隔當然你可以把750改大點,3000,那就是3秒后再隱藏啟動畫面
新聞熱點
疑難解答