1 透明控件和窗口的原理都是通过把控件或窗口的背景提取出来,成为一幅图,然后把
该图显示在控件或窗口上就达到了透明的效果。用到的 API 函数有:getwindowrect、
getdc、getdesktopwindow等。不过在win2000下可用SetWindowsAttribute(不知是否写错)
函数来设置窗口的透明度。
2 透明控件、窗体的主要作用是产生不同的视觉效果,并且有时需要看请窗口的背景。
3 你看了下面的文章后,你就能大概了解透明控件、透明窗体的实现机制和具体方法了。
如何制作半透明窗口
松本电工实业有限公司
舒嵩嵩
---- 用过金山词霸的朋友,一定会为其半透明的翻译提示窗口而称奇。究竟这种窗口是如何做出来的呢?下面我们将来探讨这种半透明的窗口的制作方法。
一、 原理
---- 首先,我们先从透明窗口说起,其实透明窗口就是可以透过窗口看到它背景。所以,我们可以将窗口后面的背景图象,显示在窗口前面,就可实现透明窗口的效果了。至于半透明的效果,是在透明的基础上,加上一层滤镜,使看到的背景模糊一点而已。所以,在拿到背景图象后,先在该图象加上一层滤镜(把图象弄模糊),然后再显示在窗口上,就能达到半透明的效果。
---- 我们可归纳出实现半透明窗口的步骤:在窗口显示前其获取背景图 → 对背景图象进行滤镜效果处理 → 将处理过的背景图象显示在窗口前面。
---- (1) 获取背景图象
---- 要获取背景图,先用GetDC(0)函数获取整个屏幕设备场景(DC),再用CopyRect函数拷贝窗口的背景到指定的Tbitmap,该Tbitmap就是我们所要的图象了。其中函数GetDC(0)取得的DC可用TCanvas.Handle保存;而CopyRect是TCancas类的成员函数,作用是从一Canvas中拷贝一指定区域(Rect)到另一Canvas的指定区域。
---- (2)对背景图进行滤镜效果处理
---- 用循环的方法遍历图象的每一点,将各点的某些频段的光波滤除。其实,滤镜种类繁多,所以的算法亦很多,读者们可参考相关资料,选择您满意的方法。本文的滤镜是灰色的,实现方法见TranslucentBmp(Bmp:TBitmap;AColor:TColor;ATransparent:Longint)。其中,参数Bmp是要处理的图象,AColor是滤镜的颜色,ATransparent是透明度。
二、 写程序
- 将以上原理用Delphi编写成程序,在Delphi中新建一Project,Form1的Height和Width分别设成150和300(不要做的太大,不然显示速度很慢),再设置BorderStyle的值为bsNone;在Form1中添加一Timage控件Image1,将其Align属性设成alClient。再添加一标签Label1和按钮TSpeedButton,在Label1的Caption属性中输入"这是一半透明窗口!",按钮的Caption属性设成"x",在其OnClick事件中输入一行"Close;"。并将它们Bring to Front。另外,可添加四个TShape,贴在Image1的四边上,以构造Form1的3D效果,如图(一)。各控件的属性如下表:
组件名称 属性 设置值
Form1 BorderStyle BsNone
Height 150
Width 300
TFont 宋体9号
Image1 Align AlClient
Label1 Caption 这是一半透明窗口!
TFont 宋体9号,黄色
SpeedButton1 Caption X
Left 279
Top -1
Height 14
Width 13
Transparent True
图(一)
---- 完整的源代码如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, Buttons;
type
TForm1 = class(TForm)
Label1: TLabel;
Shape1: TShape;
Shape2: TShape;
Shape3: TShape;
Shape4: TShape;
Image1: TImage;
SpeedButton1: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
private
{ Private declarations }
//截获背景图象
function GetBackgroundBmp:TBitmap;
//对背景图象进行滤镜处理
procedure TranslucentBmp(Bmp:TBitmap;
AColor:TColor;ATransparent:Longint);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//以下截获背景图象
function TForm1.GetBackgroundBmp:TBitmap;
var Scn:TCanvas;
h,w:Integer;
begin
Scn:=TCanvas.Create; //建立整个屏幕的画布
h:=ClientHeight;//窗口的高
w:=ClientWidth; //窗口的宽
Result.Height:=h; //设返回位图的高就是窗口的高
Result.Width:=w;//设返回位图的宽就是窗口的宽
try
Scn.Handle:=GetDC(0);//取得整个屏幕的DC
//以下一行将窗口的背景部分复制到指定的画布中,
也就是本函数的返回值
Result.Canvas.CopyRect(Rect(0,0,w,h),Scn,
Rect(Left,Top,Left+w,Top+h));
ReleaseDC(0, Scn.handle);
finally
Scn.Free;
end;
end;
//以下函数对背景图象进行滤镜处理,
Bmp是要处理的位图;ATransparent是透明度
procedure TForm1.TranslucentBmp(Bmp:
TBitmap;AColor:TColor;ATransparent:Longint);
var BkColor:COLORREF;
ForeColor:Longint;
R,G,B:Int64;
i,j:Integer;
begin
ForeColor:=ColorToRGB(AColor);
with Bmp.Canvas do
for i:=ClientHeight-1 downto 0 do
for j:=ClientWidth-1 downto 0 do
begin
BkColor:=GetPixel(Handle,j,i); //取得每一象素
R:=Byte(ForeColor)+
(Byte(BkColor)-Byte(ForeColor))*ATransparent;
G:=Byte(ForeColor shr 8)+
(Byte(BkColor shr 8)-Byte(ForeColor
shr 8))*ATransparent;
B:=Byte(ForeColor shr 16)+
(Byte(BkColor shr 16)-Byte(ForeColor
shr 16))*ATransparent;
SetPixelV(Handle,j,i,RGB(R,G,B));//合成象素
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var BackgroundBmp:TBitmap;
begin
try
BackgroundBmp:=Tbitmap.Create;
//建立窗口背景图
BackgroundBmp.PixelFormat:=pf24bit;
//指定该图是24位真彩色
BackgroundBmp:=GetBackgroundBmp;
//取得窗口背景图
TranslucentBmp(BackgroundBmp,clBlack,50);
//对该图象进行滤镜处理
Image1.Picture.Bitmap:=BackgroundBmp;
//将处理过的图象显示出来
finally
BackgroundBmp.Free;
end;
end;
procedure TForm1.SpeedButton1Click
(Sender: TObject);
begin
Close;
end;
end.
---- 程序的运行效果如图(一)所示。
三、 结束语
---- 需要说明的是:由于受到以上滤镜算法的速度影响,所以窗口显示时有所延迟,在窗口频繁显示和关闭时不是很流畅。但不知读者朋友们有没有发现,金山词霸的半透明窗口效果只能在带MMX指令集的处理器中才起作用,所以笔者大胆推测,金山词霸的半透明窗口是经过MMX的多媒体指令集进行优化的,这样它才可以达到理想的效果。有兴趣的朋友可以试一下,说不定您做得比金山词霸还好呢。 ---- 以上程序在中文Windows 98、Delphi 4 C/S环境下编译通过。
4 这个通常都是用图片来实现这样的效果。
5 其实要做出这样的效果的最大难点是你要设计出漂亮的图片来,图片做出来了,就容易了,
因为现在有很多控件帮我们,自己做的话,我估计程序的运行效率不高。