ContextMenuHandlerMain.pas 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. unit ContextMenuHandlerMain;
  2. interface
  3. uses
  4. DragDrop, DropTarget, DragDropContext,
  5. Forms, ShlObj, SysUtils, Classes, Menus;
  6. {$include '..\..\Components\DragDrop.inc'}
  7. {$ifndef VER13_PLUS}
  8. type
  9. TDataModule = TForm;
  10. {$endif}
  11. type
  12. TDataModuleContextMenuHandler = class(TDataModule, IUnknown, IShellExtInit, IContextMenu)
  13. DropContextMenu1: TDropContextMenu;
  14. PopupMenu1: TPopupMenu;
  15. MenuCompile: TMenuItem;
  16. MenuLine1: TMenuItem;
  17. procedure MenuCompileClick(Sender: TObject);
  18. procedure DropContextMenu1Popup(Sender: TObject);
  19. procedure DataModuleCreate(Sender: TObject);
  20. procedure DataModuleDestroy(Sender: TObject);
  21. private
  22. FFiles: TStrings;
  23. public
  24. // Aggregate IShellExtInit and IContextMenu to the TDropContextMenu component.
  25. property ContextMenuHandler: TDropContextMenu read DropContextMenu1
  26. implements IShellExtInit, IContextMenu;
  27. end;
  28. implementation
  29. {$R *.DFM}
  30. uses
  31. Windows,
  32. ComServ,
  33. ComObj,
  34. Registry;
  35. const
  36. // CLSID for this shell extension.
  37. // Modify this for your own shell extensions (press [Ctrl]+[Shift]+G in
  38. // the IDE editor to gererate a new CLSID).
  39. CLSID_ContextMenuHandler: TGUID = '{516EC4D3-4AD9-11D5-AA6A-00E0189008B3}';
  40. resourcestring
  41. // Name of the file class we wish to operate on.
  42. sFileClass = 'DelphiProject';
  43. // The extension would normally have been '.dpr' (Delphi project), but since
  44. // we don't want to delete Delphi's file registration when we are uninstalled,
  45. // we specify an empty string as the extension and thus disable the
  46. // registration and unregistration of the file type.
  47. sFileExtension = '';
  48. // Class name of our shell extension.
  49. sClassName = 'DelphiProjectCompiler';
  50. // Description of our shell extension.
  51. sDescription = 'Drag and Drop Component Suite Context Menu demo';
  52. // File name replacement in case multiple files has been selected.
  53. sManyFiles = 'multiple projects';
  54. // Returns string containing path to Delphi command line compiler.
  55. function GetCompilerPath: string;
  56. var
  57. Reg: TRegistry;
  58. Version: integer;
  59. begin
  60. Reg := TRegistry.Create;
  61. try
  62. with Reg do
  63. begin
  64. RootKey := HKEY_LOCAL_MACHINE;
  65. // Locate higest version of Delphi in registry (v2 - v10).
  66. Version := 10;
  67. while (Version >= 3) and (not OpenKey(format('\SOFTWARE\Borland\Delphi\%d.0', [Version]), False)) do
  68. dec(Version);
  69. Result := ExpandFileName(ReadString('RootDir') + '\bin\dcc32.exe');
  70. end;
  71. if AnsiPos(' ', Result) <> 0 then
  72. Result := ExtractShortPathName(Result);
  73. finally
  74. Reg.Free;
  75. end;
  76. end;
  77. procedure TDataModuleContextMenuHandler.DataModuleCreate(Sender: TObject);
  78. begin
  79. FFiles := TStringList.Create;
  80. end;
  81. procedure TDataModuleContextMenuHandler.DataModuleDestroy(Sender: TObject);
  82. begin
  83. FFiles.Free;
  84. end;
  85. procedure TDataModuleContextMenuHandler.MenuCompileClick(Sender: TObject);
  86. procedure WinExecAndWait(const FileName, Parameters: string; Wait: boolean);
  87. var
  88. StartupInfo: TStartupInfo;
  89. ProcessInfo: TProcessInformation;
  90. begin
  91. FillChar(StartupInfo, Sizeof(StartupInfo),#0);
  92. StartupInfo.cb := Sizeof(StartupInfo);
  93. StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  94. StartupInfo.wShowWindow := SW_SHOWDEFAULT;
  95. // Warning: Even though we could (and I would prefer to) call CreateProcess
  96. // like this:
  97. // CreateProcess(PChar(FileName), PChar(Parameters), ...
  98. // a bug in Delphi's ParamStr function would cause the target application
  99. // to fail if we did so. The bug causes ParamStr(1) to "disappear".
  100. if (CreateProcess(nil, PChar(FileName+' '+Parameters), nil, nil, False,
  101. CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo,
  102. ProcessInfo)) then
  103. begin
  104. if (Wait) then
  105. // Wait 60 seconds then assume something went wrong and exit.
  106. WaitforSingleObject(ProcessInfo.hProcess, 60000);
  107. end;
  108. end;
  109. var
  110. i: integer;
  111. begin
  112. // Invoke Delphi command line compiler to compile each project in turn.
  113. for i := 0 to FFiles.Count-1 do
  114. WinExecAndWait(GetCompilerPath, ExtractShortPathName(FFiles[0]), True);
  115. end;
  116. procedure TDataModuleContextMenuHandler.DropContextMenu1Popup(Sender: TObject);
  117. var
  118. i: integer;
  119. procedure ClearItem(Item: TMenuItem);
  120. begin
  121. {$ifdef VER13_PLUS}
  122. Item.Clear;
  123. {$else}
  124. while (Item.Count > 0) do
  125. Item[0].Free;
  126. {$endif}
  127. end;
  128. begin
  129. // TDropContextMenu component now contains the files being dragged. Save them
  130. // for later use.
  131. FFiles.Assign(DropContextMenu1.Files);
  132. // Make sure that we only work on Delphi project files.
  133. for i := FFiles.Count-1 downto 0 do
  134. if (AnsiCompareText(ExtractFileExt(FFiles[i]), '.dpr') <> 0) then
  135. FFiles.Delete(i);
  136. // Insert source filename(s) into menu.
  137. if (FFiles.Count = 1) then
  138. MenuCompile.Caption := format(MenuCompile.Caption, [ExtractFileName(FFiles[0])])
  139. else if (FFiles.Count > 1) then
  140. MenuCompile.Caption := format(MenuCompile.Caption, [sManyFiles])
  141. else
  142. ClearItem(PopupMenu1.Items);
  143. end;
  144. initialization
  145. TDropContextMenuFactory.Create(ComServer, TDataModuleContextMenuHandler,
  146. CLSID_ContextMenuHandler, sClassName, sDescription, sFileClass,
  147. sFIleExtension, ciMultiInstance);
  148. end.