明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

DELPHI中使用API函數(shù)完成多態(tài)FORM

[摘要]陳學軍  實現(xiàn)異型FORM并不是一件難事,本文將向您介紹如何利用API函數(shù)實現(xiàn)圓角矩形和橢圓形FORM,并在此基礎之上探討實現(xiàn)TWINcontrol類的后裔的異型的實現(xiàn)。   欲改變FORM的形狀,也就是實現(xiàn)對區(qū)域(region)的控制。在Win32 API程序參考手冊有關區(qū)域(region)的定...
陳學軍

  實現(xiàn)異型FORM并不是一件難事,本文將向您介紹如何利用API函數(shù)實現(xiàn)圓角矩形和橢圓形FORM,并在此基礎之上探討實現(xiàn)TWINcontrol類的后裔的異型的實現(xiàn)。

  欲改變FORM的形狀,也就是實現(xiàn)對區(qū)域(region)的控制。在Win32 API程序參考手冊有關區(qū)域(region)的定義是這樣描述的:它可以是一個矩形,多邊形,橢圓形(或者是兩者的復合,或者是更多的形狀),這些都可以被填充,畫圖,翻轉,結構化并可以得到焦點執(zhí)行。

  由定義得出結論:區(qū)域(region)是可以被改變和操縱的,依據(jù)我們的需求可定義區(qū)域并制作出我們所要求的形狀。

  應當指出的是區(qū)域(region)也能對任何TWINcontrol類的后裔定義和控制(不僅僅是FORMS),就是說,可以將區(qū)域(region)的定義運用到向Tpanel或TEdit這樣的對象。在改變TWINcontrol類的后裔控件的形狀時,需要提供一句柄并創(chuàng)建一些改變形狀的函數(shù)。

  具體實現(xiàn)方式一般分為兩步:

  1.定義所需形狀的區(qū)域邊界形狀(比如:橢圓形)。

  2.將已定義的區(qū)域邊界形狀運用到窗口。

  這里,我們將通過調用Windows API函數(shù)完成以上兩個步驟,下面就具體函數(shù)的應用予以說明:

  實現(xiàn)第一步:定義區(qū)域邊界。

  在這里將調用三個WinAPI,這三個函數(shù)是:

  CreateEllipticRgn()功能是生成橢圓形區(qū)域;

  CreateRoundRectRgn()功能是生成圓角矩形區(qū)域;

  CreatePolygonRgn()功能是生成多邊形區(qū)域,Windows要確保使其頂點自動相連形成一封閉的區(qū)域。

  這三個函數(shù)通過返回的指針變量標識所生成的區(qū)域將被第二步所應用。這些函數(shù)在Delphi中的函數(shù)聲明及參數(shù)含義說明如下:

 。1)橢圓形區(qū)域生成函數(shù):

   函數(shù)原形:HRGN CreateEllipticRgn(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect);

   參數(shù)含義:

   nLeftRect,nTopRect:區(qū)域的左上角坐標;

   nRightRect, nBottomRect:區(qū)域的右下角坐標;

 。2)圓角矩形區(qū)域生成函數(shù):

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

   參數(shù)含義:

   nLeftRect, nTopRect:區(qū)域的左上角坐標;

   nRightRect, nBottomRect:區(qū)域的右下角坐標;

  nWidthEllipse, nHeightEllipse:圓角的寬度和高度;

 。3)多邊形區(qū)域生成函數(shù):

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

   參數(shù)含義:

   Lppt:指向一個POINT類型的數(shù)組,該數(shù)組定義多邊形頂點;

   CPoints:定義數(shù)組中頂點數(shù);

   FnPolyFillMode:定義填充模式,可選值為ALTERNATE或WINDING。

  實現(xiàn)第二步:將返回的HRGN類型的區(qū)域值被設置窗口區(qū)域函數(shù)調用。

   設置窗口區(qū)域函數(shù):

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

   參數(shù)說明:

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

   hRgn:所給區(qū)域句柄;

   bRedraw:是否顯示重畫窗口的標志。

  在每一個函數(shù)的最后都需要調用SetWindowRgn函數(shù),然后由Windows操作系統(tǒng)實現(xiàn)區(qū)域的各種形狀的設置并顯示。

  以下將測試的FORM的整個源代碼列出,在FORM上添加了四個按鈕分別控制實現(xiàn):橢圓形,圓角矩形,等邊多邊形和星形;一個Tpanel控件為了演示TWINcontrol類的后裔的區(qū)域定義和控制;一個SpinEdit控件定義多邊形和星形的頂點連接數(shù)目。

  源程序:

  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;       //得到每個頂點的度數(shù)

   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環(huán)境下調試成功,可以直接引用。