要更改应用程序的窗口的外观,我们可以在两个时候更改,一是在应用程序窗口创建之前,二是在应用程序窗口创建之后进行更改。本文将两种方式记录下来。
在窗口创建之前修改:
我们之前已经知道,在应用程序窗口创建之前会调用一个叫PreCreateWindow()的函数,要想在窗口创建之前修改程序窗口的外观跟大小,就应该在CMainFrame类(SDI程序)中的PreCreateWindow()函数中进行。
virtual BOOL PreCreateWindow( CREATESTRUCT& cs ); //PrecreateWindow()函数原型,参数稍后作解释。
PreCreateWindow()函数是一个虚函数,在MFC的底层代码中,当调用PreCreateWindow()函数时,如果传递了子类对象的指针,根据多态性的原理,那么就会调用子类对象的PreCreateWindow()函数。函数原型中的参数类型是一个CREAGTETRUCT结构,我们这里可以看一下这个结构体中含有哪些字段。
typedef struct tagCREATESTRUCTW { LPVOID lpCreateParams; HANDLE hInstance; HMENU hMenu; HWND hwndParent; int cy; int cx; int y; int x; LONG style; LPCSTR lpszName; LPCSTR lpszClass; DWORD dwExStyle;} CREATESTRUCTW, *PCREATESTRUCTW, *LPCREATESTRUCTW;//This structure defines the initialization parameters passed to the window procedure of an application.
之前我们就应该知道了,CREATESTRUCT结构体中的字段跟CreateWindowEx()函数中的参数是完全一致的(只是顺序相反而已)。PreCreateWindow()函数中的参数是一个引用类型,这样,我们只要更改参数cs中的成员变量的值就能实现目的:因为这种改变会反映到MFC底层代码中,当MFC底层代码调用CrateWindowEx()创建窗口时,它会使用改变后的参数值去创建。
注意:我们修改cs.lpszName的值,在单文档程序的标题中不会体现出来,因为cs.Style默认窗口样式中含有FWS_ADDTOTITLE这种MFC特定的样式,需要将这个样式去掉我们的设置才能生效。如下:
cs.Style &= ~FWS_ADDTOTITLE;
对于窗口的位置和大小,是在创建窗口的时候去设定的,那么我们可通过自己编写窗口类,而让窗口按我们设定的窗口类创建,而窗口的图标、光标和背景是
在设计窗口类的时候设定的,我们可以在CMainFrame::PreCreateWindow编写自己的窗口类。(即定义一个WNDCLASS 对象,对其成员变量赋值,然后使用RegisterClass()函数将其注册,WNDCLASS对象将MENU设为NULL并不会影响MENU的创建,即MENU还会生成)。
但是,由于SDI中含有MainFrame跟一个View的两个窗口(View在Frame之上)。CMainFrame类中的PreCreateWindow()函数中不能修改光标和背景。要改变这些,只能在View类中PreCrateWindow()函数中实现。
综上我们知道:在View类中只能修改客户区含有的内容,在MainFrame中只能修改window(主窗口)含有的内容。
当然,有时候为了能够更改一个光标的指针,就要重写整个的WNDCLASS窗口类,这样不划算!有没有方便的方式呢?MFC中有AfxRegisterWndClass()这个全局函数(Afx开头的都是MFC中的全局函数)。原型如下:
LPCTSTR AFXAPI AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor = 0, HBRUSH hbrBackground = 0, HICON hIcon = 0 );
在CMainFrame类中的PreCreateWindow()函数中使cs.lpszClass成员接收AfxRegisterWndClass()函数的返回值。并对AfxRegisterWndClass()函数参数进行设置就行了。
在窗口创建之后修改:
在窗口创建之后利用SetWindowLong函数来改变窗口的外观,看看函数原型:
LONG SetWindowLong( HWND hWnd, // handle to window int nIndex, // offset of value to set LONG dwNewLong // new value);
我们可以在CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)调用该函数。与SetWindowLong函数相对应的还有GetWindowLong,用来获取指定窗口的信息。(了解一下)
而在窗口建立后修改光标,背景等,我们可以使用一个类似的函数---SetClassLong(),看看原型
DWORD SetClassLong( HWND hWnd, // handle to window int nIndex, // index of value to change LONG dwNewLong // new value);
至于参数中有那些符合的取值,MSDN中详细介绍。我们使用此函数在Viwe类中的OnCreate()函数调用它。
PS:AfxGetInstanceHandle()获取程序句柄
宏MAKEINTRESOUCE将一个int型资源转换成与资源管理函数兼容的资源类型——是一个宏!!!
记录下自己的所学,虽然浅薄!!!如果我是一只蜗牛,那就只能慢慢向上爬!