孙鑫
VC++
讲座笔记
Lesson 9 修改应用程序的外观,工具栏、状态栏编程
第一部分 改变应用程序的外观
一、 问题:要修改一个应用程序的外观,应该在应用程序创建之前还是在创建之后修改呢?
修改一幢楼房应在建成之前,应在窗口创建之前修改。要改变一个框架窗口的外观,应在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