各位,用COOLFORM透明窗口是做出来了,但是怎样才能做出不规则的窗口啊???(100分)

  • 主题发起人 主题发起人 firewind
  • 开始时间 开始时间
F

firewind

Unregistered / Unconfirmed
GUEST, unregistred user!
各位,用COOLFORM透明窗口是做出来了,,,但是怎样才能做出不规则的窗口啊???
 
文字的:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure FormDblClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}



procedure TForm1.FormDblClick(Sender: TObject);
var
ppp,mybrush,mydc:Longint ;
begin
mybrush:=CreateSolidBrush(clred );
mydc:=GetDC(handle);
BeginPath (mydc) ;
SelectObject(mydc,mybrush );
Ellipse(mydc ,100,100,510,360);
DeleteObject(mybrush );
EndPath (mydc);
ppp:= PathToRegion(mydc);
SetWindowRgn( handle, ppp, true );
end;

procedure TForm1.Button1Click(Sender: TObject);
var
ppp,mydc:Longint ;
begin
BeginPath(Canvas.Handle);
SetBkMode( Canvas.Handle, TRANSPARENT );
Canvas.Font.Name:= '宋体';
Canvas.Font.Size:=300;
Canvas.TextOut( 20, 20, '帅');//用"帅"作为form的形状
EndPath(Canvas.Handle);
ppp:= PathToRegion(Canvas.Handle);
SetWindowRgn( Handle, ppp, true );
end;

procedure TForm1.FormCreate(Sender: Tobject);
var hr :thandle;
begin
hr:=createroundrectrgn(0,0,width,height,100,50);//定义园角矩形(win API函数)
setwindowrgn(handle,hr,true); //设置园角窗口
end;


end.

如果是其他不规则的,你要把它拆分成许多规则的东西,然后合并:用
CombineRgn这个函数
 
好象蛮复杂的......
 
呵呵,不是很复杂,只是我懒得筛选了,里面有许多相关的而已。
实际上生成文字的只有一段
 
如果我只想做一个三角形的窗口呢?是不是要做一个三角形的图片,然后在COOLFROM里调用啊???
 
具体实现方式一般分为两步:

  1.定义所需形状的区域边界形状(比如:椭圆形)。

  2.将已定义的区域边界形状运用到窗口。

  这里,我们将通过调用Windows API函数完成以上两个步骤,下面就具体函数的应用予以说明:

  实现第一步:定义区域边界。

  在这里将调用三个WinAPI,这三个函数是:

  CreateEllipticRgn()功能是生成椭圆形区域;

  CreateRoundRectRgn()功能是生成圆角矩形区域;

  CreatePolygonRgn()功能是生成多边形区域,Windows要确保使其顶点自动相连形成一封闭的区域。

  这三个函数通过返回的指针变量标识所生成的区域将被第二步所应用。这些函数在Delphi中的函数声明及参数含义说明如下:

  (1)椭圆形区域生成函数:

   函数原形:HRGN CreateEllipticRgn(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect);

   参数含义:

   nLeftRect,nTopRect:区域的左上角坐标;

   nRightRect, nBottomRect:区域的右下角坐标;

  (2)圆角矩形区域生成函数:

   函数原形:HRGN CreateRoundRectRgn(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect,int nWidthEllipse,int nHeightEllipse);

   参数含义:

   nLeftRect, nTopRect:区域的左上角坐标;

   nRightRect, nBottomRect:区域的右下角坐标;

  nWidthEllipse, nHeightEllipse:圆角的宽度和高度;

  (3)多边形区域生成函数:

   函数原形:HRGN CreatePolygonRgn(CONST POINT *lppt,int cPoints, int fnPolyFillMode);

   参数含义:

   Lppt:指向一个POINT类型的数组,该数组定义多边形顶点;

   CPoints:定义数组中顶点数;

   FnPolyFillMode:定义填充模式,可选值为ALTERNATE或WINDING。

  实现第二步:将返回的HRGN类型的区域值被设置窗口区域函数调用。

   设置窗口区域函数:

   函数原形:int SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw);

   参数说明:

   hWnd:指向所操作的窗口的句柄;

   hRgn:所给区域句柄;

   bRedraw:是否显示重画窗口的标志。

  在每一个函数的最后都需要调用SetWindowRgn函数,然后由Windows操作系统实现区域的各种形状的设置并显示。
 
不写一句代码,用D6简单实现不规则窗口(以下操作在Windows2000+D6下运行通过):
1.找一张图片(*.bmp,*.ico,*.jpg,*.Gif,...反正用TImage能打开就行了),图片中除了你想要留的部份外,
其它部分最好弄成黑色的(其它颜色也可以,只是为了操作方便而已)
2.在Form上放一Timage,设置Align := alClient,调入该图片,设置图片的一些属性,
如:AutoSize,Center,Transparent等
3.设置
Form1.BorderStyle := bsNone;
Form1.TransparentColorValue := clBlack;
Form1.TransparentColor := True;
4.按F9运行看看吧
 
