利用.net(C#)在Vista磨砂玻璃窗口上正确画出文字和图片(GDI+版)

本文欢迎转载,但请标明出处.

作者: 吴滂

 貌似Windows Vista昨天正式发布了,也是该写写东西的时候啦,其实这篇文章我很早就写了的,不过是用E文写的,发表在codeproject上:

http://www.codeproject.com/vista/textonglass.asp

当时用的是Windows Vista Beta2 做的测试,演示有些地方已经和现在正式版(或者RC1)的系统不一样,不过功能还是照样能实现的。

现在我们就直入正题吧。Windows Vista给我们带来了磨砂玻璃的半透明窗体边框,其实这个效果是可以扩展到整个窗口区域的,让整个窗体成为一个“玻璃片”,效果就像在Vista下按alt+Tab键后看到的切换窗口一样。要达到这个效果,我们得借助于Vista提供的一组新API :DWM(Desktop Windows Manager) API。主要用到以下几个函数:DwmIsCompositionEnabled 和 DwmExtendFrameIntoClientArea.

当然,调用API的话,P/Invoke代码不可避免,这是这两个API的C#引用声明:

 

[System.Runtime.InteropServices.DllImport( " dwmapi.dll " )]
public   extern   static   int  DwmIsCompositionEnabled( ref   int  en ) ;   // 该函数用于判断Aero合成效果是否打开,否则无法看到磨砂效果
[System.Runtime.InteropServices.DllImport( " dwmapi.dll " )]
public   extern   static   int  DwmExtendFrameIntoClientArea(IntPtr hwnd,  ref  MARGINS margin ) ;   // 该函数用于扩展玻璃区域

 

要注意DwmExtendFrameIntoClientArea函数最后一个参数为MARGINS 结构体,用于确定要扩展的玻璃区域距离窗体上下左右边框的距离大小,它的定义为:

 

public   struct  MARGINS
{
     
public int m_left;
     
public int m_right;
     
public int m_top;
     
public int m_buttom
}
;

如果你要把整个窗口都变成玻璃,只需把MARGINS所有成员设为-1。下面是一段示例代码:

 

int  en = 0 ;

MARGINS mg
= new  MARGINS();

mg.m_Buttom 
=   - 1 ;

mg.m_Left 
=   - 1 ;

mg.m_Right 
=   - 1 ;

mg.m_Top 
=   - 1  ;
// 确保你使用的是Vista
if  (System.Environment.OSVersion.Version.Major  >=   6 )             
{
    DwmIsCompositionEnabled(
ref en);    //检测Aero合成已经被打开
    if(en>0)
    
{
          DwmExtendFrameIntoClientArea(
this.Handle, ref mg);

    }
else{
          MessageBox.Show(
"Desktop Composition is Disabled!");

    }

}
else {

     MessageBox.Show(
"Please run this on Windows Vista.");

}

如果你这时按下F5,会发现看不到任何特殊的效果:窗体还是和原来一样。那是因为系统在本来应该是玻璃的区域自动用默认背景色填充了,以致于看不到效果。这个时候,我们必须在Paint事件上做写些脚,把整个窗体用纯黑填充(RGB(0,0,0)刚好和ARGB的100%透明有着一样的bit pattern ),本来还有一个办法能看到效果,就是设置透明颜色让背景透明,但是这个方法已经在RC1的Vista之后不可用,就不做介绍了。

void  Form1_Paint( object  sender, PaintEventArgs e)
        
{
            
//throw new Exception("The method or operation is not implemented.");
            SolidBrush bsh;
            bsh 
= new SolidBrush(Color.FromArgb(Convert.ToInt32(bgAlpha.Text ),Color.Black ));
            Graphics g 
= e.Graphics;
            g.FillRectangle(bsh, 
this.pictureBox2.ClientRectangle );  //pictureBox2铺满整个窗体
            bsh.Dispose();

        }

这样就可以看到效果:

实现了玻璃效果后你很快会发现问题:图片框和Label不能正确的显示文字,文本框文字的黑色部分也会变成玻璃效果:

用Graphics的DrawString也无法在玻璃上面画出正常的文本。为了能正确的画出文本,我们不能直接使用Graphic对象,而必须先把要画的字“写”在一个Path对象上面,最后再把Path用Graphics.FillPath填充到窗体上:

Graphics g  =   this .CreateGraphics();

GraphicsPath blackfont 
=   new  GraphicsPath();

SolidBrush brsh 
=   new  SolidBrush(Color.White);

blackfont.AddString(
" Hello Vista " new  FontFamily( " Tahoma " ,
(
int )FontStyle.Regular,  26 new  Point( 0 0 ), StringFormat.GenericDefault);

// SmoothingMode 是必须的, 否则会看到文本的锯齿边缘

g.SmoothingMode 
=  System.Drawing.Drawing2D.SmoothingMode.HighQuality  ;   
g.FillPath(brsh, blackfont);    
// 用白色填充文本

效果:

当然,如果你只是画图片到玻璃区域,Graphics的DrawImage就足够了:

当然,这种画文本的方法并不是Windows的“标准方法”,至于如何利用API在玻璃区域上画出像标题文字一样的带白色渐变效果的文本,我会在后面的文章里介绍,这里先给大家看看效果图:

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值