SDI的初始化过程
CWinApp --> CDocument --> CFrameWnd --> CView 。(要注意:SDI包含两个窗口,一个是框架窗口,一个是视图窗口,视图窗口覆盖在框架窗口之上,因此操作的时候,需要注意到底是在对视图窗口进行操作,还是在对框架窗口进行操作,SDI窗口是多个窗口的叠加)。
改变窗口的外观
在窗口创建完成之前,可以利用PreCreateWindow()函数去改变窗口的样式(改变CREATESTRUCTURE的值);在窗口创建完成过后,可以在OnCreate函数中利用GetWindowLong函数和SetWindowLong()两个函数来改变窗口的外观。
也可以通过改变窗口的窗口类WNDCLASS的信息来改变窗口的外观。
在PreCreateWindow中进行改变:
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(); //获取应用程序的HINSTANCE;
wndcls.lpfnWndProc=::DefWindowProc; //应用程序的默认消息处理过程,这里使用的是全局的默认消息处理。也可以使用DefWindowProc,即使用CWnd类自带的默认消息处理。
wndcls.lpszClassName="Marcel"; //窗口类变量的类名。
wndcls.style=CS_HREDRAW|CS_HVERDRAW;
RegisterClass(&wndcls); //注册窗口类。
cs.lpszClass="Marcel"; //用新建的窗口类替换原有的窗口类。
也可以使用全局的AfxRegisterClass()来改变CS的某几个属性,具体参照MSDN。
cs.lpszClass=AfxRegisterClass(.....)。这种方法使用很方便,不需要重新写一个类,其实该函数仍然是写一个类赋值给cs响应的成员。
改变窗口的标题
在SDI中,窗口的标题是文档的标题,因此想要改变窗口的标题,需要将文档的标题类型去掉。
使用cs.style = cs.style & ~FWS_ADDTOTITLE;此时,应用程序的标题即只使用程序的标题,而不使用文档的标题。
FWS_ADDTOTITLE是MFC特定的一种样式,只是框架将文档标题添加到窗口标题上。因此,如果想让窗口显示自己设置的标题,需要将此属性去掉。
WNDCLASS
结构WNDCLASS包含一个窗口类的全部信息,也是Windows编程中使用的基本数据结构之一,应用程序通过定义一个窗口类确定窗口的属性。
AfxGetInstanceHandle
This function allows you to retrieve the instance handle of the current application.
SetWindowLong和SetClassLong
SetWindowLong该函数改变指定窗口的属性.函数也将指定的一个32位值设置在窗口的额外存储空间的指定偏移位置。 SetClassLong该函数替换在额外类存储空间的指定偏移地址的32位长整型值,或替换指定窗口所属类的WNDCLASSEX结构. SetClassLong是与窗口类有关,学过win32编程的人都知道,一个应用程序在创建某个类型的窗口(CreateWindow)前,必须首先注册该“窗口类”(Windows Class,WNDCLASS)。而这个Class即表示窗口类,所以SetClassLong是设置窗口类的属性。 SetWindowLong是已经创建好的窗口,所以它是设置窗口的属性。所以这两个还是有区别的,当我们想改变窗口的属性时就调用SetWindowLong,而改变窗口类的属性时最好调用SetClassLong
SetClassLong针对的是窗口类,SetWindowLong针对的是某个具体的窗口;窗口类是一种窗口模板,可以以此窗口类生成多个窗口,因此改变了窗口类,以此为模板生成的窗口都会改变,而SetWindowLong仅仅是改变某个窗口。
SetWindowLong改变的是某个具体的窗口,SetClassLong改变的是某个具体窗口所属的窗口类。
在MFC程序中,如果想要改变应用程序窗口的图标,则应在框架类中进行,因为框架窗口中才有标题栏,所以才能修改位于该标题栏上的图标;如果想要修改程序窗口的背景和光标,则应该在视类中进行。