var
rgn:HRGN;

rgn:=CreateEllipticRgn( 0,0,50,50);
SetWindowRgn(handle,rgn,true);
 
没有必要那么麻烦,为什么不利用现成的控件coolcontrol
在http://www.playicq.com下可以下载
 
太繁了,有现成的控件干吗不用!找一找extrapack
 
我写的一篇没有被发表的文章,也许对你有用。其中的makeregion函数可以根据一幅位图的轮廓形成一个不规则窗口
采用优化算法,速度很快。
===============================================================================
用delphi做一个会在桌面上跳舞的小猪
————兼谈不规则窗口的制作
dodo505
也许大家对office助手都有印象:一个小孙悟空或一个小狗不时地在桌面上耍来耍去,玩弄出各种姿态和花样,用鼠标单击它时还会弹出菜单选项与用户交互。那么它是怎么作出来的呢?本文便向大家介绍如何制作一个象office助手那样的会在桌面上跳舞的小猪。
编程思路:要做一个在桌面上跳舞的小猪,我们可以用位图拷贝函数BitBlt通过各种不同的掩膜组合向桌面上连续绘制不同的透明图片(图片如下图1)这样就会形成小猪在桌面上跳舞的动画。
图1(图片见附件)
但这样做有一个极大的缺点,那就是这样作成的小猪只顾自己跳舞无法与用户交互,也就是说无论我们用鼠标单击或双击小猪,它都没有任何反应,更不会弹出什么菜单选项了。那又该怎么办呢?最直接的解决办法就是使用不规则窗口,即先按照第一张小猪跳舞图片中小猪的轮廓形成一个不规则窗口(如图2),
图2
这时再把该图片放到该不规则窗口中时,则此窗口只显示出小猪来,其余部分自然是透明的(如图3)。
图3
依此类推再处理第二张,形成又一个不规则窗口,然后显示出来,再处理第三张......。如此不停地显示便形成了小猪在桌面上跳舞的动画。由于该动画本身就是一个窗口,所以可以响应各种窗口消息事件如双击、单击等等。
那么现在的关键问题就是如何根据一幅位图的轮廓形成一个不规则窗口,这就要用到几个windows的api函数:CreateRectRgn,CreateEllipticRgn,CombineRgn,SetWindowRgn。其中CreateRectRgn函数用来创建一个矩形区域,CreateEllipticRgn函数用来创建一个圆或椭圆形区域。SetWindowRgn函数用来设置窗口的形状,SetWindowRgn函数的定义如下:
int SetWindowRgn( HWND hWnd, HRGN hRgn, BOOL bRedrawflag);
窗口的形状由参数 hRgn 所标志的区域 (region) 决定。通过创建不同的区域就可以创建不同形状窗口。例如下面的代码,可以产生一个圆形的窗口。(如图4)
图4
var
R : HRgn;
begin
R := CreateEllipticRgn(0,0,300,300);
SetWindowRgn( handle,R , TRUE ) ;
end;

CombineRgn函数可以混合两个区域成为一个区域。其函数原形为
int CombineRgn(

HRGN hrgnDest, // 目标区域的句柄
HRGN hrgnSrc1, // 源区域1的句柄
HRGN hrgnSrc2, // 源区域2的句柄
int fnCombineMode // 两个区域混合的方式
);

比如下面代码混合三个圆形区域形成一个米老鼠形的区域。(如图5)
图5
var
R1,R2,R3 : HRgn;
begin
//分别创建三个圆形区域R1,R2,R3
R1 := CreateEllipticRgn(0,0,60,60);
R2 := CreateEllipticRgn(150,0,210,60);
R3 := CreateEllipticRgn(30,30,180,180);
//混合这三个圆形区域则形成一个米老鼠形区域
combinergn(R1,R1,R2,rgn_or);
combinergn(R1,R1,R3,rgn_or);
//将这个米老鼠形区域赋给本窗口,则形成一个米老鼠形窗口
SetWindowRgn( handle,R1 , TRUE ) ;
end;
由于窗口是米老鼠形状的所以在米老鼠形窗口里放置一个图片框,则图片框里的图片只会显示成米老鼠的形状。(如图6)
图6
有了上面的介绍我们就可以用CreateRectRgn函数和CombineRgn函数通过一种算法来根据一幅位图的轮廓形成一个不规则窗口了。具体方法如下:在窗口中放入一Image图片框,在图片框中加载一幅图片,我们采用一个两重循环,逐行扫描图片中不透明的区域,用CreateRectRgn函数得到一个个连续的不透明的小矩形区域,然后将这些小矩形区域用CombineRgn函数组成一个整个的区域便得到了这个图片轮廓的区域,即按照该图片的轮廓形成了一个不规则区域。再用SetWindowRgn函数将该区域赋给窗口便按照该图片的轮廓形成了一个不规则窗口。
知道了如何根据一幅图片的轮廓形成一个不规则窗口,那么利用不规则窗口连续显示不同的图片以形成动画,就可以制作出我们的在桌面上跳舞的小猪了。(制作出的画面如图7)。
图7
用这种方法制作出来的小猪可以响应我们的鼠标事件,比如本程序中我们用鼠标单击小猪则可以弹出一个弹出菜单,选其中的“退出”选项则可关闭该程序。由于本程序中采用的算法是一行一行地扫描而不是一个点一个点地扫描所以速度很快。
程序源代码如下:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs,StdCtrls, ExtCtrls, Menus;

