home *** CD-ROM | disk | FTP | other *** search
/ Delphi Anthology / aDELPHI.iso / Runimage / Delphi50 / Demos / Activex / Shellext / contextm.pas next >
Pascal/Delphi Source File  |  1999-08-11  |  6KB  |  203 lines

  1. unit ContextM;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, ActiveX, ComObj, ShlObj, Dialogs;
  7.  
  8. type
  9.   TContextMenu = class(TComObject, IShellExtInit, IContextMenu)
  10.   private
  11.     FFileName: array[0..MAX_PATH] of Char;
  12.   protected
  13.     { IShellExtInit }
  14.     function IShellExtInit.Initialize = SEIInitialize; // Avoid compiler warning
  15.     function SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
  16.       hKeyProgID: HKEY): HResult; stdcall;
  17.     { IContextMenu }
  18.     function QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast,
  19.       uFlags: UINT): HResult; stdcall;
  20.     function InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult; stdcall;
  21.     function GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
  22.       pszName: LPSTR; cchMax: UINT): HResult; stdcall;
  23.   end;
  24.  
  25. const
  26.   Class_ContextMenu: TGUID = '{EBDF1F20-C829-11D1-8233-0020AF3E97A9}';
  27.  
  28. implementation
  29.  
  30. uses ComServ, SysUtils, ShellApi, Registry;
  31.  
  32. function TContextMenu.SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
  33.   hKeyProgID: HKEY): HResult;
  34. var
  35.   StgMedium: TStgMedium;
  36.   FormatEtc: TFormatEtc;
  37. begin
  38.   // Fail the call if lpdobj is Nil.
  39.   if (lpdobj = nil) then begin
  40.     Result := E_INVALIDARG;
  41.     Exit;
  42.   end;
  43.  
  44.   with FormatEtc do begin
  45.     cfFormat := CF_HDROP;
  46.     ptd      := nil;
  47.     dwAspect := DVASPECT_CONTENT;
  48.     lindex   := -1;
  49.     tymed    := TYMED_HGLOBAL;
  50.   end;
  51.  
  52.   // Render the data referenced by the IDataObject pointer to an HGLOBAL
  53.   // storage medium in CF_HDROP format.
  54.   Result := lpdobj.GetData(FormatEtc, StgMedium);
  55.   if Failed(Result) then
  56.     Exit;
  57.   // If only one file is selected, retrieve the file name and store it in
  58.   // FFileName. Otherwise fail the call.
  59.   if (DragQueryFile(StgMedium.hGlobal, $FFFFFFFF, nil, 0) = 1) then begin
  60.     DragQueryFile(StgMedium.hGlobal, 0, FFileName, SizeOf(FFileName));
  61.     Result := NOERROR;
  62.   end
  63.   else begin
  64.     FFileName[0] := #0;
  65.     Result := E_FAIL;
  66.   end;
  67.   ReleaseStgMedium(StgMedium);
  68. end;
  69.  
  70. function TContextMenu.QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst,
  71.           idCmdLast, uFlags: UINT): HResult;
  72. begin
  73.   Result := 0; // or use MakeResult(SEVERITY_SUCCESS, FACILITY_NULL, 0);
  74.  
  75.   if ((uFlags and $0000000F) = CMF_NORMAL) or
  76.      ((uFlags and CMF_EXPLORE) <> 0) then begin
  77.     // Add one menu item to context menu
  78.     InsertMenu(Menu, indexMenu, MF_STRING or MF_BYPOSITION, idCmdFirst,
  79.       'Compile...');
  80.  
  81.     // Return number of menu items added
  82.     Result := 1; // or use MakeResult(SEVERITY_SUCCESS, FACILITY_NULL, 1)
  83.   end;
  84. end;
  85.  
  86. function GetCompilerPath: string;
  87. // Returns string containing path to Delphi command line compiler
  88. var
  89.   Reg: TRegistry;
  90. begin
  91.   Reg := TRegistry.Create;
  92.   try
  93.     with Reg do begin
  94.       RootKey := HKEY_LOCAL_MACHINE;
  95.  
  96.       OpenKey('\SOFTWARE\Borland\Delphi\5.0', False);
  97.       Result := ExpandFileName(ReadString('RootDir') + '\bin\dcc32.exe');
  98.     end;
  99.     if AnsiPos(' ', Result) <> 0 then
  100.       Result := ExtractShortPathName(Result);
  101.     Result := Result + ' "%s"';
  102.   finally
  103.     Reg.Free;
  104.   end;
  105. end;
  106.  
  107. function TContextMenu.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
  108. resourcestring
  109.   sPathError = 'Error setting current directory';
  110.  
  111. var
  112.   H: THandle;
  113.   PrevDir: string;
  114.   
  115. begin
  116.   Result := E_FAIL;
  117.   // Make sure we are not being called by an application
  118.   if (HiWord(Integer(lpici.lpVerb)) <> 0) then
  119.   begin
  120.     Exit;
  121.   end;
  122.  
  123.   // Make sure we aren't being passed an invalid argument number
  124.   if (LoWord(lpici.lpVerb) <> 0) then begin
  125.     Result := E_INVALIDARG;
  126.     Exit;
  127.   end;
  128.  
  129.   // Execute the command specified by lpici.lpVerb
  130.   // by invoking the Delphi command line compiler.
  131.   PrevDir := GetCurrentDir;
  132.   try
  133.     if not SetCurrentDir(ExtractFilePath(FFileName)) then
  134.       raise Exception.CreateRes(@sPathError);
  135.  
  136.     H := WinExec(PChar(Format(GetCompilerPath, [FFileName])), lpici.nShow);
  137.  
  138.     if (H < 32) then
  139.       MessageBox(lpici.hWnd, 'Error executing Delphi compiler.', 'Error',
  140.         MB_ICONERROR or MB_OK);
  141.     Result := NOERROR;
  142.   finally
  143.     SetCurrentDir(PrevDir);
  144.   end;
  145. end;
  146.  
  147. function TContextMenu.GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
  148.   pszName: LPSTR; cchMax: UINT): HRESULT;
  149. begin
  150.   if (idCmd = 0) then begin
  151.     if (uType = GCS_HELPTEXT) then
  152.       // return help string for menu item
  153.       StrCopy(pszName, 'Compile the selected Delphi project');
  154.     Result := NOERROR;
  155.   end
  156.   else
  157.     Result := E_INVALIDARG;
  158. end;
  159.  
  160. type
  161.   TContextMenuFactory = class(TComObjectFactory)
  162.   public
  163.     procedure UpdateRegistry(Register: Boolean); override;
  164.   end;
  165.  
  166. procedure TContextMenuFactory.UpdateRegistry(Register: Boolean);
  167. var
  168.   ClassID: string;
  169. begin
  170.   if Register then begin
  171.     inherited UpdateRegistry(Register);
  172.  
  173.     ClassID := GUIDToString(Class_ContextMenu);
  174.     CreateRegKey('DelphiProject\shellex', '', '');
  175.     CreateRegKey('DelphiProject\shellex\ContextMenuHandlers', '', '');
  176.     CreateRegKey('DelphiProject\shellex\ContextMenuHandlers\ContMenu', '', ClassID);
  177.  
  178.     if (Win32Platform = VER_PLATFORM_WIN32_NT) then
  179.       with TRegistry.Create do
  180.         try
  181.           RootKey := HKEY_LOCAL_MACHINE;
  182.           OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions', True);
  183.           OpenKey('Approved', True);
  184.           WriteString(ClassID, 'Delphi Context Menu Shell Extension Example');
  185.         finally
  186.           Free;
  187.         end;
  188.   end
  189.   else begin
  190.     DeleteRegKey('DelphiProject\shellex\ContextMenuHandlers\ContMenu');
  191.     DeleteRegKey('DelphiProject\shellex\ContextMenuHandlers');
  192.     DeleteRegKey('DelphiProject\shellex');
  193.  
  194.     inherited UpdateRegistry(Register);
  195.   end;
  196. end;
  197.  
  198. initialization
  199.   TContextMenuFactory.Create(ComServer, TContextMenu, Class_ContextMenu,
  200.     '', 'Delphi Context Menu Shell Extension Example', ciMultiInstance,
  201.     tmApartment);
  202. end.
  203.