制作可点击的异形窗口(2)
一、带透明效果的异形窗体首先封装一个函数实现带alpha效果的异形窗体。//根据传入的参数实现异形窗体//Wnd: 窗体句柄//Bmp: 窗体的图像支持alpha像素//Alpha: 透明度在bmp的基础上再叠加一个透明度0为全透255为不叠加透明度procedure AlphaUpdateLayeredWindow(Wnd: HWND; Bmp: TBitmap; Alpha: Byte);varPt: TPoint;R: TRect;Sz: TSize;BF: _BLENDFUNCTION;beginGetWindowRect(Wnd, R);Pt : Point(0, 0);Sz.cx : Bmp.Width;Sz.cY : Bmp.Height;bf.BlendOp : AC_SRC_OVER;bf.BlendFlags : 0;bf.SourceConstantAlpha : Alpha;bf.AlphaFormat : AC_SRC_ALPHA;SetWindowLong(wnd, GWL_EXSTYLE, GetWindowLong(wnd, GWL_EXSTYLE) or WS_EX_LAYERED);UpdateLayeredWindow(wnd, 0, R.TopLeft, Sz, Bmp.Canvas.Handle, Pt, 0, BF, ULW_ALPHA);end;接着在窗体的FormCreate事件中载入图片素材根据图片建立异形窗体。procedure TForm1.FormCreate(Sender: TObject);varpng: TPngImage;bmp: TBitmap;beginpng : TPngImage.Create;trypng.LoadFromFile(TPath.Combine(ExtractFilePath(Application.ExeName), ‘1.png’));bmp : TBitmap.Create;trybmp.Assign(png);AlphaUpdateLayeredWindow(Handle, bmp, 255);finallybmp.Free;end;finallypng.Free;end;end;最后添加鼠标响应按下鼠标可以拖动它。procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);beginReleaseCapture;Perform(WM_SYSCOMMAND, $F012, 0);end;至此一个简单的异形窗体就制作好下面是运行时的录屏效果。1[运行效果转gif后颜色会有损失]二、增加动画只是这个样子未免有点单调让我们来加点动画效果让事情变得更有趣。在窗体上添加一个TTimer每50ms触发一次事件。procedure TForm1.Timer1Timer(Sender: TObject);vari: Integer;begin//每50ms重绘一次bmp.Assign(png1);//绘制两个光点到bmp不断变换位置产生动画for i : 1 to 2 do beginbmp.Canvas.Draw(Points[i].X, Points[i].Y, png2);UpdatePos(i);end;AlphaUpdateLayeredWindow(Handle, bmp, 255);end;bmp、Points、png等在FormCreate提取预设好完整代码如下unit Unit1;interfaceusesWinapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Imaging.pngimage,Vcl.ExtCtrls, Vcl.ComCtrls, IOUtils;typeTForm1 class(TForm)Timer1: TTimer;procedure FormMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);procedure FormCreate(Sender: TObject);procedure FormDestroy(Sender: TObject);procedure Timer1Timer(Sender: TObject);private//光点的绘制位置Points: array[1…2] of TPoint;//预载入Png图片png1, Png2: TPngImage;bmp: TBitmap;procedure UpdatePos(index: integer);publicend;varForm1: TForm1;implementation{$R *.dfm}//根据传入的参数实现异形窗体//Wnd: 窗体句柄//Bmp: 窗体的图像支持alpha像素//Alpha: 透明度在bmp的基础上再叠加一个透明度0为全透255为不叠加透明度procedure AlphaUpdateLayeredWindow(Wnd: HWND; Bmp: TBitmap; Alpha: Byte);varPt: TPoint;R: TRect;Sz: TSize;BF: _BLENDFUNCTION;beginGetWindowRect(Wnd, R);Pt : Point(0, 0);Sz.cx : Bmp.Width;Sz.cY : Bmp.Height;bf.BlendOp : AC_SRC_OVER;bf.BlendFlags : 0;bf.SourceConstantAlpha : Alpha;bf.AlphaFormat : AC_SRC_ALPHA;SetWindowLong(wnd, GWL_EXSTYLE, GetWindowLong(wnd, GWL_EXSTYLE) or WS_EX_LAYERED);UpdateLayeredWindow(wnd, 0, R.TopLeft, Sz, Bmp.Canvas.Handle, Pt, 0, BF, ULW_ALPHA);end;procedure TForm1.FormCreate(Sender: TObject);beginFillMemory(Points, Sizeof(Points), 0);Points[1].X : Random(Width div 2) * 2;//载入两个Png图片png1 : TPngImage.Create;png1.LoadFromFile(TPath.Combine(ExtractFilePath(Application.ExeName), ‘1.png’));png2 : TPngImage.Create;png2.LoadFromFile(TPath.Combine(ExtractFilePath(Application.ExeName), ‘2.png’));bmp : TBitmap.Create;end;procedure TForm1.FormDestroy(Sender: TObject);beginif Assigned(png1) then png1.Free;if Assigned(png2) then png2.Free;if Assigned(bmp) then bmp.Free;end;procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);beginReleaseCapture;Perform(WM_SYSCOMMAND, $F012, 0);end;procedure TForm1.Timer1Timer(Sender: TObject);vari: Integer;begin//每50ms重绘一次bmp.Assign(png1);//绘制两个光点到bmp不断变换位置产生动画for i : 1 to 2 do beginbmp.Canvas.Draw(Points[i].X, Points[i].Y, png2);UpdatePos(i);end;AlphaUpdateLayeredWindow(Handle, bmp, 255);end;procedure TForm1.UpdatePos(index: integer);beginInc(Points[index].X, 8);Inc(Points[index].Y, 12);if (Points[index].X Width) or (Points[index].Y Height) then beginPoints[index].X : Random(Width div 3) * 3;Points[index].Y : -10;end;end;end.这是运行后的录屏2