我写的程序如下:<br>Contextmenuhandle.pas,将Form保存为<br>OpWindow.pas。<br>Contextmenu.dpr的程序清单如下:<br>library contextmenu;<br> uses<br> ComServ,<br> contextmenuhandle in 'contextmenuhandle.pas',<br> opwindow in 'opwindow.pas' {Form2};<br><br>exports<br> DllGetClassObject,<br> DllCanUnloadNow,<br> DllRegisterServer,<br> DllUnregisterServer;<br><br>{$R *.TLB}<br><br>{$R *.RES}<br><br>begin<br><br>end.<br><br> Contextmenuhandle的程序清单如下:<br>unit ContextMenuHandle;<br><br>interface<br> uses Windows,ActiveX,ComObj,ShlObj,Classes;<br><br>type<br> TContextMenu = class(TComObject,IShellExtInit,IContextMenu)<br> private<br> FFileName: array[0..MAX_PATH] of Char;<br> protected<br> function IShellExtInit.Initialize = SEIInitialize; // Avoid compiler warning<br> function SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;<br> hKeyProgID: HKEY): HResult; stdcall;<br> function QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast,<br> uFlags: UINT): HResult; stdcall;<br> function InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult; stdcall;<br> function GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;<br> pszName: LPSTR; cchMax: UINT): HResult; stdcall;<br>end;<br><br>const<br><br> Class_ContextMenu: TGUID = '{19741013-C829-11D1-8233-0020AF3E97A0}';<br><br>{全局唯一标识符(GUID)是一个16字节(128为)的值,它唯一地标识一个接口(interface)}<br>var<br> FileList:TStringList;<br><br><br>implementation<br><br>uses ComServ, SysUtils, ShellApi, Registry,UnitForm;<br><br>function TContextMenu.SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;<br> hKeyProgID: HKEY): HResult;<br>var<br> StgMedium: TStgMedium;<br> FormatEtc: TFormatEtc;<br> FileNumber,i:Integer;<br>begin<br> file://如/果lpdobj等于Nil,则本调用失败<br> if (lpdobj = nil) then begin<br> Result := E_INVALIDARG;<br> Exit;<br> end;<br><br> file://首/先初始化并清空FileList以添加文件<br> FileList:=TStringList.Create;<br> FileList.Clear;<br> file://初/始化剪贴版格式文件<br> with FormatEtc do begin<br> cfFormat := CF_HDROP;<br> ptd := nil;<br> dwAspect := DVASPECT_CONTENT;<br> lindex := -1;<br> tymed := TYMED_HGLOBAL;<br> end;<br> Result := lpdobj.GetData(FormatEtc, StgMedium);<br><br> if Failed(Result) then Exit;<br><br> file://首/先查询用户选中的文件的个数<br> FileNumber := DragQueryFile(StgMedium.hGlobal,$FFFFFFFF,nil,0);<br> file://循/环读取,将所有用户选中的文件保存到FileList中<br> for i:=0 to FileNumber-1 do begin<br> DragQueryFile(StgMedium.hGlobal, i, FFileName, SizeOf(FFileName));<br> FileList.Add(FFileName);<br> Result := NOERROR;<br> end;<br><br> ReleaseStgMedium(StgMedium);<br>end;<br><br>function TContextMenu.QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst,<br> idCmdLast, uFlags: UINT): HResult;<br>begin<br> Result := 0;<br> if ((uFlags and $0000000F) = CMF_NORMAL) or<br> ((uFlags and CMF_EXPLORE) <> 0) then begin<br> // 往Context Menu中加入一个菜单项 ,菜单项的标题为察看位图文件<br> InsertMenu(Menu, indexMenu, MF_STRING or MF_BYPOSITION, idCmdFirst,<br> PChar('文件操作'));<br> // 返回增加菜单项的个数<br> Result := 1;<br> end;<br>end;<br><br>function TContextMenu.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;<br>var<br> frmOP:TForm1;<br>begin<br> // 首先确定该过程是被系统而不是被一个程序所调用<br> if (HiWord(Integer(lpici.lpVerb)) <> 0) then<br> begin<br> Result := E_FAIL;<br> Exit;<br> end;<br> // 确定传递的参数的有效性<br> if (LoWord(lpici.lpVerb) <> 0) then begin<br> Result := E_INVALIDARG;<br> Exit;<br> end;<br><br> file://建/立文件操作窗口<br> frmOP:=TForm1.Create(nil);<br> file://将/所有的文件列表添加到文件操作窗口的列表中<br> frmOP.ListBox1.Items := FileList;<br> Result := NOERROR;<br>end;<br><br><br>function TContextMenu.GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;<br> pszName: LPSTR; cchMax: UINT): HRESULT;<br>begin<br> if (idCmd = 0) then begin<br> if (uType = GCS_HELPTEXT) then<br> {返回该菜单项的帮助信息,此帮助信息将在用户把鼠标<br> 移动到该菜单项时出现在状态条上。}<br> StrCopy(pszName, PChar('点击该菜单项将执行文件操作'));<br> Result := NOERROR;<br> end<br> else<br> Result := E_INVALIDARG;<br>end;<br><br>type<br> TContextMenuFactory = class(TComObjectFactory)<br> public<br> procedure UpdateRegistry(Register: Boolean); override;<br>end;<br><br>procedure TContextMenuFactory.UpdateRegistry(Register: Boolean);<br>var<br> ClassID: string;<br>begin<br> if Register then begin<br> inherited UpdateRegistry(Register);<br> ClassID := GUIDToString(Class_ContextMenu);<br> file://当/注册扩展库文件时,添加库到注册表中<br> CreateRegKey('*/shellex', '', '');<br> CreateRegKey('*/shellex/ContextMenuHandlers', '', '');<br> CreateRegKey('*/shellex/ContextMenuHandlers/FileOpreation', '', ClassID);<br><br> file://如/果操作系统为Windows NT的话<br> if (Win32Platform = VER_PLATFORM_WIN32_NT) then<br> with TRegistry.Create do<br> try<br> RootKey := HKEY_LOCAL_MACHINE;<br> OpenKey('SOFTWARE/Microsoft/Windows/CurrentVersion/Shell Extensions', True);<br> OpenKey('Approved', True);<br> WriteString(ClassID, 'Context Menu Shell Extension');<br> finally<br> Free;<br> end;<br> end<br> else begin<br> DeleteRegKey('*/shellex/ContextMenuHandlers/FileOpreation');<br> inherited UpdateRegistry(Register);<br> end;<br>end;<br><br> <br><br>initialization<br> TContextMenuFactory.Create(ComServer, TContextMenu, Class_ContextMenu,<br> '', 'Context Menu Shell Extension', ciMultiInstance,tmApartment);<br><br>end.<br><br><br> 在OpWindow窗口中加入一个TListBox控件和两个TButton控件,OpWindows.pas的程序清单如下:<br>unit opwindow;<br><br>interface<br><br>uses<br> Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br> ExtCtrls, StdCtrls,shlobj,shellapi,ActiveX;<br><br>type<br> TForm1 = class(TForm)<br> ListBox1: TListBox;<br> Button1: TButton;<br> Button2: TButton;<br> procedure FormCreate(Sender: TObject);<br> procedure FormClose(Sender: TObject; var Action: TCloseAction);<br> procedure Button1Click(Sender: TObject);<br> procedure Button2Click(Sender: TObject);<br> private<br> { Private declarations }<br> public<br> FileList:TStringList;<br> { Public declarations }<br> end;<br><br>var<br> Form1: TForm1;<br><br>implementation<br><br>{$R *.DFM}<br><br>procedure TForm1.FormCreate(Sender: TObject);<br>begin<br> FileList:=TStringList.Create;<br> Button1.Caption :='复制文件';<br> Button2.Caption :='移动文件';<br> Self.Show;<br>end;<br><br>procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);<br>begin<br> FileList.Free;<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br> sPath:string;<br> fsTemp:SHFILEOPSTRUCT;<br> i:integer;<br>begin<br> sPath:=InputBox('文件操作','输入复制路径','c:/windows');<br> if sPath<>''then begin<br> fsTemp.Wnd := Self.Handle;<br> file://设/置文件操作类型<br> fsTemp.wFunc :=FO_COPY;<br> file://允/许执行撤消操作<br> fsTemp.fFlags :=FOF_ALLOWUNDO;<br> for i:=0 to ListBox1.Items.Count-1 do begin<br> file://源/文件全路径名<br> fsTemp.pFrom := PChar(ListBox1.Items.Strings);<br> file://要/复制到的路径<br> fsTemp.pTo := PChar(sPath);<br> fsTemp.lpszProgressTitle:='拷贝文件';<br> if SHFileOperation(fsTemp)<>0 then<br> ShowMessage('文件复制失败');<br> end;<br> end;<br>end;<br><br>procedure TForm1.Button2Click(Sender: TObject);<br>var<br> sPath:string;<br> fsTemp:SHFILEOPSTRUCT;<br> i:integer;<br>begin<br> sPath:=InputBox('文件操作','输入移动路径','c:/windows');<br> if sPath<>''then begin<br> fsTemp.Wnd := Self.Handle;<br> fsTemp.wFunc :=FO_MOVE;<br> fsTemp.fFlags :=FOF_ALLOWUNDO;<br> for i:=0 to ListBox1.Items.Count-1 do begin<br> fsTemp.pFrom := PChar(ListBox1.Items.Strings);<br> fsTemp.pTo := PChar(sPath);<br> fsTemp.lpszProgressTitle:='移动文件';<br> if SHFileOperation(fsTemp)<>0 then<br> ShowMessage('文件复制失败');<br> end;<br> end;<br>end;<br><br>end.<br><br>我在windows右键菜单中加'文件操作'关键是怎样加在文件操作前加图标,象winrar或winzip一样!