单中增添菜单项的。如果系统中安装了
winzip,那么当用右键单击一个名为windows的文件(夹)时,其上下文相关菜单就会有一个名为add to windows.zip的菜单项。
本文要实现的context menu handler与winzip提供的上下文菜单相似。它将在任意类型的文件对象的上下文相关菜单中添加一个
文件操作菜单项,当点击该项后,接口
程序就会弹出一个文件操作窗口,执行文件拷贝、移动等操作。
编写context menu handler必须实现ishellextinit、icontextmenu和tcomobjectfactory三个接口。ishellextinit实现
接口的初始化,icontextmenu接口对象实现上下文相关菜单,icomobjectfactory接口实现对象的创建。
下面来介绍具体的
程序实现。首先在delphi中点击菜单的 file|new 项,在new item窗口中选择dll建立一个dll工程文件。
然后点击菜单的 file|new 项,在new item窗口中选择unit建立一个unit文件,点击点击菜单的 file|new 项,在new item窗口
中选择form建立一个新的窗口。将将工程文件保存为contextmenu.dpr ,将unit1保存为contextmenuhandle.pas,将form保存为
opwindow.pas。
contextmenu.dpr的
程序清单如下:
library contextmenu;
uses
comserv,
contextmenuhandle in ''contextmenuhandle.pas'',
opwindow in ''opwindow.pas'' {form2};
exports
dllgetclassobject,
dllcanunloadnow,
dllregisterserver,
dllunregisterserver;
{$r *.tlb}
{$r *.res}
begin
end.
contextmenuhandle的
程序清单如下:
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: puint;
pszname: lpstr; cchmax: uint): hresult; stdcall;
end;
const
class_contextmenu: tguid = ''{19741013-c829-11d1-8233-0020af3e97a0}'';
{全局唯一标识符(guid)是一个16字节(128为)的值,它唯一地标识一个接口(interface)}
var
filelist:tstringlist;
implementation
uses comserv, sysutils, shellapi, registry,unitform;
function tcontextmenu.seiinitialize(pidlfolder: pitemidlist; lpdobj: idataobject;
hkeyprogid: hkey): hresult;
var
stgmedium: tstgmedium;
formatetc: tformatetc;
filenumber,i:integer;
begin
file://如果lpdobj等于nil,则本调用失败
if (lpdobj = nil) then begin
result := e_invalidarg;
exit;
end;
file://首先初始化并清空filelist以添加文件
filelist:=tstringlist.create;
filelist.clear;
file://初始化剪贴版格式文件
with formatetc do begin
cfformat := cf_hdrop;
ptd := nil;
dwaspect := dv
aspect_content;
lindex := -1;
tymed := tymed_hglobal;
end;
result := lpdobj.getdata(formatetc, stgmedium);
if failed(result) then exit;
file://首先
查询用户选中的文件的个数
filenumber := dragqueryfile(stgmedium.hglobal,$ffffffff,nil,0);
file://循环读取,将所有用户选中的文件保存到filelist中
for i:=0 to filenumber-1 do begin
dragqueryfile(stgmedium.hglobal, i, ffilename, sizeof(f