type
TForm1 = class(TForm)
Image1: TImage;
Timer1: TTimer;
PopupMenu1: TPopupMenu;
N1: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
procedure creat(Sender: TObject);
procedure clicked(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure N1Click(Sender: TObject);
private
{ Private declarations }
a:integer;
mousepos:Tpoint;//存放鼠标指针位置
function makeregion(imagebox:Timage):hrgn;
//上面函数的作用是按照imagebox中的位图形状形成一个不规则区域
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}
function Tform1.makeregion(imagebox:Timage):hrgn;
//该函数的作用是按照imagebox中的位图形状形成一个不规则区域
var
lineregion,fullregion:hrgn;//定义区域
x,y,startlinex:integer;//存放位置坐标
transparentcolor:longword;//存放所指定的透明色
infirstregion,inlinea:boolean;
picwidth,picheight:integer; //图象的宽和高
hdc:hwnd;//图象框的句柄

begin
hdc:=imagebox.canvas.handle;//得到图象框的句柄
picwidth:=imagebox.width;//得到图象框的宽和高
picheight:=imagebox.height;
infirstregion:=true;
inlinea:=false;
startlinex:=0;
fullregion:=0;
transparentcolor:=getpixel(hdc,0,0);//指定透明色
//下面的两重循环逐行地扫描不透明色,将连续的不透明色形成一个个小的区域
//然后将这些小区域混合成一个大的不规则区域即位图中不透明区域的形状
//由于是一行行地扫描而不是一个点一个点地扫描所以速度快多了。
for y:=0 to picheight-1 do
begin
for x:=0 to picwidth-1 do
begin
if ((getpixel(hdc,x,y)=transparentcolor) or (x=picwidth)) then
begin
if (inlinea=true) then
begin
inlinea:=false;
//将连续的不透明色组成一个小的矩形区域
lineregion:=createrectrgn(startlinex,y,x,y+1);
if (infirstregion=true)then
begin
fullregion:=lineregion;
infirstregion:=false;
end
else
begin
//混合小的矩形区域到一个大区域,循环结束后,此大区域就是整个不规则窗口
combinergn(fullregion,fullregion,lineregion,rgn_or);
deleteobject(lineregion);
end;
end;
end
else
begin
if (inlinea=false)then
begin
inlinea:=true;
startlinex:=x;
end;
end;
end;
end;
result:= fullregion; //返回所形成的不规则区域
end;

procedure TForm1.creat(Sender: TObject);
begin
//窗体式样为无边框
form1.BorderStyle:=bsNone;
//初始化a
a:=0;
end;
procedure TForm1.clicked(Sender: TObject);
begin
//得到当前鼠标位置
getcursorpos(mousepos);
//弹出菜单
popupmenu1.Popup(mousepos.x,mousepos.y);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
aa:hrgn;//用于存储得到的区域
picture:string;//存储要显示的位图文件的文件名
begin
image1.AutoSize:=true;//按位图尺寸自动调整大小
a:=a+1;//每经过一个计时器事件,就换一幅位图
if a<8 then
begin
picture:='pig'+inttostr(a)+'.bmp' ;
image1.Picture.LoadFromFile(picture) ;
end
else
a:=0;
//按照image1中的位图形状形成一个不规则区域
aa:=makeregion(image1);
//将形成的不规则区域赋给本窗体以形成一个不规则窗体
setwindowrgn(handle,aa,true);
end;
procedure TForm1.N1Click(Sender: TObject);
begin
//单击窗体,在弹出的菜单中选“退出”时关闭本程序
application.Terminate;
end;

end.
以上程序在Delphi6,WindowsMe下调试通过。
==================================================================
 
后退
顶部