CnControlHook.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  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 CnControlHook;
  21. {* |<PRE>
  22. ================================================================================
  23. * 软件名称:开发包基础库
  24. * 单元名称:控件消息处理过程挂接组件单元
  25. * 单元作者:周劲羽 (zjy@cnpack.org)
  26. * 备 注:该单元定义了 TCnControlHook 组件,允许通过替换 TControl 子类的
  27. * WindowProc 属性来获得控件的消息通知。
  28. * 开发平台:PWin2000Pro + Delphi 5.0
  29. * 兼容测试:PWin9X/2000/XP + Delphi 5/6
  30. * 本 地 化:该单元中的字符串均符合本地化处理方式
  31. * 单元标识:$Id$
  32. * 修改记录:2003.04.30 V1.2
  33. * 修正控件在消息处理过程中释放导致挂接对象出错的问题
  34. * 2002.10.19 V1.1
  35. * 重新编写比较完善的组件
  36. * 2002.10.15 V1.0
  37. * 创建单元
  38. ================================================================================
  39. |</PRE>}
  40. interface
  41. {$I CnPack.inc}
  42. uses
  43. Windows, Messages, SysUtils, Classes, Controls, Forms, CnClasses, CnConsts,
  44. CnCompConsts;
  45. type
  46. //==============================================================================
  47. // 控件挂接子项
  48. //==============================================================================
  49. { TCnControlHookItem }
  50. TCnControlHook = class;
  51. TCnControlHookCollection = class;
  52. THookMessageEvent = procedure (Sender: TObject; Control: TControl;
  53. var Msg: TMessage; var Handled: Boolean) of object;
  54. {* 挂接消息事件
  55. |<PRE>
  56. Sender: TObject - 产生事件的组件
  57. Control: TControl - 该消息要发送的控件对象,即被挂接的控件
  58. var Msg: TMessage - 消息变量
  59. var Handled: Boolean - 事件处理过程是否捕获该消息,如果为真将不调用原控件消息过程
  60. |</PRE>}
  61. TCnControlHookItem = class(TCollectionItem)
  62. {* 控件挂接子项类,用于 TCnControlHook 组件中。
  63. 当被挂接的控件释放时,相关联的 Item 对象也会被自动释放,
  64. 用户可不用考虑重复挂接的问题,但也不要静态访问 Item 对象。}
  65. private
  66. FOwner: TCnControlHookCollection;
  67. FControl: TControl;
  68. FBeforeMessage: THookMessageEvent;
  69. FAfterMessage: THookMessageEvent;
  70. procedure SetControl(const Value: TControl);
  71. procedure Hook;
  72. procedure UnHook;
  73. protected
  74. function DoAfterMessage(Control: TControl; var Msg: TMessage): Boolean; dynamic;
  75. function DoBeforeMessage(Control: TControl; var Msg: TMessage): Boolean; dynamic;
  76. property Owner: TCnControlHookCollection read FOwner;
  77. public
  78. procedure Assign(Source: TPersistent); override;
  79. constructor Create(Collection: TCollection); override;
  80. destructor Destroy; override;
  81. published
  82. property Control: TControl read FControl write SetControl;
  83. {* 要 Hook 的控件}
  84. property BeforeMessage: THookMessageEvent read FBeforeMessage write FBeforeMessage;
  85. {* 控件消息事件,在默认消息处理过程之前调用}
  86. property AfterMessage: THookMessageEvent read FAfterMessage write FAfterMessage;
  87. {* 控件消息事件,在默认消息处理过程之后调用}
  88. end;
  89. //==============================================================================
  90. // 控件挂接列表类
  91. //==============================================================================
  92. { TCnControlHookCollection }
  93. TCnControlHookCollection = class(TOwnedCollection)
  94. {* 控件挂接列表类,用于 TCnControlHook 组件中}
  95. private
  96. FOwner: TCnControlHook;
  97. function GetItem(Index: Integer): TCnControlHookItem;
  98. procedure SetItem(Index: Integer; const Value: TCnControlHookItem);
  99. protected
  100. property ControlHook: TCnControlHook read FOwner;
  101. public
  102. constructor Create(AOwner: TCnControlHook);
  103. destructor Destroy; override;
  104. function Add(Control: TControl): TCnControlHookItem;
  105. {* 增加一个控件挂接项}
  106. procedure Remove(Control: TControl);
  107. {* 删除一个控件挂接项}
  108. function IndexOf(Control: TControl): Integer;
  109. {* 查找控件挂接项}
  110. property Items[Index: Integer]: TCnControlHookItem read GetItem write SetItem; default;
  111. {* 控件挂接项数组}
  112. end;
  113. //==============================================================================
  114. // 控件消息过程挂接组件
  115. //==============================================================================
  116. { TCnControlHook }
  117. TCnControlHook = class(TCnComponent)
  118. {* 控件消息过程挂接组件,允许通过替换 TControl 子类的 WindowProc 属性来获得控件的消息通知}
  119. private
  120. FActive: Boolean;
  121. FItems: TCnControlHookCollection;
  122. FBeforeMessage: THookMessageEvent;
  123. FAfterMessage: THookMessageEvent;
  124. procedure SetActive(const Value: Boolean);
  125. procedure SetItems(const Value: TCnControlHookCollection);
  126. protected
  127. function DoAfterMessage(Control: TControl; var Msg: TMessage): Boolean; dynamic;
  128. function DoBeforeMessage(Control: TControl; var Msg: TMessage): Boolean; dynamic;
  129. procedure Loaded; override;
  130. procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
  131. public
  132. constructor Create(AOwner: TComponent); override;
  133. destructor Destroy; override;
  134. function IndexOf(Control: TControl): Integer;
  135. {* 返回指定被挂接控件的索引号,如果不存在,返回 -1}
  136. function Hook(Control: TControl): TCnControlHookItem;
  137. {* 挂接指定控件,返回挂接项,如果已挂接返回原挂接项}
  138. procedure UnHook(Control: TControl);
  139. {* 取消对指定控件的挂接}
  140. function IsHooked(Control: TControl): Boolean;
  141. {* 判断指定控件是否被挂接}
  142. published
  143. property Active: Boolean read FActive write SetActive default True;
  144. {* 是否允许使用}
  145. property Items: TCnControlHookCollection read FItems write SetItems;
  146. {* 挂接控件列表}
  147. property BeforeMessage: THookMessageEvent read FBeforeMessage write FBeforeMessage;
  148. {* 控件消息事件,在默认消息处理过程之前调用}
  149. property AfterMessage: THookMessageEvent read FAfterMessage write FAfterMessage;
  150. {* 控件消息事件,在默认消息处理过程之后调用}
  151. end;
  152. implementation
  153. const
  154. UM_DESTROYHOOK = WM_USER + 101;
  155. type
  156. //==============================================================================
  157. // 控件消息处理过程挂接对象(私有类)
  158. //==============================================================================
  159. { TCnControlHookObject }
  160. TCnControlHookMgr = class;
  161. TCnControlHookObject = class
  162. private
  163. FList: TList;
  164. FControlHookMgr: TCnControlHookMgr;
  165. FControl: TControl;
  166. FOldWndProc: TWndMethod;
  167. FUpdateCount: Integer;
  168. FAutoFree: Boolean;
  169. function GetCount: Integer;
  170. function GetItem(Index: Integer): TCnControlHookItem;
  171. protected
  172. procedure WndProc(var Message: TMessage);
  173. property Control: TControl read FControl;
  174. property ControlHookMgr: TCnControlHookMgr read FControlHookMgr;
  175. public
  176. constructor Create(AControlHookMgr: TCnControlHookMgr; AControl: TControl);
  177. destructor Destroy; override;
  178. function Add(Item: TCnControlHookItem): Integer;
  179. procedure DoFree;
  180. function Updating: Boolean;
  181. procedure Delete(Item: TCnControlHookItem); overload;
  182. procedure Delete(Index: Integer); overload;
  183. property Count: Integer read GetCount;
  184. property Items[Index: Integer]: TCnControlHookItem read GetItem;
  185. end;
  186. //==============================================================================
  187. // 控件消息处理过程挂接组件(私有类)
  188. //==============================================================================
  189. { TCnControlHookMgr }
  190. TCnControlHookMgr = class(TComponent)
  191. {* 控件消息挂接组件,通过替换 TControl 子类的 WindowProc 属性来工作}
  192. private
  193. FList: TList;
  194. function GetCount: Integer;
  195. function GetHookedControls(Index: Integer): TControl;
  196. function GetItem(Index: Integer): TCnControlHookObject;
  197. protected
  198. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  199. public
  200. constructor Create(AOwner: TComponent); override;
  201. destructor Destroy; override;
  202. procedure HookControl(Item: TCnControlHookItem);
  203. procedure UnhookControl(Item: TCnControlHookItem); overload;
  204. procedure UnhookControl(Control: TControl); overload;
  205. function IndexOf(Control: TControl): Integer;
  206. property Count: Integer read GetCount;
  207. property HookedControls[Index: Integer]: TControl read GetHookedControls;
  208. property Items[Index: Integer]: TCnControlHookObject read GetItem;
  209. end;
  210. var
  211. ControlHookMgr: TCnControlHookMgr;
  212. // 返回挂接管理器
  213. function GetControlHookMgr: TCnControlHookMgr;
  214. begin
  215. if not Assigned(ControlHookMgr) then
  216. ControlHookMgr := TCnControlHookMgr.Create(nil);
  217. Result := ControlHookMgr;
  218. end;
  219. //==============================================================================
  220. // 控件消息处理过程挂接对象(私有类)
  221. //==============================================================================
  222. { TCnControlHookObject }
  223. // 构造器
  224. constructor TCnControlHookObject.Create(AControlHookMgr: TCnControlHookMgr;
  225. AControl: TControl);
  226. begin
  227. Assert(Assigned(AControlHookMgr) and Assigned(AControl));
  228. FUpdateCount := 0;
  229. FAutoFree := False;
  230. FList := TList.Create;
  231. FControlHookMgr := AControlHookMgr;
  232. FControl := AControl;
  233. FOldWndProc := FControl.WindowProc;
  234. FControl.WindowProc := WndProc;
  235. FControl.FreeNotification(FControlHookMgr);
  236. end;
  237. // 析构器
  238. destructor TCnControlHookObject.Destroy;
  239. var
  240. i: Integer;
  241. begin
  242. try // 异常保护
  243. if Assigned(FControl) then
  244. begin
  245. FControlHookMgr.FList.Remove(Self);
  246. FControl.RemoveFreeNotification(FControlHookMgr);
  247. FControl.WindowProc := FOldWndProc;
  248. FControl := nil;
  249. end;
  250. for i := 0 to Count - 1 do
  251. Items[i].Free;
  252. FList.Free;
  253. except
  254. Application.HandleException(Self);
  255. end;
  256. inherited;
  257. end;
  258. function TCnControlHookObject.Updating: Boolean;
  259. begin
  260. Result := FUpdateCount > 0;
  261. end;
  262. procedure TCnControlHookObject.DoFree;
  263. begin
  264. if Updating then
  265. begin
  266. FAutoFree := True;
  267. try
  268. FControlHookMgr.FList.Remove(Self);
  269. FControl.RemoveFreeNotification(FControlHookMgr);
  270. FControl.WindowProc := FOldWndProc;
  271. FControl := nil;
  272. except
  273. Application.HandleException(Self);
  274. end;
  275. end
  276. else
  277. Free;
  278. end;
  279. // 新的消息处理过程
  280. procedure TCnControlHookObject.WndProc(var Message: TMessage);
  281. var
  282. i: Integer;
  283. Handled: Boolean;
  284. begin
  285. try
  286. Inc(FUpdateCount);
  287. try
  288. Handled := False;
  289. // 调用挂接消息前处理过程
  290. for i := Count - 1 downto 0 do // 后挂接的先处理
  291. if Assigned(Items[i].FOwner) and Assigned(Items[i].FOwner.FOwner) and
  292. Items[i].FOwner.FOwner.FActive and Items[i].DoBeforeMessage(FControl,
  293. Message) then
  294. begin
  295. Handled := True;
  296. Break;
  297. end;
  298. if Handled then Exit;
  299. // 调用原处理过程
  300. if Assigned(FOldWndProc) then
  301. FOldWndProc(Message);
  302. // 调用挂接消息后处理过程
  303. if not FAutoFree then
  304. begin
  305. for i := Count - 1 downto 0 do // 后挂接的先处理
  306. if Assigned(Items[i].FOwner) and Assigned(Items[i].FOwner.FOwner) and
  307. Items[i].FOwner.FOwner.FActive and Items[i].DoAfterMessage(FControl,
  308. Message) then
  309. Break;
  310. end;
  311. finally
  312. Dec(FUpdateCount);
  313. end;
  314. // 此处进行释放
  315. if FAutoFree then
  316. Free;
  317. except
  318. Application.HandleException(Self);
  319. end;
  320. end;
  321. //------------------------------------------------------------------------------
  322. // 列表操作方法
  323. //------------------------------------------------------------------------------
  324. // 增加一项
  325. function TCnControlHookObject.Add(Item: TCnControlHookItem): Integer;
  326. begin
  327. if FList.IndexOf(Item) < 0 then
  328. begin
  329. Item.FControl := FControl;
  330. Result := FList.Add(Item);
  331. end
  332. else
  333. Result := -1;
  334. end;
  335. // 根据索引号删除一项
  336. procedure TCnControlHookObject.Delete(Index: Integer);
  337. begin
  338. if (Index >= 0) and (Index < FList.Count) then
  339. begin
  340. FList.Delete(Index);
  341. if Count = 0 then // 无挂接项时自动释放
  342. DoFree;
  343. end;
  344. end;
  345. // 根据子项删除一项
  346. procedure TCnControlHookObject.Delete(Item: TCnControlHookItem);
  347. begin
  348. Delete(FList.IndexOf(Item));
  349. end;
  350. //------------------------------------------------------------------------------
  351. // 属性读写方法
  352. //------------------------------------------------------------------------------
  353. // Count 属性读方法
  354. function TCnControlHookObject.GetCount: Integer;
  355. begin
  356. Result := FList.Count;
  357. end;
  358. // Items 数组属性读方法
  359. function TCnControlHookObject.GetItem(Index: Integer): TCnControlHookItem;
  360. begin
  361. Result := TCnControlHookItem(FList[Index]);
  362. end;
  363. //==============================================================================
  364. // 控件消息处理过程挂接组件(私有类)
  365. //==============================================================================
  366. { TCnControlHookMgr }
  367. // 构造器
  368. constructor TCnControlHookMgr.Create(AOwner: TComponent);
  369. begin
  370. inherited;
  371. FList := TList.Create;
  372. end;
  373. // 析构器
  374. destructor TCnControlHookMgr.Destroy;
  375. var
  376. i: Integer;
  377. begin
  378. for i := Count - 1 downto 0 do
  379. Items[i].DoFree;
  380. FList.Free;
  381. inherited;
  382. end;
  383. //------------------------------------------------------------------------------
  384. // 挂接相关方法
  385. //------------------------------------------------------------------------------
  386. // 组件通知事件
  387. procedure TCnControlHookMgr.Notification(AComponent: TComponent;
  388. Operation: TOperation);
  389. begin
  390. inherited;
  391. if (Operation = opRemove) and (AComponent is TControl) then
  392. UnhookControl(TControl(AComponent)); // 控件释放时反挂接
  393. end;
  394. // 返回控件索引号
  395. function TCnControlHookMgr.IndexOf(Control: TControl): Integer;
  396. var
  397. i: Integer;
  398. begin
  399. Result := -1;
  400. for i := 0 to Count - 1 do
  401. if HookedControls[i] = Control then
  402. begin
  403. Result := i;
  404. Exit;
  405. end;
  406. end;
  407. // 挂接控件
  408. procedure TCnControlHookMgr.HookControl(Item: TCnControlHookItem);
  409. var
  410. Obj: TCnControlHookObject;
  411. Idx: Integer;
  412. begin
  413. Assert(Assigned(Item) and Assigned(Item.FControl));
  414. Idx := IndexOf(Item.FControl);
  415. if Idx < 0 then
  416. begin
  417. Obj := TCnControlHookObject.Create(Self, Item.FControl);
  418. Obj.Add(Item);
  419. FList.Add(Obj);
  420. end
  421. else
  422. Items[Idx].Add(Item);
  423. end;
  424. // 反挂接控件
  425. procedure TCnControlHookMgr.UnhookControl(Item: TCnControlHookItem);
  426. var
  427. Idx: Integer;
  428. begin
  429. Assert(Assigned(Item) and Assigned(Item.FControl));
  430. Idx := IndexOf(Item.FControl);
  431. if Idx >= 0 then
  432. Items[Idx].Delete(Item);
  433. end;
  434. // 反挂接控件
  435. procedure TCnControlHookMgr.UnhookControl(Control: TControl);
  436. var
  437. Idx: Integer;
  438. begin
  439. Idx := IndexOf(Control);
  440. if Idx >= 0 then
  441. Items[Idx].DoFree;
  442. end;
  443. //------------------------------------------------------------------------------
  444. // 属性读写方法
  445. //------------------------------------------------------------------------------
  446. // HookedControlCount 属性读方法
  447. function TCnControlHookMgr.GetCount: Integer;
  448. begin
  449. Result := FList.Count;
  450. end;
  451. // HookedControls 属性读方法
  452. function TCnControlHookMgr.GetHookedControls(Index: Integer): TControl;
  453. begin
  454. Result := TCnControlHookObject(FList[Index]).Control;
  455. end;
  456. // Items 数组属性读方法
  457. function TCnControlHookMgr.GetItem(Index: Integer): TCnControlHookObject;
  458. begin
  459. Result := TCnControlHookObject(FList[Index]);
  460. end;
  461. //==============================================================================
  462. // 控件挂接子项
  463. //==============================================================================
  464. { TCnControlHookItem }
  465. // 类构造器
  466. constructor TCnControlHookItem.Create(Collection: TCollection);
  467. begin
  468. inherited;
  469. Assert(Assigned(Collection));
  470. FOwner := TCnControlHookCollection(Collection);
  471. end;
  472. // 类析构器
  473. destructor TCnControlHookItem.Destroy;
  474. begin
  475. if Assigned(FControl) then
  476. GetControlHookMgr.UnhookControl(Self);
  477. inherited;
  478. end;
  479. // 对象赋值
  480. procedure TCnControlHookItem.Assign(Source: TPersistent);
  481. begin
  482. if Source is TCnControlHookItem then
  483. begin
  484. TCnControlHookItem(Source).Control := FControl;
  485. end
  486. else
  487. inherited;
  488. end;
  489. // 产生 AfterMessage 事件
  490. function TCnControlHookItem.DoAfterMessage(Control: TControl;
  491. var Msg: TMessage): Boolean;
  492. begin
  493. Result := FOwner.FOwner.DoAfterMessage(Control, Msg);
  494. if not Result and FOwner.FOwner.FActive and Assigned(FAfterMessage) then
  495. FAfterMessage(Self, Control, Msg, Result);
  496. end;
  497. // 产生 BeforeMessage 事件
  498. function TCnControlHookItem.DoBeforeMessage(Control: TControl;
  499. var Msg: TMessage): Boolean;
  500. begin
  501. Result := FOwner.FOwner.DoBeforeMessage(Control, Msg);
  502. if not Result and FOwner.FOwner.FActive and Assigned(FBeforeMessage) then
  503. FBeforeMessage(Self, Control, Msg, Result);
  504. end;
  505. // 挂接
  506. procedure TCnControlHookItem.Hook;
  507. begin
  508. if ([csLoading, csDesigning] * FOwner.FOwner.ComponentState = []) and
  509. Assigned(FControl) then
  510. GetControlHookMgr.HookControl(Self);
  511. end;
  512. // 反挂接
  513. procedure TCnControlHookItem.UnHook;
  514. begin
  515. if ([csLoading, csDesigning] * FOwner.FOwner.ComponentState = []) and
  516. Assigned(FControl) then
  517. GetControlHookMgr.UnhookControl(Self);
  518. end;
  519. // Control 属性写方法
  520. procedure TCnControlHookItem.SetControl(const Value: TControl);
  521. begin
  522. if Value <> FControl then
  523. begin
  524. UnHook;
  525. FControl := Value;
  526. Hook;
  527. end;
  528. end;
  529. //==============================================================================
  530. // 控件挂接列表类
  531. //==============================================================================
  532. { TCnControlHookCollection }
  533. // 构造器
  534. constructor TCnControlHookCollection.Create(AOwner: TCnControlHook);
  535. begin
  536. inherited Create(AOwner, TCnControlHookItem);
  537. FOwner := AOwner;
  538. end;
  539. // 析构器
  540. destructor TCnControlHookCollection.Destroy;
  541. begin
  542. inherited;
  543. end;
  544. // 增加一项
  545. function TCnControlHookCollection.Add(Control: TControl): TCnControlHookItem;
  546. var
  547. Idx: Integer;
  548. begin
  549. Idx := IndexOf(Control);
  550. if Idx >= 0 then
  551. Result := Items[Idx]
  552. else
  553. begin
  554. Result := TCnControlHookItem(inherited Add);
  555. Result.Control := Control;
  556. end;
  557. end;
  558. // 删除一项
  559. procedure TCnControlHookCollection.Remove(Control: TControl);
  560. var
  561. Idx: Integer;
  562. begin
  563. Idx := IndexOf(Control);
  564. if Idx >= 0 then
  565. Items[Idx].Free;
  566. end;
  567. // 查找子项
  568. function TCnControlHookCollection.IndexOf(Control: TControl): Integer;
  569. var
  570. i: Integer;
  571. begin
  572. Result := -1;
  573. for i := 0 to Count - 1 do
  574. if Items[i].FControl = Control then
  575. begin
  576. Result := i;
  577. Exit;
  578. end;
  579. end;
  580. // Items 数组属性读方法
  581. function TCnControlHookCollection.GetItem(
  582. Index: Integer): TCnControlHookItem;
  583. begin
  584. Result := TCnControlHookItem(inherited Items[Index]);
  585. end;
  586. // Items 数组属性写方法
  587. procedure TCnControlHookCollection.SetItem(Index: Integer;
  588. const Value: TCnControlHookItem);
  589. begin
  590. inherited SetItem(Index, Value);
  591. end;
  592. //==============================================================================
  593. // 控件消息过程挂接组件
  594. //==============================================================================
  595. { TCnControlHook }
  596. // 构造器
  597. constructor TCnControlHook.Create(AOwner: TComponent);
  598. begin
  599. inherited;
  600. FItems := TCnControlHookCollection.Create(Self);
  601. FActive := True;
  602. end;
  603. // 析构器
  604. destructor TCnControlHook.Destroy;
  605. begin
  606. FItems.Free;
  607. inherited;
  608. end;
  609. // 运行期属性已装载
  610. procedure TCnControlHook.Loaded;
  611. var
  612. i: Integer;
  613. begin
  614. inherited;
  615. for i := 0 to Items.Count - 1 do
  616. Items.Items[i].Hook;
  617. end;
  618. // 挂接指定控件,返回挂接项索引号,如果已挂接返回原挂接项索引号
  619. function TCnControlHook.Hook(Control: TControl): TCnControlHookItem;
  620. begin
  621. Result := Items.Add(Control);
  622. end;
  623. // 返回指定被挂接控件的索引号,如果不存在,返回 -1
  624. function TCnControlHook.IndexOf(Control: TControl): Integer;
  625. begin
  626. Result := Items.IndexOf(Control);
  627. end;
  628. // 判断指定控件是否被挂接
  629. function TCnControlHook.IsHooked(Control: TControl): Boolean;
  630. begin
  631. Result := IndexOf(Control) >= 0;
  632. end;
  633. // 取消对指定控件的挂接
  634. procedure TCnControlHook.UnHook(Control: TControl);
  635. begin
  636. Items.Remove(Control);
  637. end;
  638. //------------------------------------------------------------------------------
  639. // 产生事件方法
  640. //------------------------------------------------------------------------------
  641. // 产生AfterMessage事件
  642. function TCnControlHook.DoAfterMessage(Control: TControl;
  643. var Msg: TMessage): Boolean;
  644. begin
  645. Result := False;
  646. if Active and Assigned(FAfterMessage) then
  647. FAfterMessage(Self, Control, Msg, Result);
  648. end;
  649. // 产生BeforeMessage事件
  650. function TCnControlHook.DoBeforeMessage(Control: TControl;
  651. var Msg: TMessage): Boolean;
  652. begin
  653. Result := False;
  654. if Active and Assigned(FBeforeMessage) then
  655. FBeforeMessage(Self, Control, Msg, Result);
  656. end;
  657. // Active 属性写方法
  658. procedure TCnControlHook.SetActive(const Value: Boolean);
  659. begin
  660. FActive := Value;
  661. end;
  662. // Items 属性写方法
  663. procedure TCnControlHook.SetItems(
  664. const Value: TCnControlHookCollection);
  665. begin
  666. FItems.Assign(Value);
  667. end;
  668. // 取作者信息
  669. procedure TCnControlHook.GetComponentInfo(var AName, Author, Email,
  670. Comment: string);
  671. begin
  672. AName := SCnControlHookName;
  673. Author := SCnPack_Zjy;
  674. Email := SCnPack_ZjyEmail;
  675. Comment := SCnControlHookComment;
  676. end;
  677. initialization
  678. finalization
  679. if Assigned(ControlHookMgr) then
  680. FreeAndNil(ControlHookMgr);
  681. end.