首先,创建一个单文档的应用程序。
在窗口创建之前修改
方式1
在我们创建的CMainFrame类的PreCreateWindow函数中写一个自己的窗口类并注册
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);
//类名称设置为我们设计的窗口类的名字
cs.lpszClass = _T("传智播客");
return TRUE;
}
上边的代码把我们的应用程序改成了黑色背景,帮助光标,错误图标。使用默认窗口过程函数。
关于为什么菜单被创建
运行程序发现只有图标改变了,背景和光标并没有改变,菜单项也没有消失,为什么呢?
在利用MFC向导生成SDI应用程序时,在应用程序类的InitInstance函数中有如下代码:
// 注册应用程序的文档模板。 文档模板
// 将用作文档、框架窗口和视图之间的连接
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMenuDoc),
RUNTIME_CLASS(CMainFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CMenuView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
也就是说在创建文档模板时,将菜单资源标识(IDR_MAINFRAME)作为其中的一个参数传入,当MFC底层代码在创建框架窗口时,就会将此标识转换为相应菜单句柄,然后去创建菜单和框架窗口。因此在这里将菜单设置为NULL,并不会影响菜单的创建。
关于为什么窗口背景和光标没有改变
应用程序包含连个窗口:
l 应用程序框架窗口
l 视类窗口
前者包含了后者,后者覆盖在前者上面。程序运行后我们看到的窗口实际上是视类窗口,而我们代码中实际上修改的是框架窗口的背景和光标。应用程序的图标属于框架窗口,所以程序运行后看到图标改变了。
改变背景和光标的操作我们应该放在视类中实现,我们应该在视类窗口创建之前,即在PreCreateWindow函数中将窗口类设置为先前自定义的那个类,因为这是那个窗口类已经注册了,所以可以直接使用那么窗口类的名字:
BOOL CMyView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
cs.lpszClass = _T("传智播客");
return CView::PreCreateWindow(cs);
}
在MFC中如果想修改应用程序的窗口的图标,应该在框架类中进行,因为框架窗口中才有标题栏,所以才能修改位于标题栏上的图标。如果想修改应用程序窗口的背景和光标,就应该在视类中进行。
方式2
通过上边的例子我们可以知道,在框架类中只能修改窗口的图标,而为了实现这一功能,我们需要重写整个窗口类。显然,这是一件很麻烦的事情,MFC给我们提供了一个全局函数: AfxRegisterWndClass,用来设定窗口的类型、光标、图标、背景。其函数原型定义如下:
LPCTSTR AFXAPI AfxRegisterWndClass(
UINT nClassStyle,
HCURSOR hCursor = 0,
HBRUSH hbrBackground = 0,
HICON hIcon = 0
);
设置图标:
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;
}
设置光标和背景色:
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);
}
在窗口创建之后修改
使用Windows API函数 SetClassLong
函数原型如下:
DWORD SetClassLong(HWND hWnd,int nlndex,LONG dwNewLong)
参数:
l hWnd:窗口句柄及间接给出的窗口所属的类。
l nIndex: 指定要设置的索引
n GCL_HBRBACKGROUND 设置新的背景画刷
n GCL_HCURSOR 设置新的光标
n GCL_HICON 设置新的图标
n GCL_STYLE 设置新的窗口样式
设置图标:
在CMainFram类的OnCreate函数最后,return语句之前添加如下代码:
SetClassLong(m_hWnd, GCL_HICON, (LONG)LoadIcon(NULL, IDI_ERROR));
设置光标和背景
在莹莹程序生成的视类的OnCreate函数最后,return语句之前添加如下代码:
//背景色
SetClassLong(m_hWnd, GCL_HBRBACKGROUND,
(LONG)(HBRUSH)GetStockObject(BLACK_BRUSH));
//光标
SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_HELP));
本文版权归黑马程序员C/c++培训学院所有,欢迎转载,转载请注明作者出处。谢谢!
作者:黑马程序员C/C++培训学院
首发:http://c.itheima.com