第九章、定制应用程序外观

9.1修改应用程序窗口的外观

对于MFC AppWizard生成的应用程序,我们可以在应用程序窗口创建之前修改,也可以在该窗口创建之后进行。

9.1.1在窗口创建之前修改

新建一个单文档应用程序,取名Style,如果想在应用程序创建之前修改它的外观和大小,就应该在框架类的PreCreateWindow成员函数中进行。

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;
}

PreCreateWindow是一个虚函数,可以利用多态性调用子类对象的PreCreateWindow函数。
CREATESTRUCT结构中的字段与CreateWindowEx函数中的参数是完全一致的,只不过顺序相反而已。因为CREATESTRUCT参数为引用类型,可以在子类对象中修改这个参数成员变量的值。
当MFC底层代码调用CreateWindowEx函数去创建窗口时,他就会使用改变后的参数值去创建这个窗口。这里该变量窗口的长度和宽度。如图。
在这里插入图片描述
如果想修改应用程序窗口的坐标,可以修改CREATESTRUCT结构体中lpszName成员的值来实现。
cs.lpszName=“vc++”;
但是运行后,发现应用程序标题并没有发生改变。
这个Style应用程序是一个单文档应用程序,在单文档的界面中,程序默认的窗口样式是WS_OVERLAPPEDWINDOW和FWS_ADDTOTITLE,FWS_ADDTOTITLE是MFC特定的一种样式,指示框架将文档标题添加到窗口标题之上,如果想让窗口显示自己的标题,只需要将窗口的FWS_ADDTOTITLE样式去掉即可。
cs.style &= ~FWS_ADDTOTITLE;
或者cs.style =cs.style & ~FWS_ADDTOTITLE;
或者cs.style =WS_OVERLAPPEDWINDOW;
如图。
在这里插入图片描述

9.1.2在窗口创建之后修改

窗口创建之后可以利用SetWindowLong函数进行修改,为了改变窗口类型,该函数第二个参数为GWL_STYLE,第三个参数指定新的窗口类型。在窗口创建之后改变其外观,可以在框架类OnCreate函数中实现。

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 ……
 // TODO: Delete these three lines if you don't want the toolbar to
 //  be dockable
 m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
 EnableDocking(CBRS_ALIGN_ANY);
 DockControlBar(&m_wndToolBar);
 SetWindowLong(m_hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW);
 return 0;
}

运行程序,发现窗口标题栏上面去掉了文本标题。如图。
在这里插入图片描述
如果在已有的窗口类型上面进行修改,首先要获得该窗口类型,利用GetWindowLong函数。

LONG GetWindowLong(
  HWND hWnd,  // handle of window
  int nIndex  // offset of value to retrieve
);

如果将第二个参数设定为GWL_STYLE,获取指定窗口的类型。

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 ……
 // TODO: Delete these three lines if you don't want the toolbar to
 //  be dockable
 m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
 EnableDocking(CBRS_ALIGN_ANY);
 DockControlBar(&m_wndToolBar);
 SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE)& ~WS_MAXIMIZEBOX);
 return 0;
}

运行,发现右上角最大化框变灰了,窗口就不能放大。如图。
在这里插入图片描述

9.2修改窗口的光标、图标和背景。

9.2.1在窗口创建之前修改

图标、光标和背景是在设计窗口类时指定的,因此在框架类的PreCreateWindow函数中编写自己的窗口类并注册。

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
 if( !CFrameWnd::PreCreateWindow(cs) )
  return FALSE;
 // TODO: Modify the Window class or styles here by modifying
 //  the CREATESTRUCT cs
 WNDCLASS wndcls;
 //类的额外内存和窗口的额外内存都设置为0
 wndcls.cbClsExtra=0;
 wndcls.cbWndExtra=0;
 //背景设置为黑色
 wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
 //使用系统光标,第一个参数为NULL,使用系统帮助光标
 wndcls.hCursor=LoadCursor(NULL,IDC_HELP);
 //使用系统错误的图标
 wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);
 //调用该函数,获取当前应用程序实例句柄
 wndcls.hInstance=AfxGetInstanceHandle();
 //调用默认的窗口过程函数,不做特殊消息的处理
 wndcls.lpfnWndProc=::DefWindowProc;
 //类的名称和菜单的名称、窗口类的类型是水平和垂直重绘
 wndcls.lpszClassName="vc++";
 wndcls.lpszMenuName=NULL;
 wndcls.style=CS_HREDRAW | CS_VREDRAW;
 RegisterClass(&wndcls);
 //使用刚刚注册的窗口类
 cs.lpszClass="vc++";
 return TRUE;
}

运行程序,发现只有图标变化了,光标和背景没有变化。如图。
在这里插入图片描述
因为只有图标是在框架类窗口上,没有被视类覆盖。因此对于光标和背景的修改需要在视类中修改。
因为窗口类已经注册了,所以创建视类窗口时,可以直接使用该窗口类。

BOOL CStyleView::PreCreateWindow(CREATESTRUCT& cs)
{
 // TODO: Modify the Window class or styles here by modifying
 //  the CREATESTRUCT cs
 cs.lpszClass="vc++";
 return CView::PreCreateWindow(cs);
}

运行结果如图。
在这里插入图片描述
重写窗口类这个方法很麻烦,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: Modify the Window class or styles here by modifying
 //  the CREATESTRUCT cs
 cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,0,0,LoadIcon(NULL,IDI_WARNING)); 
 return TRUE;
}

只设置一个警告类型的图标
在视类中:

BOOL CStyleView::PreCreateWindow(CREATESTRUCT& cs)
{
 // TODO: Modify the Window class or styles here by modifying
 cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,LoadCursor(NULL,IDC_CROSS),(HBRUSH)GetStockObject(BLACK_BRUSH),0); 
 return CView::PreCreateWindow(cs);
}

设置一个十字形状的光标,背景设置为黑色。

但是,如果均用默认的0。光标就是箭头,背景透明,图标就是Windows Logo。

9.2.2在窗口创建之后修改

这时可以利用全局API函数:SetClassLong。

DWORD SetClassLong(
  HWND hWnd,       // handle of window
  int nIndex,      // index of value to change
  LONG dwNewLong   // new value
);

第二个参数是属性的索引。
GCL_HBRBACKGROUND:设置新的背景画刷。
GCL_HCURSOR:设置新的光标。
GCL_HICON:设置新的图标。
GCL_STYLE:设置新的窗口样式。
第三个参数:要设置的新的属性值。

首先在框架类的OnCreate函数中设置图标:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 ......
 // TODO: Delete these three lines if you don't want the toolbar to
 //  be dockable
 m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
 EnableDocking(CBRS_ALIGN_ANY);
 DockControlBar(&m_wndToolBar);
 SetClassLong(m_hWnd,GCL_HICON,(LONG)LoadIcon(NULL,IDI_ERROR));
 return 0;
}

由于视类没有OnCreate函数,所以需要添加WM_CREATE消息相应函数。

int CStyleView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
 if (CView::OnCreate(lpCreateStruct) == -1)
  return -1;
 // TODO: Add your specialized creation code here
 SetWindowLong(m_hWnd,GCL_HBRBACKGROUND,(LONG)GetStockObject(BLACK_BRUSH));
 SetWindowLong(m_hWnd,GCL_HCURSOR,(LONG)LoadCursor(NULL,IDC_HELP));
 return 0;
}

修改窗口的光标和背景。运行结果与前面是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

身影王座

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值