1. 程式人生 > >一個最簡單的Delphi2010的PNG異形視窗方法

一個最簡單的Delphi2010的PNG異形視窗方法

同事演示了一個.NET的的PNG異形視窗.挺漂亮.於是也想用Delphi顯擺一個.

關於Delphi用PNG做異形視窗的資料有不少.都是用GDIPlus或者TPNGImage元件載入PNG影象做的.但是我很懶,不想引用的GDIPlus,也不想去找PNGImage下載.

好在從Delphi2009開始Delphi中就收購了PNGImage,並整合到後繼的版本中.Delphi2010又包裝了微軟的IWICImagingFactory介面,這樣處理PNG的工作就交給作業系統去做了.

函式很簡單一共就幾行,關鍵就是UpdateLayeredWindow.

發現CodeGear真讓我上火.他們收工了PNGImage以後搞的東西居然改出了問題.透明盒漸變都有問題.做異形視窗該漸變部分居然是透明的.該透明的部分居然是不透明的.看了一下被收購前的PNGImage一點問題都沒有.CodeGear真實的.

只好用Delphi2010提供的IWICImagingFactory介面的包裝了,這次PNG的處理交給微軟的作業系統了,一點問題也沒有.其他版本的Delphi只要能對IWICImagingFactory進行包裝,也一樣能處理.但還是Delphi2010最方便.什麼控制元件也不用,多餘的東西都不要.

程式碼如下,很簡單吧:)

{*******************************************************}
{                                                       }
{       異形視窗                                        }
{                                                       }
{       2009.12.4 王  銳                                }
{                                                       }
{*******************************************************}


unit UnitYXForm;

interface
uses
  Windows, Forms, Classes, Graphics;

//從檔案載入PNG
procedure YXForm_FromFile(AForm : TForm; AFileName : String);
//從資源載入PNG
procedure YXForm_FromResource(AForm : TForm; ResName : String; ResType : PWideChar; Instance : HINST = 0);
//從影象物件載入
procedure YXForm_FromGraphic(AForm : TForm; AGraphic : TGraphic);

implementation

procedure YXForm_FromFile(AForm : TForm; AFileName : String);
var
  wic : TWICImage;
begin
  wic := TWICImage.Create;
  wic.LoadFromFile(AFileName);
  YXForm_FromGraphic(AForm, wic);
  wic.Free;
end;

procedure YXForm_FromResource(AForm : TForm; ResName : String;ResType : PWideChar; Instance : HINST);
var
  wic : TWICImage;
  r : TResourceStream;
begin
  if Instance = 0 then
    Instance := HInstance;
  r := TResourceStream.Create(Instance, ResName, ResType);
  wic := TWICImage.Create;
  wic.LoadFromStream(r);

  YXForm_FromGraphic(AForm, wic);
  wic.Free;
  r.Free;
end;

procedure YXForm_FromGraphic(AForm : TForm; AGraphic : TGraphic);
var
  ptDst, ptSrc: TPoint;
  Size: TSize;
  BlendFunction: TBlendFunction;
  bmp : TBitmap;
begin
  bmp := TBitmap.Create;
  bmp.Assign(AGraphic);
  ptDst := Point(AForm.Left, AForm.Top);
  ptSrc := Point(0, 0);
  Size.cx := AGraphic.Width;
  Size.cy := AGraphic.Height;

  BlendFunction.BlendOp := AC_SRC_OVER;
  BlendFunction.BlendFlags := 0;
  BlendFunction.SourceConstantAlpha := $FF; // 透明度
  BlendFunction.AlphaFormat := AC_SRC_ALPHA;

  SetWindowLong(AForm.Handle, GWL_EXSTYLE, GetWindowLong(AForm.Handle,
      GWL_EXSTYLE) or WS_EX_LAYERED);
  UpdateLayeredWindow(AForm.Handle,
     AForm.Canvas.Handle,
     @ptDst,
     @Size,
     bmp.Canvas.Handle,
     @ptSrc,
     0,
     @BlendFunction,
     ULW_ALPHA);
  bmp.Free();
end;

end.

想要用的時候很簡單,舉個例子:

  ff := TForm2.Create(Self);
  YXForm_FromFile(ff, 'c:/a.png');

  ff.Show;

實現動畫也很容易.只要不停地YXForm_FromFile(ff, 'c:/a.png');呼叫一套動作PNG就可以了.

效果如下: