注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

隐龙 为了一生的信念

今日默默沉于水,他日飞腾在九天...

 
 
 

日志

 
 

Desktop Window Manager ——Delphi开发实践  

2012-07-10 12:33:50|  分类: Delphi |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

首先介绍一下在Delphi(2007版本以上)中对DWM所做的简单的支持。

Dwmapi.pas单元包含了DWM API调用所需要的函数,结构及常量。

并在窗体TForm的属性中添加了GlassFrame属性:

GlassFrame的成员介绍一下:
Left,Top,Right,Bottom:表示边框扩展的边距
Enabled:表示是否启用边框扩展
SheetOfGlass:表示是否启用全透明玻璃效果

下面举几个列子来说明。

第一个例子(普通边框扩展效果)

我设置GlassFrame属性如下:

窗体设计器显示为:

运行为:

第二个例子(全透明效果)

我设置GlassFrame属性如下:

窗体设计器显示为:

运行为:

Delphi通过TCustomForm的UpdateGlassFrame来实现边框扩展。

我在这里贴一下它的代码,大家可以看一下,

最终是通过调用Dwmapi的DwmExtendFrameIntoClientArea函数来实现边框扩展:

  1. procedureTCustomForm.UpdateGlassFrame(Sender: TObject);  
  2. var  
  3.  LMargins: UxTheme.TMargins;  
  4. begin  
  5.   ifDwmCompositionEnabled and HandleAllocated then  
  6.  begin  
  7.    with LMargins, FGlassFrame do  
  8.    begin  
  9.      if Enabled then  
  10.      begin  
  11.        if not SheetOfGlass then  
  12.        begin  
  13.          cxLeftWidth := Left;  
  14.          cxRightWidth := Right;  
  15.          cyTopHeight := Top;  
  16.          cyBottomHeight := Bottom;  
  17.        end  
  18.        else  
  19.        begin  
  20.          cxLeftWidth := -1;  
  21.          cxRightWidth := -1;  
  22.          cyTopHeight := -1;  
  23.          cyBottomHeight := -1;  
  24.        end;  
  25.        if not (csDesigning in ComponentState) then  
  26.          ControlState := ControlState + [csGlassPaint];  
  27.      end  
  28.      else  
  29.      begin  
  30.        ControlState := ControlState - [csGlassPaint];  
  31. {$IF NOT DEFINED(CLR)}  
  32.        FillChar(LMargins, SizeOf(LMargins), 0);  
  33. {$IFEND}  
  34.      end;  
  35.    end;  
  36.    if (csDesigning in ComponentState) then  
  37.      InvalidateRect(Handle, nil, True)  
  38.    else  
  39.    begin  
  40.      DwmExtendFrameIntoClientArea(Handle, LMargins);  
  41.      Invalidate;  
  42.    end;  
  43.   end  
  44.  else  
  45.  begin  
  46.    ControlState := ControlState - [csGlassPaint];  
  47.    if (csDesigning in ComponentState) then  
  48.      InvalidateRect(Handle, nil, True)  
  49.  end;  
  50. end;  

UpdateGlassFrame函数在CreateWnd 方法,Loaded方法,WM_DWMCOMPOSITIONCHANGED和WM_DWMNCRENDERINGCHANGED这两个消息的消息处理中调用,对于需要自已处理DWM的可以留意一下。



这一节开始,我们研究一下傲游的Areo效果实现。

傲游默认皮肤在Windows 7下面也是有Areo效果的。

下面是傲游界面截图:

通过这张图片,可以直接看出傲游左边的插件栏以及顶部的标签页头都是背景模糊的。



通过拉伸窗体的刷新延时(下图,是我用相机摄像,放到电脑上播放,然后停到这画面的时候再截的,真幸苦),可以看到它边框实际扩展的范围。

实际上,底部的状态栏和头部的工具栏也在边框扩展的范围之内:


因此我们可以得出实际边框扩展的区域为红色外框和内框之间的区域(下图):

初步测量了一下,顶部扩展了80个像素,左边扩展了48个像素,底部扩展了32个像素,右边只扩展了5个像素。

我们在代码里设置一下DWM边框扩展的边距:

 FMarInset.cxLeftWidth:=48;

 FMarInset.cyTopHeight:=80;

 FMarInset.cxRightWidth:=5;

 FMarInset.cyBottomHeight:=32;

效果如下:

接下来放置左上角头像图片框了。

因为我们现在这个窗体的客户区是整个窗体,这是什么意思呢?

我用图片举个简明的例子吧,

下图是普通窗体,我在客户区放一个TButton,

设计时:


运行时:

这次来看看我们边框扩展后的窗体,

设计时(与普通窗体相同):


运行时:

大家看明白了没有?(关于按钮的Caption为什么为半透明显示,下次再讲解)

控件的位置(Left,Top属性)是以窗体的客户区为基准的。

因此,放置头像图片框的时候,我们只需将它放在窗体客户区左上角即可。

设计状态(Left=2,Top=2):


运行时正常状态:

运行时鼠标停靠状态:

在窗体背景模糊的区域上绘制时首先要注意一点,

就是如果要让控件透明,它的背景必须得为黑色,

因为黑色的ARGB分量分别为0,0,0,0,

在DWM合成时会被视作透明色。

设计期如果窗体颜色设置为黑色,不是很好,

比如我的背景透明控件,

在窗体颜色为 clBlack的时候是这样子的(连字都看不见了):


在窗体颜色为clBtnFace的时候是这样子的:


所以我建议在窗体的FormCreate过程中写代码让窗体颜色变为黑色clBlack即可。

 

接下来是多页面控件:

由于省时,我在TabSheet中只是放了一张图片替代显示网页了,呵呵。

由于DWM提供的WM_NCHitTest消息的处理函数DwmDefWindowProc不是很完善,所以会出来鼠标明明移出了窗体,但系统按钮还高亮显示,如下图的关闭按钮(同时亮着):

 

今天先写到这时,五一期间好好想想有什么要补充的,以及接下来研究哪款软件的Areo实现。。 



  评论这张
 
阅读(802)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018