当前位置: 首页 > news >正文

制作可点击的异形窗口(2)

一、带透明效果的异形窗体
首先,封装一个函数实现带alpha效果的异形窗体。

//根据传入的参数实现异形窗体
//Wnd: 窗体句柄
//Bmp: 窗体的图像,支持alpha像素
//Alpha: 透明度,在bmp的基础上再叠加一个透明度,0为全透,255为不叠加透明度
procedure AlphaUpdateLayeredWindow(Wnd: HWND; Bmp: TBitmap; Alpha: Byte);
var
Pt: TPoint;
R: TRect;
Sz: TSize;
BF: _BLENDFUNCTION;
begin
GetWindowRect(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);
var
png: TPngImage;
bmp: TBitmap;
begin
png := TPngImage.Create;
try
png.LoadFromFile(TPath.Combine(ExtractFilePath(Application.ExeName), ‘1.png’));
bmp := TBitmap.Create;
try
bmp.Assign(png);
AlphaUpdateLayeredWindow(Handle, bmp, 255);
finally
bmp.Free;
end;
finally
png.Free;
end;
end;
最后,添加鼠标响应,按下鼠标可以拖动它。

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
ReleaseCapture;
Perform(WM_SYSCOMMAND, $F012, 0);
end;
至此,一个简单的异形窗体就制作好,下面是运行时的录屏效果。
1
[运行效果,转gif后颜色会有损失]

二、增加动画
只是这个样子未免有点单调,让我们来加点动画效果,让事情变得更有趣。
在窗体上添加一个TTimer,每50ms触发一次事件。

procedure TForm1.Timer1Timer(Sender: TObject);
var
i: Integer;
begin
//每50ms重绘一次
bmp.Assign(png1);
//绘制两个光点到bmp,不断变换位置产生动画
for i := 1 to 2 do begin
bmp.Canvas.Draw(Points[i].X, Points[i].Y, png2);
UpdatePos(i);
end;
AlphaUpdateLayeredWindow(Handle, bmp, 255);
end;
bmp、Points、png等在FormCreate提取预设好,完整代码如下:

unit Unit1;

interface

uses
Winapi.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;

type
TForm1 = 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);
public
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

//根据传入的参数实现异形窗体
//Wnd: 窗体句柄
//Bmp: 窗体的图像,支持alpha像素
//Alpha: 透明度,在bmp的基础上再叠加一个透明度,0为全透,255为不叠加透明度
procedure AlphaUpdateLayeredWindow(Wnd: HWND; Bmp: TBitmap; Alpha: Byte);
var
Pt: TPoint;
R: TRect;
Sz: TSize;
BF: _BLENDFUNCTION;
begin
GetWindowRect(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);
begin
FillMemory(@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);
begin
if 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);
begin
ReleaseCapture;
Perform(WM_SYSCOMMAND, $F012, 0);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
i: Integer;
begin
//每50ms重绘一次
bmp.Assign(png1);
//绘制两个光点到bmp,不断变换位置产生动画
for i := 1 to 2 do begin
bmp.Canvas.Draw(Points[i].X, Points[i].Y, png2);
UpdatePos(i);
end;
AlphaUpdateLayeredWindow(Handle, bmp, 255);
end;

procedure TForm1.UpdatePos(index: integer);
begin
Inc(Points[index].X, 8);
Inc(Points[index].Y, 12);
if (Points[index].X > Width) or (Points[index].Y > Height) then begin
Points[index].X := Random(Width div 3) * 3;
Points[index].Y := -10;
end;
end;

end.
这是运行后的录屏:

2

http://www.jsqmd.com/news/1169955/

相关文章:

  • Java高并发底层原理(十六)—— CompletableFuture 如何编排多个异步任务
  • 插件自定义鉴权的架构跃迁
  • eNSP Pro 2024 云化版部署:3步完成在线实验预约,免本地安装
  • YOLO26涨点改进| TGRS 2026 | 特征融合改进篇 |引入CDSF跨域协同融合模块,增强特征互补性与语义一致性,助力高光谱目标检测、图像分割、遥感目标检测、多模态融合目标检测任务,高效涨点
  • 长征十号乙运载火箭预计年底前完成一子级火箭复用飞行
  • 为什么选择KASandbox?对比传统容器运行时接口的5大优势
  • 西安自助健身系统开发哪家靠谱,IoT门禁联动后端架构拆解
  • NAS使用方法
  • 遗留系统现代化 3 种路径对比:逆向工程、再工程与正向工程选型指南
  • UE5 UpdateOverlaps六大误用场景解析与最佳实践
  • 最短路径算法实战:Python实现Dijkstra与Floyd,处理1000节点图性能对比
  • 后台保活:Android前台服务与iOS后台模式配置(132)
  • 从《我的世界》AI测试场看多模态大模型的任务链能力缺陷
  • MiniMax M2.7 DPTR模块显存泄漏深度解析
  • ai生成语音2026年哪个免费工具好用-实测对比后给出靠谱答案
  • 团城山黄金回收靠谱推荐|30年本土老店,全域免费上门无套路变现 - 华金汇黄金回收
  • AI视频生成技术解析:Dreamina Seedance 2.5在CapCut平台的实践应用
  • PilotGo-plugin-syscare性能优化指南:大规模热补丁部署的最佳实践
  • 3步掌握ClearerVoice-Studio:AI语音清晰化解决方案
  • AtomGit Flutter 鸿蒙客户端:ModalBottomSheet 实战
  • DBPanel 1.0.0-rc.5 版本发布:新增多项功能,优化体验并增强稳定性
  • 118、超分模型的可解释性:可视化注意力图与特征图分析
  • 跑遍河源6家回收店,2026年黄金/数码/奢侈品变现怎么选才不踩坑 - 金奢汇
  • GPT-5.6 系列模型深度解析:性能评测与实测体验
  • 麒麟信安安全容器魔方架构深度解析:Controller、Agent与Registry三模块协同工作
  • 深耕河南教育创新,麒麟软件获评省级首批技术支持单位
  • 2026年短视频学习笔记工具实测对比:学习者怎么选,谁才是王者
  • Windows任务栏透明化神器:TranslucentTB的5种惊艳玩法
  • 操作系统分页存储实战:3种地址转换算法详解与10道真题精解
  • 二维码设备巡检管理系统开发