實現異型FORM並不是一件難事,本文將向您介紹如何利用API函數實現圓角矩 形和橢圓形FORM,並在此基礎之上探討實現TWINcontrol類的後裔的異型的實現 。
欲改變FORM的形狀,也就是實現對區域(region)的控制。在Win32 API程序 參考手冊有關區域(region)的定義是這樣描述的:它可以是一個矩形,多邊形 ,橢圓形(或者是兩者的復合,或者是更多的形狀),這些都可以被填充,畫圖 ,翻轉,結構化並可以得到焦點執行。
由定義得出結論:區域(region)是可以被改變和操縱的,依據我們的需求 可定義區域並制作出我們所要求的形狀。
應當指出的是區域(region)也能對任何TWINcontrol類的後裔定義和控制( 不僅僅是FORMS),就是說,可以將區域(region)的定義運用到向Tpanel或 TEdit這樣的對象。在改變TWINcontrol類的後裔控件的形狀時,需要提供一句柄 並創建一些改變形狀的函數。
具體實現方式一般分為兩步:
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操作系統 實現區域的各種形狀的設置並顯示。
以下將測試的FORM的整個源代碼列出,在FORM上添加了四個按鈕分別控制實 現:橢圓形,圓角矩形,等邊多邊形和星形;一個Tpanel控件為了演示 TWINcontrol類的後裔的區域定義和控制;一個SpinEdit控件定義多邊形和星形 的頂點連接數目。
源程序:
unit form_statue;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, Spin;
type
TForm1 = class(TForm)
Button1: TButton;
SpinEdit1: TSpinEdit;
Panel1: TPanel;
Button2: TButton;
Button3: TButton;
Button4: TButton;
procedure DrawRndRectRegion(wnd : HWND; rect : TRect);
procedure DrawEllipticRegion(wnd : HWND; rect : TRect);
procedure DrawPolygonRegion(wnd : HWND; rect : TRect; NumPoints : Integer; DoStarShape : Boolean);
procedure Button1Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
rgn : HRGN;
rect : TRect;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.DrawRndRectRegion(wnd : HWND; rect : TRect);
begin
rgn := CreateRoundRectRgn(rect.left, rect.top, rect.right, rect.bottom, 30, 30);
SetWindowRgn(wnd, rgn, TRUE);
end;
procedure TForm1.DrawEllipticRegion(wnd : HWND; rect : TRect);
begin
rgn := CreateEllipticRgn(rect.left, rect.top, rect.right, rect.bottom);
SetWindowRgn(wnd, rgn, TRUE);
end;
procedure TForm1.DrawPolygonRegion(wnd : HWND; rect : TRect; NumPoints : Integer; DoStarShape : Boolean);
const
RadConvert = PI/180;
Degrees = 360;
MaxLines = 100;
var
x, y,
xCenter,
yCenter,
radius,
pts,
I : Integer;
angle,
rotation: Extended;
arPts : Array[0..MaxLines] of TPoint;
begin
xCenter := (rect.Right - rect.Left) div 2;
yCenter := (rect.Bottom - rect.Top) div 2;
if DoStarShape then
begin
rotation := Degrees/(2*NumPoints);
pts := 2 * NumPoints;
end
else
begin
rotation := Degrees/NumPoints; //得到每個頂點的度數
pts := NumPoints ;
end;
radius := yCenter;
for I := 0 to pts - 1 do begin
if DoStarShape then
if (I mod 2) = 0 then
radius := Round(radius/2)
else
radius := yCenter;
angle := ((I * rotation) + 90) * RadConvert;
x := xCenter + Round(cos(angle) * radius);
y := yCenter - Round(sin(angle) * radius);
arPts[I].X := x;
arPts[I].Y := y;
end;
rgn := CreatePolygonRgn(arPts, pts, WINDING);
SetWindowRgn(wnd, rgn, TRUE);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DrawRndRectRegion(Form1.Handle, Form1.ClientRect);
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
DrawPolygonRegion(Panel1.Handle, Panel1.BoundsRect, SpinEdit1.Value, True);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
DrawEllipticRegion(Form1.Handle, Form1.ClientRect);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
DrawPolygonRegion(Panel1.Handle, Panel1.BoundsRect, SpinEdit1.Value, False);
end;
end.
源程序在PWIN98+DELPHI5環境下調試成功,可以直接引用。