首先,創(chuàng)建一個單文檔的應(yīng)用程序。
在窗口創(chuàng)建之前修改
方式1
在我們創(chuàng)建的CMainFrame類的PreCreateWindow函數(shù)中寫一個自己的窗口類并注冊
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: 在此處通過修改
// CREATESTRUCT cs 來修改窗口類或樣式
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_HELP);
wc.hIcon = LoadIcon(NULL, IDI_ERROR);
wc.hInstance = AfxGetInstanceHandle();
wc.lpfnWndProc = ::DefWindowProc;
wc.lpszClassName = _T("傳智播客");
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
//注冊窗口類
RegisterClass(&wc);
//類名稱設(shè)置為我們設(shè)計的窗口類的名字
cs.lpszClass = _T("傳智播客");
return TRUE;
}
上邊的代碼把我們的應(yīng)用程序改成了黑色背景,幫助光標,錯誤圖標。使用默認窗口過程函數(shù)。
關(guān)于為什么菜單被創(chuàng)建
運行程序發(fā)現(xiàn)只有圖標改變了,背景和光標并沒有改變,菜單項也沒有消失,為什么呢?
在利用MFC向?qū)蒘DI應(yīng)用程序時,在應(yīng)用程序類的InitInstance函數(shù)中有如下代碼:
// 注冊應(yīng)用程序的文檔模板。 文檔模板
// 將用作文檔、框架窗口和視圖之間的連接
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMenuDoc),
RUNTIME_CLASS(CMainFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CMenuView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
也就是說在創(chuàng)建文檔模板時,將菜單資源標識(IDR_MAINFRAME)作為其中的一個參數(shù)傳入,當MFC底層代碼在創(chuàng)建框架窗口時,就會將此標識轉(zhuǎn)換為相應(yīng)菜單句柄,然后去創(chuàng)建菜單和框架窗口。因此在這里將菜單設(shè)置為NULL,并不會影響菜單的創(chuàng)建。
關(guān)于為什么窗口背景和光標沒有改變
應(yīng)用程序包含連個窗口:
l 應(yīng)用程序框架窗口
l 視類窗口
前者包含了后者,后者覆蓋在前者上面。程序運行后我們看到的窗口實際上是視類窗口,而我們代碼中實際上修改的是框架窗口的背景和光標。應(yīng)用程序的圖標屬于框架窗口,所以程序運行后看到圖標改變了。
改變背景和光標的操作我們應(yīng)該放在視類中實現(xiàn),我們應(yīng)該在視類窗口創(chuàng)建之前,即在PreCreateWindow函數(shù)中將窗口類設(shè)置為先前自定義的那個類,因為這是那個窗口類已經(jīng)注冊了,所以可以直接使用那么窗口類的名字:
BOOL CMyView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此處通過修改
// CREATESTRUCT cs 來修改窗口類或樣式
cs.lpszClass = _T("傳智播客");
return CView::PreCreateWindow(cs);
}
在MFC中如果想修改應(yīng)用程序的窗口的圖標,應(yīng)該在框架類中進行,因為框架窗口中才有標題欄,所以才能修改位于標題欄上的圖標。如果想修改應(yīng)用程序窗口的背景和光標,就應(yīng)該在視類中進行。
方式2
通過上邊的例子我們可以知道,在框架類中只能修改窗口的圖標,而為了實現(xiàn)這一功能,我們需要重寫整個窗口類。顯然,這是一件很麻煩的事情,MFC給我們提供了一個全局函數(shù): AfxRegisterWndClass,用來設(shè)定窗口的類型、光標、圖標、背景。其函數(shù)原型定義如下:
LPCTSTR AFXAPI AfxRegisterWndClass(
UINT nClassStyle,
HCURSOR hCursor = 0,
HBRUSH hbrBackground = 0,
HICON hIcon = 0
);
設(shè)置圖標:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: 在此處通過修改
// CREATESTRUCT cs 來修改窗口類或樣式
cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, 0, 0,
LoadIcon(NULL, IDI_ERROR));
return TRUE;
}
設(shè)置光標和背景色:
BOOL CMenuView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此處通過修改
// CREATESTRUCT cs 來修改窗口類或樣式
cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
LoadCursor(NULL, IDC_HELP),
(HBRUSH)GetStockObject(BLACK_BRUSH), NULL);
return CView::PreCreateWindow(cs);
}
在窗口創(chuàng)建之后修改
使用Windows API函數(shù) SetClassLong
函數(shù)原型如下:
DWORD SetClassLong(HWND hWnd,int nlndex,LONG dwNewLong)
參數(shù):
l hWnd:窗口句柄及間接給出的窗口所屬的類。
l nIndex: 指定要設(shè)置的索引
n GCL_HBRBACKGROUND 設(shè)置新的背景畫刷
n GCL_HCURSOR 設(shè)置新的光標
n GCL_HICON 設(shè)置新的圖標
n GCL_STYLE 設(shè)置新的窗口樣式
設(shè)置圖標:
在CMainFram類的OnCreate函數(shù)最后,return語句之前添加如下代碼:
SetClassLong(m_hWnd, GCL_HICON, (LONG)LoadIcon(NULL, IDI_ERROR));
設(shè)置光標和背景
在瑩瑩程序生成的視類的OnCreate函數(shù)最后,return語句之前添加如下代碼:
//背景色
SetClassLong(m_hWnd, GCL_HBRBACKGROUND,
(LONG)(HBRUSH)GetStockObject(BLACK_BRUSH));
//光標
SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_HELP));
本文版權(quán)歸黑馬程序員C/c++培訓(xùn)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明作者出處。謝謝!
作者:黑馬程序員C/C++培訓(xùn)學(xué)院
首發(fā):http://c.itheima.com