不规则窗口设计

本例效果图:

新建应用,添加一个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 函数。

 

 

转载于:https://www.cnblogs.com/keyvip/archive/2010/10/17/1853728.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值