窗口风格的实际效果

窗口风格对窗口有很多影响,我先简单将一些使用常见窗口风格的结果,展现如下。




我们知道

  • WS_BORDER   Creates a window that has a border.

  • WS_DLGFRAME   Creates a window with a double border but no title.

  • WS_CAPTION   Creates a window that has a title bar (implies the WS_BORDER style). Cannot be used with the WS_DLGFRAME style.

  • WS_THICKFRAME   Creates a window with a thick frame that can be used to size the window.

  • WS_EX_WINDOWEDGE   Specifies that a window has a border with a raised edge.

  • WS_EX_CLIENTEDGE   Specifies that a window has a 3D look — that is, a border with a sunken edge.

  • WS_EX_STATICEDGE   Creates a window with a three-dimensional border style intended to be used for items that do not accept user input.

这些风格都可以改变窗口的边界。

1.WS_BORDER

  1. int nBorder = GetSystemMetrics(SM_CYBORDER);    // nBorder为1  
  2. m_tWnd.Create(NULL, NULL, WS_VISIBLE|WS_BORDER, CRect(100,100,200,200), GetDesktopWindow(), 0);  
  3.   
  4. CRect   rcWnd;  
  5. CRect   rcClient;  
  6. m_tWnd.GetWindowRect(rcWnd);  
  7. m_tWnd.GetClientRect(rcClient);  
  8.   
  9. // 结果:rcWnd(top=100,left=100,right=300,bottom=300)  
  10. //      rcClient(top=0,left=0,right=198,bottom=198)  

这里很明显nBorder的值为1,实际上客户区就是排除了该Border的值来设定的。


2.WS_DLGFRAME

  1. int nDlgFrame = GetSystemMetrics(SM_CYDLGFRAME);    // nDlgFrame为3  
  2. m_tWnd.Create(NULL, NULL, WS_VISIBLE|WS_DLGFRAME, CRect(100,100,300,300), GetDesktopWindow(), 0);  
  3.   
  4. CRect   rcWnd;  
  5. CRect   rcClient;  
  6. m_tWnd.GetWindowRect(rcWnd);  
  7. m_tWnd.GetClientRect(rcClient);  
  8.   
  9. // 结果:rcWnd(top=100,left=100,right=300,bottom=300)  
  10. //      rcClient(top=0,left=0,right=194,bottom=194)  

这里窗口的非客户区的宽度四个方向均为3,可见就是GetSystemMetrics(SM_CYDLGFRAME)的值。


3.再看下WS_CAPTION(虽然MSDN说不要WS_CAPTION不能和WS_DLGFRAME一同使用,但我们知道WS_CAPTION是WS_BORDER和WS_DLGFRAME的集合)

  1. int nCaption = GetSystemMetrics(SM_CYCAPTION);  // nCaption为22  
  2. m_tWnd.Create(NULL, NULL, WS_VISIBLE|WS_CAPTION, CRect(100,100,300,300), GetDesktopWindow(), 0);  
  3.   
  4. CRect   rcWnd;  
  5. CRect   rcClient;  
  6. m_tWnd.GetWindowRect(rcWnd);  
  7. m_tWnd.GetClientRect(rcClient);  
  8.   
  9. // 结果:rcWnd(top=100,left=100,right=200,bottom=200)  
  10. //      rcClient(top=0,left=0,right=194,bottom=172)  

这里很明显了,窗口先切去FRAME这个框架的四个方向的宽度,为3。然后切去CAPTION占用的高度,为22。剩余的就是客户区的高度(即200 - 3 - 22)。

但是实际上我截取的窗口范围是210X210(本文开头的图片有表示)。窗口无缘无故的扩张了10X10的范围,但是客户区的范围是正确的。这是为什么呢?

为什么边界被扩张了呢?我发贴也没人解答,但是你们打开任务管理器(在WIN7下面)是不是看到了dwm.exe这个程序。这个程序叫Desktop Window Manager,查了一下有关这方面的资料。的确是这个程序捣鬼的。我在服务里面关闭了该程序,显示的实际窗口和程序获得的窗口就一致了。


下面的几个窗口风格,凡是被扩张了10X10的边界的,都是dwm.exe这个程序捣鬼的,这里我就不一一表述了。

但是我还想再追加几个问题,如果你想自绘标题栏,你该如何是好呢?

第一,你得自己设定哪里是客户区,哪里是非客户区。

使用WM_NCCALCSIZE该消息,把你认为是非客户区的部分截去。代码如下:

  1. CDrawTitleBarDlg::CDrawTitleBarDlg(CWnd* pParent /*=NULL*/)  
  2.     : CDialog(CDrawTitleBarDlg::IDD, pParent)  
  3. {  
  4.     // ...  
  5.     //Thickness of the sizing border around  
  6.     m_nNcFrameThick     = GetSystemMetrics(SM_CYFRAME);  
  7.     //Height of a button in a window's caption or title bar, in pixels.  
  8.     m_nCaptionThick     = GetSystemMetrics(SM_CYCAPTION);  
  9.     // ...  
  10. }  
  11.   
  12. void CDrawTitleBarDlg::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)  
  13. {  
  14.     if (!bCalcValidRects) {  
  15.         return;  
  16.     }  
  17.     // 自己计算客户区大小  
  18.     lpncsp->rgrc[0].left += m_nNcFrameThick;  
  19.     lpncsp->rgrc[0].top += m_nNcFrameThick + m_nCaptionThick;  
  20.     lpncsp->rgrc[0].right -= m_nNcFrameThick;  
  21.     lpncsp->rgrc[0].bottom -= m_nNcFrameThick;  
  22. }  

这里是按照系统绘制具有WS_CAPTION来设定的,你也可以自己改变边框以及标题栏厚度。

重载WM_NCPAINT消息,自己绘制。


有关桌面窗口管理器的知识:

在vista系统中,应用程序的非客户区域(标题栏,图标,边框,标题栏按钮)的外观都是DWM控制的.使用DWM的API,你可以控制DWN渲染窗口的边框.

DWM AP的一个特性是允许扩展应用程序边框到客户端区域。这使你可以集成客户端的用户界面,比如工具栏,到外框中,使某些控件显示在系统界面的最突出的位置。比如,vista上的IE7就通过扩展上边框在外框集成了导航条

关闭桌面窗口管理器dwm.exe服务的办法:

>Start
>Control Panel
>Administrative Tools
>Services

>Look down the list for 'Desktop Window Manager Session Manager' and double click. Select startup type 'Disabled' and reboot the machine or just force the service to stop.

本文转自:http://blog.youkuaiyun.com/oldmtn/article/details/7257788

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值