Using Delphi Write Windows Shell Extensions For the user of the operating system principle, it will know that a complete operating system provides a shell (shell) to facilitate the use of various functions provided by the usage operating system. The housing of Windows (here is the operating system of Windows 95 / Windows NT4.0 or more) not only provides a convenient and beautiful GUI graphical interface, but also provides powerful enclosure extension, and everyone may see in many software. These housings are expanded. For example, when you have Winzip in your system, when you right click on a folder or file, you will appear in the pop-up menu. Alternatively, the FTP site folder that appears in the Windows Explorer in the Bullet FTP. Windows supports seven types of housing extensions (called Handler), and their corresponding role is as follows:
(1) Context Menu Handlers: Add a context-related menu to a specific type of file object;
(2) DRAG-AND-DROP HANDLERS is used to support OLE data transmission when a user is dragging and dropping a type of file object;
(3) Icon Handlers is used to provide a unique icon to a file object, or you can give a certain type of file object;
(4) Property Sheet Handlers adds an attribute page to the file object (just right click on the file object or folder object, the dialog box that appears after selecting the Properties in the pop-up menu), the property page can be used for the same type of file object, or Give a file object specify a unique property page;
(5) Copy-Hook Handlers When the folder object or printer object is copied, move, delete, and rename it, it will be called by the system, and some of these operations can be allowed or prohibited by adding COPY-HOOK HANDERS for Windows.
(6) DROP TARGET HANDLERS is called by the system when an object is dragged and dropped to another object;
(7) Data Object handlers will be called by the system when the file is dragged, copy or paste.
All housing extensions of Windows are based on COM (Component Object Model) component model, and the housing is accessible through the interface (interface). The outer casing extension is designed into a 32-bit process server program, and is provided in the form of a dynamic link library to serve the operating system. Therefore, if you want to expand the Windows user interface, some knowledge of writing COM objects is necessary. Due to the limit, COM is not introduced here, the reader can refer to Microsoft's MSDN library or related help documentation, an interface can be seen as a special class, which contains a set of function combination processes to operate an object. After writing the enclosure extension, they must register them to take effect. All housing extensions must be registered under the HKEY_CLASSES_ROOT / CLSID key of the Windows registry. Below the key, you can find a key like {0000002F-0000-0000-C000-000000000046}, which is the global unique class identifier (GUID). Each housing extension must have a global unique class identifier, and Windows is using this unique class identifier to find the housing extension handler. The location of the housing extension dynamic link library in the system is recorded under the INPROCSERVER32 sub-key under the class identifier. The housing extension associated with some file type is registered under the corresponding type of Shellex primary key. If the Windows operating system is Windows NT, the housing extension must be registered under the hkey_local_machine / software / shellextensions / approved primary / shellextensions / approved primary / shellextensions / approved primary key in the registry. After compiling the DLL programs that have been extended in the case, you can use the regsvr32.exe provided by Windows itself to register the DLL server program. If you use Delphi, you can also select Register ActiveX Server to register in the RUN menu.
Let's first introduce a relatively common case extension application: context-related menus, in Windows, right-click the menu that pops up when you pop up with files or folders is called context-related menus. To dynamically add menu items to the context-related menu, you can implement it by writing the Context Menu Handler. For example, Winzip and UltraEdit, which are familiar to, are dynamically add menu items to the menu by writing the Context Menu Handler. If Winzip is installed in the system, when you use the right-click File (clip), the context-related menu has a menu item called Add to Windows.zip. This article is similar to the context menu provided by Winzip. It will add a file operation menu item to the context-related menu of any type of file object. When you click this item, the interface program will pop up a file operation window, perform file copy, move, etc. Write the Context Menu Handler must implement three interfaces of Ishellextinit, IconTextMenu, and TcomobjectFactory. ISHELLEXTINIT implementation interface initialization, IContextMenu interface object implements context-related menus, the IComObjectFactory interface implements the creation of objects. Let's introduce specific procedures. First click on the File | New item of the menu in Delphi, select DLL to create a DLL project file in the New Item window. Then click on the File | New item of the menu. Select Unit to create a Unit file in the New Item window, click the File | New item to click on the menu, select Form to create a new window in the New Item window. The engineering file will be saved as contextMenu.dpr, saved Unit1 as ContextMenuHandle.PAS, saved Form as Opwindow.PAS. Contextmenu.dpr program list is as follows: library contextmenu; uses ComServ, contextmenuhandle in 'contextmenuhandle.pas', opwindow in 'opwindow.pas' {Form2}; exports DllGetClassObject, DllCanUnloadNow, DllRegisterServer, DllUnregisterServer;
{$ R * .tlb}
{$ R * .res}
Begin
End.
The list of contextMenuHandle is as follows: Unit contextmenuhandle;
Interface Uses Windows, ActiveX, Comobj, Shlobj, Classes;
type TContextMenu = class (TComObject, IShellExtInit, IContextMenu) private FFileName: array [0..MAX_PATH] of Char; protected function IShellExtInit.Initialize = SEIInitialize; // Avoid compiler warning function SEIInitialize (pidlFolder: PItemIDList; lpdobj: IDataObject; hKeyProgID: HKEY): HResult; stdcall; function QueryContextMenu (Menu: HMENU; indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): HResult; stdcall; function InvokeCommand (var lpici: TCMInvokeCommandInfo): HResult; stdcall; function GetCommandString (idCmd, uType: UINT PWRESERVED: PSZNAME: LPSTR; CCHMAX: UINT): HRESULT; stdcall; end; const
Class_ContextMenu: tguid = '{19741013-C829-11D1-8233-0020AF3E97A0}';
{Global Single Identifier (GUID) is a 16-byte (128) value that uniquely identifies an interface (interface)} var filelist: tstringlist;
IMPLEMENTATION
Uses Comserve, Sysutils, Shellapi, Registry, Unitform;
function TContextMenu.SEIInitialize (pidlFolder: PItemIDList; lpdobj: IDataObject; hKeyProgID: HKEY): HResult; var StgMedium: TStgMedium; FormatEtc: TFormatEtc; FileNumber, i: Integer; begin file: // if lpdobj equal to Nil, the call fails if present (lpdobj = nil) The begin result: = E_INVALIDARG; EXIT;
File: // First initialize and empty filelist: = tstringList.create; filelist.clear; file: // Initialization Scrapbook format file with formatetc do beg cfformat: = cf_hdrop; ptd: = nil; dwaspect: = dvaspect_content: = DVASPECT_CONTENT LINDEX: = -1; TYMED: = TYMED_HGLOBAL; END; Result: = LPDOBJ.GETDATA (Formatetc, STGMEDIUM);
IF failed (result).
File: // Query the number of files in the user selected file filenumber: = DragQueryFile (STGMEDIUM.HGLOBAL, $ FFFFFFFFF, NIL, 0); file: // Save all users to FORELIST in FORELIST for i : = 0 TO FileNumber-1 Do Begin Dragqueryfile (STGMEDIUM.HGLOBAL, I, FFileName, Sizeof (FFileName); FileList.Add (FFileName); Result: = noError; End; ReleaseSTGMedium (STGMEDIUM); END;
function TContextMenu.QueryContextMenu (Menu: HMENU; indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): HResult; begin Result: = 0; if ((uFlags and $ 0000000F) = CMF_NORMAL) or ((uFlags and CMF_EXPLORE) <> 0) THEN BEGIN / / Add a menu item to the Context Menu, the title of the menu item is to view bitmap file INSERTMENU (Menu, IndexMenu, MF_String OR MF_BYPOSITION, IDCMDFIRST, PCHAR ('file operation')); // Return to add menu items Number Result: = 1; End;
Function TCONTextMenu.invokeCommand (var lpici: tcminvokecommandinfo): hResult; var fmop: tform1; begin // First, determine that the process is called by the system instead of being called by a program (HiWord (integer (ipici.lpverb)) <> 0) THEN BEGIN RESULT: = E_FAIL; EXIT; END; // Determines the validity IF of Parameters IF (Loword (LPICI.LPVERB) <> 0) The begin Result: = E_INVALIDARG; End;
File: // Establish file operation window frmop: = tform1.create (nil); file: // Add all file list to the list of FRMOP.ListBox1.Items: = fileListBox1.Items: = filelist; result: = noerror; end ;
function TContextMenu.GetCommandString (idCmd, uType: UINT; pwReserved: PUINT; pszName: LPSTR; cchMax: UINT): HRESULT; begin if (idCmd = 0) then begin if (uType = GCS_HELPTEXT) then {return to the menu item information to help This help information will appear on the status bar when the user moves the mouse to the menu item. } Strcopy (PSZNAME, PCHAR ('Click this menu item to execute file action'); result: = noerror; end else result: = e_invalidarg;
type TContextMenuFactory = class (TComObjectFactory) public procedure UpdateRegistry (Register: Boolean); override; end; procedure TContextMenuFactory.UpdateRegistry (Register: Boolean); var ClassID: string; begin if Register then begin inherited UpdateRegistry (Register); ClassID: = GUIDToString (Class_ContextMenu); File: // When the expansion library file is registered, add the library to the registry CreateRegkey ('* / shellex', ',' '); CreateRegKey (' * / shellex / contextMenuHandlers', ',' '); CreateRegKey (' * / shellex / contextMenuHandlers / Fileopreation ", '', classid);
file: // If the operating system is Windows NT, then if (Win32Platform = VER_PLATFORM_WIN32_NT) then with TRegistry.Create do try RootKey: = HKEY_LOCAL_MACHINE; OpenKey ( 'SOFTWARE / Microsoft / Windows / CurrentVersion / Shell Extensions', True); OpenKey (' Approved ', True); WriteString (ClassID,' Context Menu Shell Extension '); finally Free; end; end else begin DeleteRegKey (' * / shellex / ContextMenuHandlers / FileOpreation '); inherited UpdateRegistry (Register); end; end;
Initialization TcontextMenuFactory.create (COMSERVER, TCONTEXTMENU, CLASS_CONTEXTMENU, '', 'Context Menu Shell Extension', CIMULTIINSTANCE, TMAPARTMENT);
End.
Add a TListBox control and two TButton controls in the OpWindow window, OpWindows.PAS list is as follows: Unit Opwindow;
Interface
Uses Windows, Messages, Sysutils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, Stdctrls, Shlobj, Shellapi, ActiveX;
type TForm1 = class (TForm) ListBox1: TListBox; Button1: TButton; Button2: TButton; procedure FormCreate (Sender: TObject); procedure FormClose (Sender: TObject; var Action: TCloseAction); procedure Button1Click (Sender: TObject); procedure Button2Click (Sender: TOBJECT); private filelist: tstringlist; {public declarations} end; var form1: tform1
IMPLEMENTATION
{$ R * .dfm}
Procedure TForm1.FormCreate (Sender: TOBJECT); begin filelist: = tstringlist.create; button1.caption: = 'copy file'; button2.caption: = 'mobile file'; Self.Show;
Procedure TFORM1.FORMCLOSE (Sender: Tobject; VAR Action: tclosection); begin filelist.free; end;
Procedure TForm1.Button1Click (Sender: Tobject); var spath: string; fstemp: shfileopstruct; i: integer; begin spath: = inputbox ('file operation', 'input copy path ",' c: / windows'); if spath <> '' Then Begin fStemp.Wnd: = Self.Handle; File: // Settings File Operation Type FStemp.Wfunc: = FO_COPY; File: // Allow Undo operation fStemp.fflags: = fof_allowundo; for i: = 0 To listbox1.items.count-1 do begin file: // Source file full path name fStemp.pfrom: = pchar (listbox1.items.strings [i]); file: // To copy the path fstemp.pto: = Pchar (spath); fstemp.lpszprogresstitle: = 'copy file'; if shfileopert (fstemp) <> 0 Then ShowMessage ('file copy failed'); end; end;
Procedure TForm1.Button2Click (Sender: Tobject); var spath: string; fstemp: shfileopstruct; i: integer; begin spath: = inputbox ('file operation', 'input mobile path', 'c: / windows'); if spath <> '' The begin fstemp.wnd: = self.handle; fstemp.wfunc: = fo_move; fStemp.fflags: = fof_allowundo; for i: = 0 to listbox1.items.count-1 do begin fStemp.pfrom: = pchar (ListBox1.Items.Strings [i]); fStemp.pto: = pchar (spath); fstemp.lpszprogresstitle: = 'mobile file'; if shfileOperation (fstemp) <> 0 Then ShowMessage ('file copy failed "; end ; END; END;
Click on the Project | Build ContextMenu item of the menu, Delphi creates a contextMenu.dll file, which is the context-related menu program. Use, regrR32.exe registration program, then click on any one or several files in any one or several files in Windows, in the context menu, will more one file action menu item, click on the item, list the list of pop-up windows The file name of all the files you selected, you can select the copy file button or the mobile file button to perform file operations.