第一部分 改变应用程序的外观 一、 问题:要修改一个应用程序的外观,应该在应用程序创建之前还是在创建之后修改呢? 修改一幢楼房应在建成之前,应在窗口创建之前修改。要改变一个框架窗口的外观,应在CMainFrame::PreCreateWindow()中去改变, CREATESTRUCT cs结构体的类型和个数与创建窗口的CreateWindowEx()的个数和类型是完全一致的。只是顺序正好相反。 PreCreateWindow(cs)的参数cs被声明为一个引用类型,如果在子类中修改了cs的值,这种改变会反应到MFC的底层代码中。 1、修改窗口的大小: 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.cx=300; cs.cy=200; return TRUE; } 2、修改窗口的标题 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.lpszName="http://www.sunxin.org"; return TRUE; } 标题并没有被改变。 分析:程序是一个SDI应用程序,打开Word时,它的标题栏显示的一个“文档1”标题, 在MSDN中,Window Styles 在一个SDI应用程序中,缺省的窗口类型是WS_OVERLAPPEDWINDOW 和FWS_ADDTOTITLE的组合。 FWS_ADDTOTITLE 用来增加文档的标题到窗口的标题 去掉FWS_ADDTOTITLE属性。 cs.style&=~FWS_ADDTOTITLE; //取反,并进行与操作。 cs.style=WS_OVERLAPPEDWINDOW; //直接赋值 二、 问题:在窗口创建之后能不能修改外观和大小呢? The SetWindowLong function changes an attribute of the specified window LONG SetWindowLong( HWND hWnd, int nIndex, GWL_STYLE LONG dwNewLong ); 在OnCreate函数中去改变 在所有的窗口对象(C++对象)中都有一个公有的成员变量m_hWnd,保存了与对象相关的窗口的句柄。 SetWindowLong(m_hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW); 问题:在使用SetWindowLong设置窗口类型里,想获得现有的窗口类型,怎么进行? LONG GetWindowLong( HWND hWnd, //窗口句柄 int nIndex //常量,指定窗口的那种信息 如:GWL_STYLE ); 获取现有类型,去掉最大化按钮 SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE) & ~WS_MAXIMIZEBOX); 三、 如果要修改窗口的图标、光标和背景,应该如何去修改? 图标、光标和背景是在设计窗口类时被指定的,窗口类的设计和注册是由MFC的底层代码自动实现的,不可能去修改MFC的底层代码,如何修改? 一、自己编写窗口类,并注册,让随后的窗口的创建按照我们设计好的窗口类去创建。 在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;//必须指定为API函数,不同于CWnd中的DefWindowProc(参数个数不同) wndcls.lpszClassName="sunxin.org"; wndcls.lpszMenuName=NULL;//菜单的创建并不是在设计窗口类时创建的,由MFC在构造pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,…) 被创建。 wndcls.style=CS_HREDRAW | CS_VREDRAW; RegisterClass(&wndcls); cs.lpszClass="sunxin.org";//precreatewindow()中判lpszClass是否为空,不为空说明已注册 编译并运行,发现只有图标被改变,背景、光标未改变,为什么? 答:view始终履盖在frame窗口上,必须在view类的precreatewindow中,指定窗口类为刚才自己编写的这个窗口类。 BOOL CStyleView::PreCreateWindow(CREATESTRUCT& cs) { cs.lpszClass="sunxin.org"; //这个窗口类已经注册了,只要指定即可 return CView::PreCreateWindow(cs); } 四、 在框架窗口中只能修改图标,为了修改图标需要重写窗口类,太麻烦,MFC中提供了一个全局函数,AfxRegisterWndClass()修改、设定一个窗口类的类型,光标、背景、图标。返回一个注册成功的窗口类类名。如果只修改类的类型(wndcls.style),只要第一个参数,其它取默认值。 LPCTSTR AFXAPI AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor = 0, HBRUSH hbrBackground = 0, HICON hIcon = 0 ); 1、 改变框架窗口的图标 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,0,0,LoadIcon(NULL,IDI_WARNING));// return TRUE; } 2、改变光标和背景,在view中 BOOL CStyleView::PreCreateWindow(CREATESTRUCT& cs) { cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, LoadCursor(NULL,IDC_CROSS),(HBRUSH)GetStockObject(BLACK_BRUSH),0); return CView::PreCreateWindow(cs); } 3、只给AfxRegisterWndClass()的第一个参数赋值,其余取缺省值,cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW); 发现:图标变成wave-flag,光标是箭头形状,背景变成透明。

评论