CnRestoreSystemMenu.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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 CnRestoreSystemMenu;
  21. {* |<PRE>
  22. ================================================================================
  23. * 软件名称:开发包属性、组件编辑器库
  24. * 单元名称:用来恢复编辑器控件右键菜单的组件
  25. * 单元作者:Chinbo(Shenloqi@hotmail.com)
  26. * 备 注:
  27. * 开发平台:PWin2000Pro + Delphi 7.0
  28. * 兼容测试:PWin9X/2000/XP + Delphi 5/6
  29. * 本 地 化:该单元和窗体中的字符串已经本地化处理方式
  30. * 单元标识:$Id$
  31. * 修改记录:
  32. * 2005.08.05 by shenloqi
  33. * 修正对于TCombobox处理的遗漏
  34. * 2005.08.03 V1.0
  35. * 创建单元
  36. ================================================================================
  37. |</PRE>}
  38. interface
  39. {$I CnPack.inc}
  40. uses
  41. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, StdCtrls,
  42. AppEvnts, CnConsts, CnClasses, CnCompConsts;
  43. type
  44. TCnContextMenuOption = (ccoVCLMenu, ccoEat, ccoSystemMenu);
  45. {$IFNDEF COMPILER6_UP}
  46. TCustomCombo = TCustomComboBox;
  47. {$ENDIF}
  48. TCnAdditionalContextMenuEvent = procedure (Ctrl: TWinControl;
  49. var cco: TCnContextMenuOption) of object;
  50. TCnAdditionalWindowContextMenuEvent = procedure (hwnd: THandle;
  51. var cco: TCnContextMenuOption) of object;
  52. TCnCustomEditContextMenuEvent = procedure (Edit: TCustomEdit;
  53. var cco: TCnContextMenuOption) of object;
  54. TCnCustomComboContextMenuEvent = procedure (Combo: TCustomCombo;
  55. var cco: TCnContextMenuOption) of object;
  56. TCnNonDelphiControlContextMenuEvent = procedure (SysControl: THandle;
  57. var cco: TCnContextMenuOption) of object;
  58. TCnRestoreSystemMenu = class(TCnComponent)
  59. private
  60. FAppEvent: TApplicationEvents;
  61. FAdditionalClasses: TStringList;
  62. FAdditionalWindowClasses: TStringList;
  63. FOnAdditionalContextMenu: TCnAdditionalContextMenuEvent;
  64. FDefAdditionalCtxMenuOpt: TCnContextMenuOption;
  65. FOnAdditionalWindowContextMenu: TCnAdditionalWindowContextMenuEvent;
  66. FDefAdditionalWndCtxMenuOpt: TCnContextMenuOption;
  67. FOnCustomComboContextMenu: TCnCustomComboContextMenuEvent;
  68. FDefCstmComboCtxMenuOpt: TCnContextMenuOption;
  69. FOnCustomEditContextMenu: TCnCustomEditContextMenuEvent;
  70. FDefCstmEdtCtxMenuOpt: TCnContextMenuOption;
  71. FOnNonDelphiControlContextMenu: TCnNonDelphiControlContextMenuEvent;
  72. FDefNonDelphiCtrlCtxMenuOpt: TCnContextMenuOption;
  73. function GetWindowClass(hwnd: THandle): string;
  74. function IsAdditionalClass(wc: TWinControl): Boolean;
  75. function IsAdditionalWindowClass(hwnd: THandle): Boolean;
  76. procedure DoMessage(var Msg: TMsg; var Handled: Boolean);
  77. protected
  78. procedure DoAdditionalContextMenu(Ctrl: TWinControl;
  79. var cco: TCnContextMenuOption);
  80. procedure DoAdditionalWindowContextMenu(hwnd: THandle;
  81. var cco: TCnContextMenuOption);
  82. procedure DoCustomComboContextMenu(Combo: TCustomCombo;
  83. var cco: TCnContextMenuOption);
  84. procedure DoCustomEditContextMenu(Edit: TCustomEdit;
  85. var cco: TCnContextMenuOption);
  86. procedure DoNonDelphiControlContextMenu(SysControl: THandle;
  87. var cco: TCnContextMenuOption);
  88. procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
  89. public
  90. constructor Create(AOwner: TComponent); override;
  91. destructor Destroy; override;
  92. published
  93. property AdditionalClasses: TStringList read FAdditionalClasses write FAdditionalClasses;
  94. property AdditionalWindowClasses: TStringList read FAdditionalWindowClasses write FAdditionalWindowClasses;
  95. property DefAdditionalCtxMenuOpt: TCnContextMenuOption
  96. read FDefAdditionalCtxMenuOpt write FDefAdditionalCtxMenuOpt default ccoSystemMenu;
  97. property DefAdditionalWndCtxMenuOpt: TCnContextMenuOption
  98. read FDefAdditionalWndCtxMenuOpt write FDefAdditionalWndCtxMenuOpt default ccoSystemMenu;
  99. property DefCstmComboCtxMenuOpt: TCnContextMenuOption
  100. read FDefCstmComboCtxMenuOpt write FDefCstmComboCtxMenuOpt default ccoSystemMenu;
  101. property DefCstmEdtCtxMenuOpt: TCnContextMenuOption
  102. read FDefCstmEdtCtxMenuOpt write FDefCstmEdtCtxMenuOpt default ccoSystemMenu;
  103. property DefNonDelphiCtrlCtxMenuOpt: TCnContextMenuOption
  104. read FDefNonDelphiCtrlCtxMenuOpt write FDefNonDelphiCtrlCtxMenuOpt default ccoVCLMenu;
  105. property OnAdditionalContextMenu: TCnAdditionalContextMenuEvent
  106. read FOnAdditionalContextMenu write FOnAdditionalContextMenu;
  107. property OnAdditionalWindowContextMenu: TCnAdditionalWindowContextMenuEvent
  108. read FOnAdditionalWindowContextMenu write FOnAdditionalWindowContextMenu;
  109. property OnCustomComboContextMenu: TCnCustomComboContextMenuEvent
  110. read FOnCustomComboContextMenu write FOnCustomComboContextMenu;
  111. property OnCustomEditContextMenu: TCnCustomEditContextMenuEvent
  112. read FOnCustomEditContextMenu write FOnCustomEditContextMenu;
  113. property OnNonDelphiControlContextMenu: TCnNonDelphiControlContextMenuEvent
  114. read FOnNonDelphiControlContextMenu write FOnNonDelphiControlContextMenu;
  115. end;
  116. implementation
  117. { TCnRestoreSystemMenu }
  118. constructor TCnRestoreSystemMenu.Create(AOwner: TComponent);
  119. begin
  120. inherited;
  121. FAdditionalClasses := TStringList.Create;
  122. FAdditionalWindowClasses := TStringList.Create;
  123. FDefAdditionalCtxMenuOpt := ccoSystemMenu;
  124. FDefAdditionalWndCtxMenuOpt := ccoSystemMenu;
  125. FDefCstmComboCtxMenuOpt := ccoSystemMenu;
  126. FDefCstmEdtCtxMenuOpt := ccoSystemMenu;
  127. FDefNonDelphiCtrlCtxMenuOpt := ccoVCLMenu;
  128. FAppEvent := TApplicationEvents.Create(Self);
  129. FAppEvent.OnMessage := DoMessage;
  130. end;
  131. destructor TCnRestoreSystemMenu.Destroy;
  132. begin
  133. FAppEvent.Free;
  134. FAdditionalWindowClasses.Free;
  135. FAdditionalClasses.Free;
  136. inherited;
  137. end;
  138. procedure TCnRestoreSystemMenu.DoAdditionalContextMenu(Ctrl: TWinControl;
  139. var cco: TCnContextMenuOption);
  140. begin
  141. if Assigned(FOnAdditionalContextMenu) then FOnAdditionalContextMenu(Ctrl, cco);
  142. end;
  143. procedure TCnRestoreSystemMenu.DoAdditionalWindowContextMenu(hwnd: THandle;
  144. var cco: TCnContextMenuOption);
  145. begin
  146. if Assigned(FOnAdditionalWindowContextMenu) then FOnAdditionalWindowContextMenu(hwnd, cco);
  147. end;
  148. procedure TCnRestoreSystemMenu.DoCustomComboContextMenu(
  149. Combo: TCustomCombo; var cco: TCnContextMenuOption);
  150. begin
  151. if Assigned(FOnCustomComboContextMenu) then FOnCustomComboContextMenu(Combo, cco);
  152. end;
  153. procedure TCnRestoreSystemMenu.DoCustomEditContextMenu(Edit: TCustomEdit;
  154. var cco: TCnContextMenuOption);
  155. begin
  156. if Assigned(FOnCustomEditContextMenu) then FOnCustomEditContextMenu(Edit, cco);
  157. end;
  158. procedure TCnRestoreSystemMenu.DoNonDelphiControlContextMenu(
  159. SysControl: THandle; var cco: TCnContextMenuOption);
  160. begin
  161. if Assigned(FOnNonDelphiControlContextMenu) then FOnNonDelphiControlContextMenu(SysControl, cco);
  162. end;
  163. function TCnRestoreSystemMenu.GetWindowClass(hwnd: THandle): string;
  164. var
  165. s: array[0..MAX_PATH - 1] of Char;
  166. begin
  167. GetClassName(hwnd, s, Length(s));
  168. Result := UpperCase(s);
  169. end;
  170. function TCnRestoreSystemMenu.IsAdditionalClass(wc: TWinControl): Boolean;
  171. begin
  172. Result := (wc <> nil) and (FAdditionalClasses.IndexOf(wc.ClassName) >= 0);
  173. end;
  174. function TCnRestoreSystemMenu.IsAdditionalWindowClass(
  175. hwnd: THandle): Boolean;
  176. begin
  177. Result := FAdditionalWindowClasses.IndexOf(GetWindowClass(hwnd)) >= 0;
  178. end;
  179. type
  180. THackCustomEdit = class(TCustomEdit);
  181. procedure TCnRestoreSystemMenu.DoMessage(var Msg: TMsg; var Handled: Boolean);
  182. var
  183. wc: TWinControl;
  184. ce: TCustomEdit;
  185. cmb: TCustomCombo;
  186. cco: TCnContextMenuOption;
  187. begin
  188. if Msg.message = WM_RBUTTONUP then
  189. begin
  190. wc := FindControl(Msg.hwnd);
  191. if wc = nil then
  192. wc := FindControl(GetParent(Msg.hwnd));
  193. if (wc <> nil) and (csDesigning in wc.ComponentState) then
  194. Exit;
  195. if wc is TCustomCombo then
  196. begin
  197. cmb := TCustomCombo(wc);
  198. cco := DefCstmComboCtxMenuOpt;
  199. DoCustomComboContextMenu(cmb, cco);
  200. case cco of
  201. ccoVCLMenu: ;
  202. ccoEat: Handled := True;
  203. ccoSystemMenu:
  204. begin
  205. with Msg do
  206. begin
  207. CallWindowProc(Pointer(GetWindowLong(Msg.hwnd, GWL_WNDPROC)), Msg.hwnd, WM_CONTEXTMENU, WParam, MakeLParam(pt.X, pt.Y));
  208. end;
  209. Handled := True;
  210. end;
  211. end;
  212. end
  213. else if wc is TCustomEdit then
  214. begin
  215. ce := TCustomEdit(wc);
  216. cco := DefCstmEdtCtxMenuOpt;
  217. DoCustomEditContextMenu(ce, cco);
  218. case cco of
  219. ccoVCLMenu: ;
  220. ccoEat: Handled := True;
  221. ccoSystemMenu:
  222. begin
  223. with THackCustomEdit(ce) do
  224. begin
  225. if PopupMenu = nil then
  226. begin
  227. with Msg do
  228. begin
  229. CallWindowProc(DefWndProc, Handle, WM_CONTEXTMENU, WParam, MakeLParam(pt.X, pt.Y));
  230. end;
  231. Handled := True;
  232. end;
  233. end;
  234. end;
  235. end;
  236. end
  237. else if IsAdditionalClass(wc) then
  238. begin
  239. cco := DefAdditionalCtxMenuOpt;
  240. DoAdditionalContextMenu(wc, cco);
  241. case cco of
  242. ccoVCLMenu: ;
  243. ccoEat: Handled := True;
  244. ccoSystemMenu:
  245. begin
  246. with Msg do
  247. begin
  248. CallWindowProc(Pointer(GetWindowLong(Msg.hwnd, GWL_WNDPROC)), Msg.hwnd, WM_CONTEXTMENU, WParam, MakeLParam(pt.X, pt.Y));
  249. end;
  250. Handled := True;
  251. end;
  252. end;
  253. end
  254. else if IsAdditionalWindowClass(Msg.hwnd) then
  255. begin
  256. cco := DefAdditionalWndCtxMenuOpt;
  257. DoAdditionalWindowContextMenu(Msg.hwnd, cco);
  258. case cco of
  259. ccoVCLMenu: ;
  260. ccoEat: Handled := True;
  261. ccoSystemMenu:
  262. begin
  263. with Msg do
  264. begin
  265. CallWindowProc(Pointer(GetWindowLong(Msg.hwnd, GWL_WNDPROC)), Msg.hwnd, WM_CONTEXTMENU, WParam, MakeLParam(pt.X, pt.Y));
  266. end;
  267. Handled := True;
  268. end;
  269. end;
  270. end
  271. else if wc = nil then
  272. begin
  273. cco := DefNonDelphiCtrlCtxMenuOpt;
  274. DoNonDelphiControlContextMenu(Msg.hwnd, cco);
  275. case cco of
  276. ccoVCLMenu: ;
  277. ccoEat: Handled := True;
  278. ccoSystemMenu:
  279. begin
  280. with Msg do
  281. begin
  282. CallWindowProc(Pointer(GetWindowLong(Msg.hwnd, GWL_WNDPROC)), Msg.hwnd, WM_CONTEXTMENU, WParam, MakeLParam(pt.X, pt.Y));
  283. end;
  284. Handled := True;
  285. end;
  286. end;
  287. end
  288. else
  289. begin
  290. Exit;
  291. end;
  292. end;
  293. end;
  294. procedure TCnRestoreSystemMenu.GetComponentInfo(var AName, Author, Email,
  295. Comment: string);
  296. begin
  297. AName := SCnRestoreSystemMenuName;
  298. Author := SCnPack_Shenloqi;
  299. Email := SCnPack_ShenloqiEmail;
  300. Comment := SCnRestoreSystemMenuComment;
  301. end;
  302. end.