本例效果图:
新建应用,添加一个PopupMenu和一个Image,代码如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Menus;
type
TForm1 = class(TForm)
Image1: TImage;
PopupMenu1: TPopupMenu;
N1: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
N4: TMenuItem;
N5: TMenuItem;
N6: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure N1Click(Sender: TObject);
procedure N2Click(Sender: TObject);
procedure N3Click(Sender: TObject);
procedure N4Click(Sender: TObject);
procedure N5Click(Sender: TObject);
procedure N6Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);//窗口初始化
begin
Image1.Align:=alClient;
BorderStyle:=bsNone;
PopupMenu:=PopupMenu1;
end;
procedure TForm1.N1Click(Sender: TObject);//绘制圆形窗口
var
r1:HRGN;
begin
r1:=CreateEllipticRgn(0,0,300,300);
SetWindowRgn(Handle,r1,True);
end;
procedure TForm1.N2Click(Sender: TObject);//绘制环形窗口
var
r1,r2:HRGN;
begin
r1:=CreateEllipticRgn(1,-1,Width-1,Height);
r2:=CreateEllipticRgn(50,50,Width-15,Height-50);
CombineRgn(r2,r1,r2,RGN_XOR);//通过组合两个已有的区域来创建一个新的GDI区域
SetWindowRgn(Handle,r2,True);
end;
procedure TForm1.N3Click(Sender: TObject);//绘制矩形窗口
var
r1:HRGN;
begin
r1:=CreateRectRgn(0,0,Width,Height);
SetWindowRgn(Handle,r1,True);
end;
procedure TForm1.N4Click(Sender: TObject);//绘制圆角矩形窗口
var
r1:HRGN;
begin
r1:=CreateEllipticRgn(-15,-15,Width+15,Height+15);
SetWindowRgn(Handle,r1,True);
end;
procedure TForm1.N5Click(Sender: TObject);//绘制椭圆形窗口
var
r1:HRGN;
begin
r1:=CreateRoundRectRgn(0,0,400,300,600,300);
SetWindowRgn(Handle,r1,True);
end;
procedure TForm1.N6Click(Sender: TObject);//退出
begin
Close;
end;
end.
在编写这个例程(例子程序)的过程中,我明白了不少东西,首先要说的就是几个创建区域的函数,如CreateEllipticRgn,CreateRectRgn..等等这些函数,这些创建区域函数其实还有不少,在这我就不一一列举了,还有不规则窗口设计的原理(通过定制区域函数定制出一个区域,然后用SetWindowRgn(设置窗口区域的函数)来实现不规则窗口),我发现这些函数都有一个特点,就是每个函数名中都有‘Rgn’的字样,为此我上网搜索,但都没明白RGN到底是什么,后来我遇到一个单词‘Region’,这单词词义是‘区域’,到此我明白RGN是什么东西了,呵呵,还是英文不好的原故.....下面我列出本文用到的函数的在C中的原型以作参考:
CRgn::CreateEllipticRgn
BOOL CreateEllipticRgn( int x1, int y1, int x2, int y2 );
返回值:如果操作成功则返回非零值;否则返回0。
参数:
// x1 指定椭圆的边界矩形的左上角的逻辑x坐标。
// y1 指定椭圆的边界矩形的左上角的逻辑y坐标。
// x2 指定椭圆的边界矩形的右下角的逻辑x坐标。
// y2 指定椭圆的边界矩形的右下角的逻辑y坐标。
说明:
此成员函数用来创建一个椭圆形区域。该区域由用x1,y1,x2,和y2指定的边界矩形来定义。该区域保存在CRgn对象中。
区域的大小被限制在32767×32767个逻辑单位和64K内存这两个值中较小的那个值的范围内。
当使用完了由CreateEllipticRgn函数创建的区域时,应用程序应该将此区域选择出设备环境外,并用DeleteObject函数来删除它。
CRgn::CreateRectRgn
BOOL CreateRectRgn( int x1, int y1, int x2, int y2 );
返回值:如果操作成功则返回非零值;否则返回0。
参数:
// x1 指定区域的左上角的逻辑x坐标。
// y1 指定区域左上角的逻辑y坐标。
// x2 指定区域右下角的逻辑x坐标。
// y2 指定区域的右下角的逻辑y坐标。
说明:
此成员函数用来创建一个矩形区域,该区域被保存在CRgn对象中。
区域的大小被限制在32767×32767个逻辑单位和64K内存这两个值中较小的那个值的范围内。
当使用完了由CreateRectRgn函数创建的区域时,应用程序应该将此区域选择出设备环境外,并用CGDIObject::DeleteObject函数来删除它。
CRgn::CreateRoundRectRgn
BOOL CreateRoundRectRgn( int x1, int y1, int x2, int y2, int x3, int y3 );
返回值:如果操作成功则返回非零值;否则返回0。
参数:
// x1 指定区域的左上角的逻辑x坐标。
// y1 指定区域左上角的逻辑y坐标。
// x2 指定区域右下角的逻辑x坐标。
// y2 指定区域的右下角的逻辑y坐标。
// x3 指定用来创建圆角的椭圆的宽度。
// y3 指定用来创建圆角的椭圆的高度。
说明:
此成员函数用来创建一个具有圆角的矩形区域。
区域的大小被限制在32767×32767个逻辑单位和64K内存这两个值中较小的那个值的范围内。
当使用完了由CreateRoundRectRgn函数创建的区域时,应用程序应该将此区域选择出设备环境外,并用CGDIObject::DeleteObject函数来删除它。
CRgn::CombineRgn
int CombineRgn( CRgn* pRgn1, CRgn* pRgn2, int nCombineMode );
返回值:
返回最后结果区域的类型。它可以是下列值之一:
// COMPLEXREGION 新区域具有相互重叠的边界。
// ERROR 未创建新区域。
// NULLREGION 新区域为空。
// SIMPLEREGION 新区域没有相互重叠的边界。
参数: pRgn1 表示一个已经存在的区域。
pRgn2 表示一个已经存在的区域。
nCombineMode 指定当组合两个源区域时要执行的操作。它可以是下列值之一: · RGN_AND 使用两个区域互相重叠的区域(相交区域)。
// RGN_COPY 创建区域1(由pRgn1标识)的一个拷贝
// RGN_DIEF 创建一个区域,该区域由区域1(由pRgn1标识)的不是区域2(由pRgn2标识)的那一部分区域组成。
// RGN_OR 组合两个区域的整个部分(两个区域的并)。
// RGN_XOR 组合两个区域,但去掉相互重叠的区域。
说明:
此成员函数通过组合两个已有的区域来创建一个新的GDI区域。所组合成的区域就像nCombineMode所指定的一样。
两个指定的区域被组合,所得到的结果区域的句柄被保存在CRgn对象中。因此,不管CRgn中原来保存的区域是什么,都将被合并后的区域所代替。
区域的大小被限制在32767×32767个逻辑单位和64K内存这两个值中较小的那个值的范围内。
使用CopyRgn只是简单地将一个区域拷贝到另一个区域。
int SetWindowRgn;(HWND hWnd, HRGN hRgn, BOOL bRedraw)
参数
hWnd
// 将被设定窗口区域的某一窗口的柄。
hRgn
// 窗口区域的句柄。 函数将窗户的窗户区域设定为这一个区域。如果 hRgn 是无效力的,函数将窗口区域设定为零。
bRedraw
// 叙述系统是否在设定窗户区域之后重划窗口。如果 bRedraw 是真实的,系统这么做; 另外,它不。 典型地, 你设定 bRedraw 到真实的如果窗口是看得见的。
返回值
// 如果函数调用成功,回返价值是非零。如果函数调用失败,回返价值是零。windows NT/2000/XP: 得到广大的错误数据,呼叫 GetLastError 。
说明
// 当这调用被呼叫的时候,系统把给窗口的讯息送给 WM_WINDOWPOSCHANGING 和WM_WINDOWPOSCHANGED 。一个窗户的窗口区域的坐标相对于窗口的上面-左边角落而不是窗口的客户区域。
在一个成功的呼叫之后,对 SetWindowRgn ,系统拥有被区域柄 hRgn 指定的区域。 系统不作区域的副本。 因此,你不应该用这一个区域柄来做任何的较进一步的功能呼叫。 尤其,不要删除这一个区域句柄。 当它不再需要的时候,系统划除这一区域句柄。
为了要获得窗口的窗口区域,呼叫 GetWindowRgn 函数。