CnWaterImage.pas 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. {******************************************************************************}
  2. { CnPack For Delphi/C++Builder }
  3. { 中国人自己的开放源码第三方开发包 }
  4. { (C)Copyright 2001-2018 CnPack 开发组 }
  5. { ------------------------------------ }
  6. { }
  7. { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
  8. { 改和重新发布这一程序。 }
  9. { }
  10. { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
  11. { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
  12. { }
  13. { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
  14. { 还没有,可访问我们的网站: }
  15. { }
  16. { 网站地址:http://www.cnpack.org }
  17. { 电子邮件:master@cnpack.org }
  18. { }
  19. {******************************************************************************}
  20. unit CnWaterImage;
  21. {* |<PRE>
  22. ================================================================================
  23. * 软件名称:界面控件包
  24. * 单元名称:水波效果图像控件
  25. * 单元作者:周劲羽 (zjy@cnpack.org)
  26. * 备 注:
  27. * 开发平台:PWinXP SP2 + Delphi 5.01
  28. * 兼容测试:
  29. * 本 地 化:该单元中的字符串均符合本地化处理方式
  30. * 单元标识:$Id$
  31. * 修改记录:2008.11.17 V1.1
  32. * 笑三少增加控制水滴初始半径与荡漾快慢的两个属性
  33. * 2005.11.22 V1.0
  34. * 创建控件
  35. ================================================================================
  36. |</PRE>}
  37. interface
  38. {$I CnPack.inc}
  39. uses
  40. Windows, Messages, SysUtils, Classes, Graphics, Controls, ExtCtrls,
  41. Math, CnWaterEffect;
  42. const
  43. csDefRandomDelay = 800;
  44. csDefRandomBlob = 500;
  45. csDefTrackBlob = 100;
  46. csDefClickBlob = 250;
  47. csDefRadius = 1;
  48. csDefInterval = 50;
  49. type
  50. { TCnWaterImage }
  51. TCnRenderEvent = procedure (Sender: TObject; ABitmap: TBitmap) of object;
  52. TCnWaterImage = class(TGraphicControl)
  53. {* 水波效果图像控件 }
  54. private
  55. FPicture: TPicture;
  56. FTimer: TTimer;
  57. FSrcBmp: TBitmap;
  58. FDstBmp: TBitmap;
  59. FWater: TCnWaterEffect;
  60. FDrawing: Boolean;
  61. FRadius : Integer;
  62. FRandomDelay: Integer;
  63. FTrackBlob: Integer;
  64. FClickBlob: Integer;
  65. FRandomBlob: Integer;
  66. FOnAfterRender: TCnRenderEvent;
  67. FOnBeforeRender: TCnRenderEvent;
  68. procedure PictureChanged(Sender: TObject);
  69. procedure SetPicture(Value: TPicture);
  70. procedure UpdateWaterData;
  71. procedure OnTimer(Sender: TObject);
  72. function GetCanvas: TCanvas;
  73. function GetDamping: TWaterDamping;
  74. procedure SetDamping(const Value: TWaterDamping);
  75. function GetInterval: Cardinal;
  76. procedure SetInterval(Value: Cardinal);
  77. protected
  78. function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override;
  79. procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  80. X, Y: Integer); override;
  81. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  82. procedure Loaded; override;
  83. procedure Resize; override;
  84. procedure Paint; override;
  85. public
  86. constructor Create(AOwner: TComponent); override;
  87. destructor Destroy; override;
  88. procedure ClearWater;
  89. {* 清空画面上的水滴效果 }
  90. procedure Blob(x, y: Integer; ARadius, AHeight: Integer);
  91. {* 在画面上产生一个水滴效果。x, y 为坐标,如果为 -1 表示随机点。ARadius 和
  92. AHeight 为初始半径和效果幅度 }
  93. property Canvas: TCanvas read GetCanvas;
  94. {* 画布属性,只在 OnBeforeRender 事件中有用 }
  95. published
  96. property Align;
  97. property Anchors;
  98. property AutoSize;
  99. property ClickBlob: Integer read FClickBlob write FClickBlob default csDefClickBlob;
  100. {* 点击画面时产生的水滴效果幅度,0 表示禁用 }
  101. property Constraints;
  102. property Damping: TWaterDamping read GetDamping write SetDamping default csDefDamping;
  103. {* 水滴阻尼系数 }
  104. property DragCursor;
  105. property DragKind;
  106. property DragMode;
  107. property Enabled;
  108. property Radius : Integer read FRadius write FRadius default csDefRadius;
  109. {* 水波初始半径,默认为 1 }
  110. property Interval : Cardinal read GetInterval write SetInterval default csDefInterval;
  111. {* 波纹荡漾快慢的间隔时间,单位毫秒,默认 50 }
  112. property ParentShowHint;
  113. property Picture: TPicture read FPicture write SetPicture;
  114. {* 背景图像 }
  115. property PopupMenu;
  116. property RandomBlob: Integer read FRandomBlob write FRandomBlob default csDefRandomBlob;
  117. {* 随机产生的水滴最大幅度,0 表示禁用 }
  118. property RandomDelay: Integer read FRandomDelay write FRandomDelay default csDefRandomDelay;
  119. {* 随机产生水滴的延时 }
  120. property ShowHint;
  121. property TrackBlob: Integer read FTrackBlob write FTrackBlob default csDefTrackBlob;
  122. {* 鼠标移动轨迹下水滴的幅度,0 表示禁用 }
  123. property Visible;
  124. property OnAfterRender: TCnRenderEvent read FOnAfterRender write FOnAfterRender;
  125. {* 画面绘制后事件 }
  126. property OnBeforeRender: TCnRenderEvent read FOnBeforeRender write FOnBeforeRender;
  127. {* 画面绘制前事件 }
  128. property OnClick;
  129. property OnContextPopup;
  130. property OnDblClick;
  131. property OnDragDrop;
  132. property OnDragOver;
  133. property OnEndDock;
  134. property OnEndDrag;
  135. property OnMouseDown;
  136. property OnMouseMove;
  137. property OnMouseUp;
  138. property OnStartDock;
  139. property OnStartDrag;
  140. end;
  141. implementation
  142. { TCnWaterImage }
  143. constructor TCnWaterImage.Create(AOwner: TComponent);
  144. begin
  145. inherited Create(AOwner);
  146. ControlStyle := ControlStyle + [csReplicatable, csOpaque];
  147. FPicture := TPicture.Create;
  148. FPicture.OnChange := PictureChanged;
  149. FTimer := TTimer.Create(Self);
  150. FTimer.Interval := csDefInterval;
  151. FTimer.OnTimer := OnTimer;
  152. FTimer.Enabled := True;
  153. FSrcBmp := TBitmap.Create;
  154. FDstBmp := TBitmap.Create;
  155. FWater := TCnWaterEffect.Create;
  156. FRandomDelay := csDefRandomDelay;
  157. FRandomBlob := csDefRandomBlob;
  158. FTrackBlob := csDefTrackBlob;
  159. FClickBlob := csDefClickBlob;
  160. Height := 105;
  161. Width := 105;
  162. end;
  163. destructor TCnWaterImage.Destroy;
  164. begin
  165. FPicture.Free;
  166. FTimer.Free;
  167. FSrcBmp.Free;
  168. FDstBmp.Free;
  169. FWater.Free;
  170. inherited Destroy;
  171. end;
  172. procedure TCnWaterImage.Paint;
  173. var
  174. Save: Boolean;
  175. begin
  176. Canvas.Lock;
  177. if csDesigning in ComponentState then
  178. with inherited Canvas do
  179. begin
  180. Pen.Style := psDash;
  181. Brush.Style := bsClear;
  182. Rectangle(0, 0, Width, Height);
  183. end;
  184. Save := FDrawing;
  185. FDrawing := True;
  186. try
  187. if Picture.Graphic <> nil then
  188. with inherited Canvas do
  189. Draw(0, 0, FDstBmp);
  190. finally
  191. Canvas.UnLock;
  192. FDrawing := Save;
  193. end;
  194. end;
  195. function TCnWaterImage.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean;
  196. begin
  197. Result := True;
  198. if not (csDesigning in ComponentState) or (Picture.Width > 0) and
  199. (Picture.Height > 0) then
  200. begin
  201. if Align in [alNone, alLeft, alRight] then
  202. NewWidth := Picture.Width;
  203. if Align in [alNone, alTop, alBottom] then
  204. NewHeight := Picture.Height;
  205. end;
  206. end;
  207. procedure TCnWaterImage.Resize;
  208. begin
  209. UpdateWaterData;
  210. inherited;
  211. end;
  212. procedure TCnWaterImage.UpdateWaterData;
  213. begin
  214. if [csLoading, csDestroying] * ComponentState = [] then
  215. begin
  216. FDstBmp.Canvas.Lock;
  217. FSrcBmp.Canvas.lock;
  218. FSrcBmp.Width := Width;
  219. FSrcBmp.Height := Height;
  220. FSrcBmp.PixelFormat := pf24bit;
  221. FDstBmp.Width := Width;
  222. FDstBmp.Height := Height;
  223. FDstBmp.PixelFormat := pf24bit;
  224. FWater.SetSize(Width, Height);
  225. if Picture.Graphic <> nil then
  226. begin
  227. FSrcBmp.Canvas.StretchDraw(ClientRect, Picture.Graphic);
  228. FDstBmp.Assign(FSrcBmp);
  229. end;
  230. FDstBmp.Canvas.UnLock;
  231. FSrcBmp.Canvas.Unlock;
  232. end;
  233. end;
  234. procedure TCnWaterImage.MouseMove(Shift: TShiftState; X, Y: Integer);
  235. begin
  236. inherited;
  237. if PtInRect(Rect(0, 0, Width, Height), Point(X, Y)) then
  238. begin
  239. if ssLeft in Shift then
  240. Blob(X, Y, FRadius, FClickBlob)
  241. else
  242. Blob(X, Y, FRadius, FTrackBlob);
  243. end;
  244. end;
  245. procedure TCnWaterImage.MouseDown(Button: TMouseButton; Shift: TShiftState;
  246. X, Y: Integer);
  247. begin
  248. inherited;
  249. if Button = mbLeft then
  250. Blob(X, Y, FRadius, FClickBlob);
  251. end;
  252. procedure TCnWaterImage.PictureChanged(Sender: TObject);
  253. begin
  254. if AutoSize and (Picture.Width > 0) and (Picture.Height > 0) then
  255. SetBounds(Left, Top, Picture.Width, Picture.Height);
  256. UpdateWaterData;
  257. if not FDrawing then Invalidate;
  258. end;
  259. procedure TCnWaterImage.OnTimer(Sender: TObject);
  260. var
  261. Bmp: TBitmap;
  262. begin
  263. if Enabled and (Picture.Graphic <> nil) then
  264. begin
  265. if (FRandomDelay > 0) and (FRandomBlob > 0) then
  266. begin
  267. if Random(Ceil(FRandomDelay / Integer(FTimer.Interval)) + 1) = 0 then
  268. Blob(-1, -1, Random(2) + 1, Random(FRandomBlob) + 100);
  269. end;
  270. if Assigned(FOnBeforeRender) then
  271. begin
  272. Bmp := TBitmap.Create;
  273. try
  274. Bmp.Assign(FSrcBmp);
  275. FOnBeforeRender(Self, Bmp);
  276. FWater.Render(Bmp, FDstBmp);
  277. finally
  278. Bmp.Free;
  279. end;
  280. end
  281. else
  282. FWater.Render(FSrcBmp, FDstBmp);
  283. if Assigned(FOnAfterRender) then
  284. FOnAfterRender(Self, FDstBmp);
  285. Invalidate;
  286. end;
  287. end;
  288. procedure TCnWaterImage.Blob(x, y, ARadius, AHeight: Integer);
  289. begin
  290. FWater.Blob(x, y, ARadius, AHeight);
  291. end;
  292. procedure TCnWaterImage.ClearWater;
  293. begin
  294. FWater.ClearWater;
  295. end;
  296. function TCnWaterImage.GetCanvas: TCanvas;
  297. begin
  298. Result := FDstBmp.Canvas;
  299. end;
  300. function TCnWaterImage.GetDamping: TWaterDamping;
  301. begin
  302. Result := FWater.Damping;
  303. end;
  304. function TCnWaterImage.GetInterval: Cardinal;
  305. begin
  306. Result := FTimer.Interval;
  307. end;
  308. procedure TCnWaterImage.SetDamping(const Value: TWaterDamping);
  309. begin
  310. FWater.Damping := Value;
  311. end;
  312. procedure TCnWaterImage.SetInterval(Value: Cardinal);
  313. begin
  314. FTimer.Interval := Value;
  315. end;
  316. procedure TCnWaterImage.SetPicture(Value: TPicture);
  317. begin
  318. FPicture.Assign(Value);
  319. end;
  320. procedure TCnWaterImage.Loaded;
  321. begin
  322. inherited;
  323. UpdateWaterData;
  324. end;
  325. end.