窗口創(chuàng)建之前修改:
要改變一個框架窗口的外觀和大小,我們應(yīng)該在CMainFrame這個類當(dāng)中的PReCreateWindow函數(shù)當(dāng)中完成。PreCreateWindow這個函數(shù)有一個參數(shù)cs,這個參數(shù)的類型為CREATESTRUCT這個結(jié)構(gòu)體。
如果要想改變窗口的外觀和大小,我們只需要去修改CREATESTRUCT這個結(jié)構(gòu)體當(dāng)中,相應(yīng)的成員變量值。
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;//高度設(shè)為300cs.cy=200;//寬度設(shè)為200
cs.style=WS_OVERLAPPEDWINDOW;//改變窗口標(biāo)題的必要步驟(MSDN查閱window styles)cs.lpszName="比他帥";//改變窗口標(biāo)題return TRUE;}
窗口創(chuàng)建之后修改:
用SetWindowLong(設(shè)置窗口類型)在窗口創(chuàng)建之后,改變窗口的外觀在窗口創(chuàng)建之后,改變外觀。可以在CMainFrame這個類當(dāng)中的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);
//獲取原有窗口的類型,在這樣的基礎(chǔ)上,進(jìn)行修改SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE) & ~WS_MAXIMIZEBOX);//GetWindowLong獲取指定窗口信息,& ~WS_MAXIMIZEBOX取反與操作,作用是去掉WS_MAXIMIZEBOX//WS_MAXIMIZEBOX最大化框變灰.(MSDN查閱window styles)return 0;}
=======================================================
窗口創(chuàng)建之前:
對于窗口的圖標(biāo),光標(biāo)和背景,是在設(shè)計窗口類的時候指定的,窗口類的設(shè)計和注冊,是由MFC底層代碼自
動幫助我們完成的,我們不能也不應(yīng)該修改MFC的底層代碼。
那么要如何才能改變窗口的圖標(biāo),光標(biāo)和背景呢?雖然不能修改MFC的底層代碼,但是我們可以編寫自己的窗口類,進(jìn)行注冊,讓隨后的窗口按照我們自己編
寫的窗口類去創(chuàng)建。
下面可以在CMainFrame這個類當(dāng)中的PreCreateWindow函數(shù)當(dāng)中,編寫自己的窗口類。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;//類額外的內(nèi)存,我們不需要wndcls.cbWndExtra=0;//窗口額外的內(nèi)存,我們也不需要wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);//背景,獲取一個黑色的背景畫刷wndcls.hCursor=LoadCursor(NULL,IDC_HELP);//光標(biāo)wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);//圖標(biāo)
wndcls.hInstance=AfxGetInstanceHandle();//全局函數(shù)AfxGetInstanceHandle獲取當(dāng)前應(yīng)用程序的句柄
wndcls.lpfnWndProc=::DefWindowProc;//窗口過程,這里我們不想改變?nèi)魏螙|西,所以用了缺省的DefWindowProc,這里要用全局的api函數(shù),以免混淆
wndcls.lpszClassName="sunxin.org";//類的名字wndcls.lpszMenuName=NULL;//菜單的名字wndcls.style=CS_HREDRAW | CS_VREDRAW;//窗口類的類型,水平重畫,垂直重畫
RegisterClass(&wndcls);//注冊窗口類cs.lpszClass="sunxin.org";//啟用自己設(shè)計的窗口類return TRUE;}
編譯后,發(fā)現(xiàn)光標(biāo)和背景沒有改變(框架窗口CMainFrame只能改變圖標(biāo))。要想改變他們必須在view類的PreCreateWindow函數(shù)中改變。BOOL CStyleView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT cscs.lpszClass="sunxin.org";//啟用自己設(shè)計的窗口類return CView::PreCreateWindow(cs);}
綜上,在MFC程序中,如果想要修改應(yīng)用程序的圖標(biāo),則應(yīng)該在框架類中修改,因?yàn)榭蚣茴惒庞袠?biāo)題欄,所以才能修改位于該標(biāo)題欄上的圖標(biāo);如果想要修改應(yīng)用程序的背景和光標(biāo),應(yīng)該在視類窗口中改變。
-----------------------------------------------------------------
我們發(fā)現(xiàn)只修改那么點(diǎn)東西,就要重寫窗口類,挺麻煩的。為了方便我們,MFC就提供了全局函數(shù)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個參數(shù)分別為窗口類的類型,光標(biāo),背景,圖標(biāo)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個參數(shù)分別為窗口類的類型,光標(biāo),背景,圖標(biāo)return CView::PreCreateWindow(cs);}
----------------------------------------------------------------
窗口創(chuàng)建之后修改:
在窗口創(chuàng)建之后(CMainFrame里的OnCreate函數(shù)),修改它的圖標(biāo)
利用全局API函數(shù)SetClassLong,它可以改變WNDCLASSEX成員變量的值DWord SetClassLong(
HWND hWnd, //要改變的窗口句柄int nIndex, //索引值(要改變的光標(biāo),圖標(biāo)......)LONG dwNewLong //所設(shè)置的新的值);
在CMainFrame里的OnCreate函數(shù)SetClassLong(m_hWnd,GCL_HICON,(LONG)LoadIcon(NULL,IDI_ERROR));
------------------------------------------
在窗口創(chuàng)建之后(在view類增加消息處理WM_CREATE),修改光標(biāo)和背景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));//修改光標(biāo)return 0;}
============================================
就是運(yùn)用預(yù)先準(zhǔn)備好的圖標(biāo),然后每隔一段時間,顯示一副新的圖標(biāo)。讓這幾個圖標(biāo)不斷來回循環(huán)的顯示,這樣就形成了動畫的效果。
這個功能,我們利用定時器,和函數(shù)SetClassLong完成。我們每隔一秒鐘,調(diào)用一次SetClassLong,SetClassLong可以在窗口創(chuàng)建之后,去改變窗口的圖標(biāo)。這樣每隔一秒鐘顯示下一副圖標(biāo),形成動畫的效果。
1.先準(zhǔn)備3副圖標(biāo),把這3副圖標(biāo)放在程序(不是vc而是你寫的程序)的res里面。2.在VC里面選擇"插入"->"資源"。之后找到那3副圖標(biāo),全部導(dǎo)入。
3.定義一個圖標(biāo)句柄數(shù)組,用來存放3副圖標(biāo)的句柄。在CMainFrame增加成員變量。變量類型HICON,名稱m_hIcons[3],權(quán)限為private
4.在CMainFrame的OnCreate上,加載這3個圖標(biāo)
m_hIcons[0]=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1)); m_hIcons[1]=LoadIcon(theApp.m_hInstance,MAKEINTRESOURCE(IDI_ICON2));//利用全局對象獲取當(dāng)前實(shí)例句柄 m_hIcons[2]=LoadIcon(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDI_ICON3));//利用全局函數(shù)獲取當(dāng)前應(yīng)用程序?qū)ο笾羔槪缓螳@取內(nèi)部數(shù)據(jù)成員
SetTimer(1,1000,NULL);//設(shè)置定時器
//AfxGetInstanceHandle()//因?yàn)橐梦覀冏约旱膱D標(biāo),所以利用全局函數(shù)AfxGetInstanceHandle設(shè)置為程序當(dāng)前的實(shí)例句柄
//MAKEINTRESOURCE(IDI_ICON1)//MAKEINTRESOURCE,將資源ID號轉(zhuǎn)換為字符指針類型
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之間不停變化,以實(shí)現(xiàn)圖標(biāo)的轉(zhuǎn)換CFrameWnd::OnTimer(nIDEvent);}
//要把一個值始終保持在一個范圍內(nèi),最好的辦法,就是取模(取余)//取余運(yùn)算;0除3余0;1除3余1;2除3余2 ;3除3余0。
=====================================================================
工具欄(CToolBar)的編程
創(chuàng)建工具欄有2種方式:(第一種)1.Create a toolbar resource.創(chuàng)建工具欄資源
2.Construct the CToolBar object.構(gòu)建CToolBar的對象
3.Call the Create (or CreateEx) function to create the Windows toolbar調(diào)用Create或者CreateEx創(chuàng)建工具欄,并且和CToolBar對象關(guān)聯(lián)起來。
4.Call LoadToolBar to load the toolbar resource. 調(diào)用LoadToolBar加載工具欄資源
(第二種)1.Construct the CToolBar object.構(gòu)造CToolBar對象
2.Call the Create (or CreateEx) function to create the Windows toolbar and attach it to the
CToolBar object.調(diào)用Create或者CreateEx創(chuàng)建工具欄,并且和CToolBar對象關(guān)聯(lián)起來。
3.Call LoadBitmap to load the bitmap that contains the toolbar button images.調(diào)用LoadBitmap加載一個工具欄位圖(.bmp)的圖象
4.Call SetButtons to set the button style and associate each button with an image in the
bitmap.調(diào)用SetButtons設(shè)置按鈕的樣式,和位圖的每一幅圖象關(guān)聯(lián)
-----------------------------------------
創(chuàng)建自己的工具欄(CToolBar)
1.在資源編輯器"插入"一個工具欄,創(chuàng)建3個工具欄資源(按鈕)
2.構(gòu)建CToolBar的對象在CMainFrame增加成員變量,類型CToolBar,名稱m_newToolBar,權(quán)限為protected
3.調(diào)用Create或者CreateEx創(chuàng)建工具欄,并且和CToolBar對象關(guān)聯(lián)起來。4.調(diào)用LoadToolBar加載工具欄資源在CMainFrame的OnCreate函數(shù)中處理::
拷貝以下的代碼::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);//讓工具欄可以停靠DockControlBar(&m_newToolBar);//讓工具欄停靠在主框架窗口上
m_wndToolBar要改為m_newToolBarCBRS_TOP改為CBRS_RIGHT//將工具欄停靠在右邊LoadToolBar(IDR_MAINFRAME)改為LoadToolBar(IDR_TOOLBAR1)
----------------------------
接上程序,在"查看"上面新建一個菜單(標(biāo)記菜單),讓工具欄顯示或者隱藏
1.在"查看"上面增加一個菜單項(xiàng),ID為IDM_VIEW_NEWTOOL,標(biāo)題為"新的工具欄"2.對新建的菜單項(xiàng)進(jìn)行命令響應(yīng)(COMMAND)
3.利用函數(shù)ShowControlBar顯示,隱藏工具欄void ShowControlBar( CControlBar* pBar, BOOL bShow, BOOL bDelay );
第二個參數(shù)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如果窗口可視的話返回真,我們因?yàn)橐阉[藏起來,所以用邏輯非操作符!}
4.給菜單項(xiàng)加上復(fù)選標(biāo)記首先是為菜單項(xiàng)進(jìn)行命令響應(yīng)(UPDATE_COMMAND_UI)
void CMainFrame::OnUpdateViewNewtool(CCmdUI* pCmdUI){// TODO: Add your command update UI handler code herepCmdUI->SetCheck(m_newToolBar.IsWindowVisible());//IsWindowVisible為真就打上標(biāo)記}
=========================================================================================
在狀態(tài)欄上添加時間顯示
1.定義字符串資源,在資源編輯器的String_Table中添加IDS_TIMER,標(biāo)題為時鐘IDS_PROGRESS, 標(biāo)題為進(jìn)度欄
2.在CMainFrame的static UINT indicators[](指示器數(shù)組ID_SEPARATOR的后面)添加IDS_TIMER,
IDS_PROGRESS。
3.在狀態(tài)欄上顯示系統(tǒng)時間,在CMainFrame的OnCreate函數(shù)中:
//CTime::GetCurrentTime//Returns a CTime object that represents the current time.返回一個CTime對象,表明當(dāng)前系統(tǒng)時間
CTime t=CTime::GetCurrentTIme();//獲取當(dāng)前系統(tǒng)時間,它返回一個CTime對象CString str=t.Format("%H:%M:%S");//將當(dāng)前系統(tǒng)時間格式化(獲取表示時間的字符串對象)
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);//將表示時間的字符串對象,輸出到狀態(tài)欄
//BOOL SetPaneText( int nIndex, LPCTSTR lpszNewText, BOOL bUpdate = TRUE );//參數(shù)分別為,狀態(tài)欄面板的索引,字符串文本
//解釋(1)//調(diào)整顯示寬度,因?yàn)榫幾g后發(fā)現(xiàn)窗格太小,并沒用足夠位置顯示到時鐘的秒數(shù)//利用函數(shù)void SetPaneInfo( int nIndex, UINT nID, UINT nStyle, int cxWidth );設(shè)置窗格信息
//CClientDC dc(this);//CSize sz=dc.GetTextExtent(str);//得到字符串顯示(表示時間)的寬度//m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx);//設(shè)置窗格信息
4.讓時間動態(tài)顯示把步驟3的代碼放在OnTimer函數(shù)上
---------------------------------------------------------------
創(chuàng)建一個進(jìn)度欄(CProgressCtrl)
1.在CMainFrame增加成員變量,類型CProgressCtrl,名稱為m_Progress,權(quán)限為protected
2.創(chuàng)建進(jìn)度欄,在CMainFrame::OnCreate()中m_Progress.Create(WS_CHILD | WS_VISIBLE,CRect(100,100,200,120),this,123);
3.設(shè)置進(jìn)度欄位置(利用CProgressCtrl::SetPos),在CMainFrame::OnCreate()中m_Progress.SetPos(50);
4.創(chuàng)建垂直進(jìn)度欄m_Progress.Create(WS_CHILD | WS_VISIBLE | PBS_VERTICAL,CRect(100,100,120,200),this,123);
5.進(jìn)度欄放在狀態(tài)欄窗格
首先要獲取要放置窗格的矩形區(qū)域(利用CStatusBar::GetItemRect函數(shù));然后將窗格的區(qū)域大小,作為我們進(jìn)度欄的區(qū)域大小。
//以上即為實(shí)現(xiàn)代碼,但是放在OnCreate函數(shù)中不能實(shí)現(xiàn):因?yàn)镺nCreate()返回前狀態(tài)欄的位置還沒有確定
//,所以無法獲得各個子窗格位置,只能用自定義消息辦法響應(yīng)。
自定義消息1)在MainFrm.h添加(class CMainFrame : public CFrameWnd前面添加)#define UM_PROGRESS WM_USER+1 //WM_USER加多小隨你,這樣就可以判斷為自定義消息
消息響應(yīng)函數(shù)原形的聲明2)在MainFrm.h中添加(DECLARE_MESSAGE_MAP()前面添加)afx_msg void OnProgress();
消息映射3)MainFrm.cpp中添加(END_MESSAGE_MAP()前面添加)ON_MESSAGE(UM_PROGRESS,OnProgress)
實(shí)現(xiàn)消息響應(yīng)函數(shù)4)void CMainFrame::OnProgress(){CRect rect;m_wndStatusBar.GetItemRect(2,&rect);//獲取狀態(tài)欄要放置窗格的矩形區(qū)域m_Progress.Create(WS_CHILD | WS_VISIBLE,rect,&m_wndStatusBar,123);m_Progress.SetPos(50);}
在OnCreate()函數(shù)中發(fā)送消息5)PostMessage(UM_PROGRESS);//注意不要用SendMessage();因?yàn)镾endMessage是將消息直接發(fā)送給消息響應(yīng)函數(shù),處理完畢之后,SendMessage函數(shù)才返回。PostMessage是將消息發(fā)送給消息隊(duì)列,然后立即返回。之后,程序通告GetMessage取出消息。
當(dāng)窗口尺寸發(fā)生改變,狀態(tài)欄的舉行區(qū)域也要發(fā)生變化,所以當(dāng)窗口尺寸發(fā)生改變時,重新獲取窗格的區(qū)域我們知道,當(dāng)窗口尺寸發(fā)生改變會發(fā)送WM_PAINT消息.只需要在WM_PAINT的響應(yīng)函數(shù)當(dāng)中添加剛才的代碼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);//獲取狀態(tài)欄要放置窗格的矩形區(qū)域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}
--------
讓進(jìn)度欄前進(jìn)在void CMainFrame::OnTimerm_Progress.StepIt();
--------------------------------------------------------------------------------------------
將鼠標(biāo)移動的坐標(biāo),適時顯示到狀態(tài)欄上
1.捕獲鼠標(biāo)移動的消息在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);//要輸出坐標(biāo)到狀態(tài)欄,先將它初始化
((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
我們發(fā)現(xiàn)。。。系統(tǒng)自動增加了CSplashWnd類而且在資源編輯器給我們增加了一副位圖(Bitmap),就是該啟動畫面
在CSplashWnd::OnCreate()中有SetTimer(1,750,NULL);設(shè)置750ms的啟動畫面顯示間隔當(dāng)然你可以把750改大點(diǎn),3000,那就是3秒后再隱藏啟動畫面
新聞熱點(diǎn)
疑難解答