当前位置:首页 > 网络编程 > 软件语言 > DELPHI > 利用COM技术实现外壳扩展的属性页

利用COM技术实现外壳扩展的属性页

点击次数:36 次 发布日期:2008-11-09 08:41:51 作者:源代码网
源代码网推荐
广告载入中
  当用户在资源管理器中调用右键菜单时,会显示一个"属性"菜单项,点击属性菜单项会显示一个属性页,用户可以获得甚至修改文件信息。我们可以定制属性页通过实现属性页扩展。如下图所示,本文实现了一个显示wave(波形)文件的信息如声道数等信息的属性页扩展。
源代码网推荐
源代码网推荐   属性页扩展通常是同某类文件相关联的来实现同之相关的操作和信息显示,另外可以同驱动器相关联,我们还可以用属性页扩展来替换控制面板程序的属性页。象其他外壳扩展程序一样,属性页扩展也是以动态连接库形式实现的进程内COM对象。它除了IUnknown接口外还要实现IShellExtInit和IShellPropSheetExt接口。
源代码网推荐
源代码网推荐   建立同文件关联的属性页扩展
源代码网推荐
源代码网推荐   首先,我们用命令File|New...,创建一个ActiveX Library,然后新建一个COM Object,实现的接口为IShellExtInit和IShellPropSheetExt。
源代码网推荐
源代码网推荐   同文件建立关联需要注册属性页,要在注册表中同相应文件对应的表项下添加Shellex/PropertySheetHandlers子键,每增加一个页面就需要注册一个表项,最大可以添加的页面数是24,我们可以用一个扩展实现多个页面。这里我们通过从TComObjectFactory继承类实现的UpdateRegistry实现了注册。

源代码网推荐
源代码网推荐   
源代码网推荐
源代码网推荐   type
源代码网推荐
源代码网推荐     TCXPropSheetFactory=class(TComObjectFactory)
源代码网推荐
源代码网推荐    public
源代码网推荐
源代码网推荐     procedure UpdateRegistry(Register: Boolean); override;
源代码网推荐
源代码网推荐    end;
源代码网推荐
源代码网推荐   procedure TCXPropSheetFactory.UpdateRegistry(Register: Boolean);var
源代码网推荐
源代码网推荐     ClassID: string;
源代码网推荐
源代码网推荐     Str,KeyName : string;begin
源代码网推荐
源代码网推荐     inherited UpdateRegistry(Register);
源代码网推荐
源代码网推荐   if Register then
源代码网推荐
源代码网推荐   begin
源代码网推荐
源代码网推荐     ClassID:=GUIDToString(Class_CXPropSheet);
源代码网推荐
源代码网推荐     with TRegistry.Create do
源代码网推荐
源代码网推荐     try
源代码网推荐
源代码网推荐     RootKey:=HKEY_CLASSES_ROOT;
源代码网推荐
源代码网推荐     OpenKey(’.wav’,TRUE);
源代码网推荐
源代码网推荐     KeyName := ReadString(’’);
源代码网推荐
源代码网推荐    if Keyname = ’’ then
源代码网推荐
源代码网推荐    begin
源代码网推荐
源代码网推荐     WriteString(’’,’WaveFile’);
源代码网推荐
源代码网推荐     OpenKey(’.wav’,TRUE);
源代码网推荐
源代码网推荐     KeyName := ReadString(’’);
源代码网推荐
源代码网推荐    end;
源代码网推荐
源代码网推荐     OpenKey(’’ KeyName ’shellexPropert eetHandlersWav’,TRUE);
源代码网推荐
源代码网推荐     WriteString(’’,Classid);
源代码网推荐
源代码网推荐     finally
源代码网推荐
源代码网推荐     Free;
源代码网推荐
源代码网推荐   end;
源代码网推荐
源代码网推荐   if(Win32Platform=VER_PLATFORM_WIN32_NT)then
源代码网推荐
源代码网推荐   begin
源代码网推荐
源代码网推荐     with TRegistry.Create do
源代码网推荐
源代码网推荐     try
源代码网推荐
源代码网推荐     RootKey:=HKEY_LOCAL_MACHINE;
源代码网推荐
源代码网推荐     OpenKey(’SOFTWAREMicrosoftWindowsCurrentVersionShell Extensions’, True);
源代码网推荐
源代码网推荐     OpenKey(’Approved’, True);
源代码网推荐
源代码网推荐     WriteString(ClassID, ’Wave File Property Sheet’);
源代码网推荐
源代码网推荐     finally
源代码网推荐
源代码网推荐     Free;
源代码网推荐
源代码网推荐     end;
源代码网推荐
源代码网推荐    end;
源代码网推荐
源代码网推荐   end
源代码网推荐
源代码网推荐   else
源代码网推荐
源代码网推荐   删除注册表项....................... end;初始化扩展是通过IShellExtInit实现的,当外壳调用IShellExtInit.Initialize时,它传递一个数据对象包含来文件对应的目录的PIDL标识符。Initialize方法需要从数据对象中提取文件名,并把文件名和PIDL标识符保存起来为了以后使用。
源代码网推荐
源代码网推荐   
源代码网推荐
源代码网推荐   function TCXPropSheet.SEIInitialize(pidlFolder: PItemIDList;
源代码网推荐
源代码网推荐     lpdobj: IDataObject; hKeyProgID: HKEY): HResult;


源代码网推荐
源代码网推荐   var
源代码网推荐
源代码网推荐     StgMedium: TStgMedium;
源代码网推荐
源代码网推荐     FormatEtc: TFormatEtc;
源代码网推荐
源代码网推荐     szFile: array[0..MAX_PATH 1]of Char;
源代码网推荐
源代码网推荐     filecount: integer;begin
源代码网推荐
源代码网推荐     Result:=E_FAIL;
源代码网推荐
源代码网推荐   if(lpdobj=nil)then
源代码网推荐
源代码网推荐   begin
源代码网推荐
源代码网推荐     Result:=E_INVALIDARG;
源代码网推荐
源代码网推荐     messagebox(0, ’1’, ’错误’, mb_ok);
源代码网推荐
源代码网推荐     Exit;
源代码网推荐
源代码网推荐   end;
源代码网推荐
源代码网推荐   with FormatEtc do
源代码网推荐
源代码网推荐   begin
源代码网推荐
源代码网推荐     cfFormat:=CF_HDROP;
源代码网推荐
源代码网推荐     ptd:=nil;
源代码网推荐
源代码网推荐     dwAspect:=DVASPECT_CONTENT;
源代码网推荐
源代码网推荐     lindex:=-1;
源代码网推荐
源代码网推荐     tymed:=TYMED_HGLOBAL;
源代码网推荐
源代码网推荐   end;
源代码网推荐
源代码网推荐   Result:=lpdobj.GetData(FormatEtc, StgMedium);
源代码网推荐
源代码网推荐   if Failed(Result)then
源代码网推荐
源代码网推荐   Exit;
源代码网推荐
源代码网推荐   //如果只有一个文件被选中,获得文件名并保存。
源代码网推荐
源代码网推荐   filecount:=DragQueryFile(stgmedium.hGlobal, $FFFFFFFF, nil, 0);
源代码网推荐
源代码网推荐   if filecount=1 then
源代码网推荐
源代码网推荐   begin
源代码网推荐
源代码网推荐     Result:=NOERROR;
源代码网推荐
源代码网推荐     DragQueryFile(stgmedium.hGlobal, 0, szFile, SizeOf(szFile)); 软件开发网 www.mscto.com
源代码网推荐
源代码网推荐     FFilename:=strpas(szFile);
源代码网推荐
源代码网推荐   end;
源代码网推荐
源代码网推荐   ReleaseStgMedium(StgMedium);end;添加页面的操作是通过IShellPropSheetExt接口来实现的。如果属性页是和文件相关联,外壳会调用IShellPropSheetExt.AddPages给属性页添加一个页面。如果属性页同控制面板程序相关联,外壳调用IShellPropSheetExt.ReplacePage来替换页面。
源代码网推荐
源代码网推荐   IShellPropSheetExt.AddPages方法有两个参数,lpfnAddPage是一个指向AddPropSheetPageProc回调函数的指针,回调函数用来提供要添加的页面信息给外壳。lParam是一个用户自定义的值,这里我们用它来返回给回调函数对象。
源代码网推荐
源代码网推荐   一般的IShellPropSheetExt.AddPages方法实现步骤是:
源代码网推荐
源代码网推荐   给PROPSHEETPAGE结构设定正确的值,特别是:
源代码网推荐
源代码网推荐   把扩展的对象引用记数变量付值给pcRefParent成员,这可以防止页面还在显示时,扩展对象被卸载。
源代码网推荐
源代码网推荐   实现PropSheetPageProc回调函数来处理页面创建和销毁的情况。
源代码网推荐
源代码网推荐   调用CreatePropertySheetPage函数来创建页面。
源代码网推荐
源代码网推荐   调用lpfnAddPage指向的函数来来添加创建好的页面。
源代码网推荐
源代码网推荐   function TCXPropSheet.AddPages(lpfnAddPage: TFNADDPROPSHEETPAGE;


源代码网推荐
源代码网推荐   lParam: LPARAM): HResult;var
源代码网推荐
源代码网推荐   PSP: TPropSheetPage;
源代码网推荐
源代码网推荐   HPSP: HPropSheetPage;begin
源代码网推荐
源代码网推荐   result:=E_FAIL;
源代码网推荐
源代码网推荐   try
源代码网推荐
源代码网推荐   psp.dwSize:=SizeOf(psp);
源代码网推荐
源代码网推荐   psp.dwFlags:=PSP_USEREFPARENT or PSP_USETITLE or PSP_USECALLBACK;
源代码网推荐
源代码网推荐   psp.hInstance:=hInstance;
源代码网推荐
源代码网推荐   //这里我们使用了事先储存在wave.res中的对话框模板,模板是用delphi5自带的
源代码网推荐
源代码网推荐   //resource workshop编辑的,使用delphi5inrcc32.exe编译的。
源代码网推荐
源代码网推荐   psp.pszTemplate:=MakeIntResource(100);
源代码网推荐
源代码网推荐   //标题名
源代码网推荐
源代码网推荐   psp.pszTitle:=’波文件信息’;
源代码网推荐
源代码网推荐   //设定回调函数
源代码网推荐
源代码网推荐   psp.pfnDlgProc:=@DialogProc;
源代码网推荐
源代码网推荐   psp.pfnCallBack:=@PropCallback;
源代码网推荐
源代码网推荐   //设定对象引用记数变量
源代码网推荐
源代码网推荐   psp.pcRefParent:=@comserver.objectcount;
源代码网推荐
源代码网推荐   //用lParam向回调函数传递对象
源代码网推荐
源代码网推荐   psp.lParam:=integer(self);
源代码网推荐
源代码网推荐   HPSP:=CreatePropertySheetPage(psp);
源代码网推荐
源代码网推荐   if HPSP$#@60;$#@62;nil then begin
源代码网推荐
源代码网推荐   if not lpfnAddPage(HPSP, lParam)then begin
源代码网推荐
源代码网推荐   DestroyPropertySheetPage(HPSP);
源代码网推荐
源代码网推荐   end else begin
源代码网推荐
源代码网推荐   _addref;//增加引用记数,否则一脱离这个方法的作用域,delphi自动释放对象。
源代码网推荐
源代码网推荐   result:=S_OK;
源代码网推荐
源代码网推荐   end
源代码网推荐
源代码网推荐   end
源代码网推荐
源代码网推荐   except
源代码网推荐
源代码网推荐   on e: exception do begin
源代码网推荐
源代码网推荐   e.message:=’添加页面’ e.message;
源代码网推荐
源代码网推荐   messagebox(0, pchar(e.message), ’错误’, mb_ok);
源代码网推荐
源代码网推荐   end;
源代码网推荐
源代码网推荐   end;end;
源代码网推荐
源代码网推荐   function TCXPropSheet.ReplacePage(uPageID: UINT;
源代码网推荐
源代码网推荐   lpfnReplaceWith: TFNADDPROPSHEETPAGE; lParam: LPARAM): HResult;begin
源代码网推荐
源代码网推荐   Result:=E_NOTIMPL;//同文件关联时,外壳不调用ReplacePage,所以不用实现end;回调函数处理属性页的消息,主要要响应WM_INITDIALOG消息来初始化页面显示信息,响应WM_COMMAND消息来处理用户交互,响应WM_NOTIFY消息来处理页面切换或关闭后处理操作结果。
源代码网推荐
源代码网推荐   
源代码网推荐
源代码网推荐   function DialogProc(hwndDlg: HWnd; Msg: UINT; wParam: wParam;
源代码网推荐
源代码网推荐   lParam: LPARAM): Bool; stdcall;
源代码网推荐
源代码网推荐   var
源代码网推荐
源代码网推荐     PageObj: TCXPropSheet;
源代码网推荐
源代码网推荐     filename: string;
源代码网推荐
源代码网推荐     displayName : string;
源代码网推荐
源代码网推荐     SheetHWnd: HWnd;
源代码网推荐
源代码网推荐   begin
源代码网推荐
源代码网推荐     result:=false;
源代码网推荐
源代码网推荐     try
源代码网推荐
源代码网推荐     if Msg=WM_INITDIALOG then begin//初始化界面
源代码网推荐
源代码网推荐   //获得lparam传递过来的对象
源代码网推荐
源代码网推荐     pageObj:=TCXPropSheet(PPropSheetPage(lParam)^.lParam);
源代码网推荐
源代码网推荐   //保存对象信息
源代码网推荐
源代码网推荐     SetWindowLong(hwndDlg, DWL_USER, integer(pageObj));
源代码网推荐
源代码网推荐   //设置界面显示波文件信息
源代码网推荐
源代码网推荐     SetDlgItemText(hwndDlg, 100, PChar(ExtractFileName(PageObj.FFileName)));
源代码网推荐
源代码网推荐     OpenMedia(PageObj.FFileName);
源代码网推荐
源代码网推荐   SetDlgItemText(hwndDlg, 101, PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_AVGBYTESPERSEC))));
源代码网推荐
源代码网推荐   SetDlgItemText(hwndDlg, 102, PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_BITSPERSAMPLE))));
源代码网推荐
源代码网推荐   SetDlgItemText(hwndDlg, 103, PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_CHANNELS))));
源代码网推荐
源代码网推荐   CloseMedia;
源代码网推荐
源代码网推荐     SetWindowLong(hwndDlg, DWL_MSGRESULT, 0);
源代码网推荐
源代码网推荐     Result:=TRUE;
源代码网推荐
源代码网推荐   end
源代码网推荐
源代码网推荐   else if(Msg=WM_COMMAND)then begin
源代码网推荐
源代码网推荐   if Lo(wParam)=110 then//用户点击了关于按钮(id=110)
源代码网推荐
源代码网推荐     MessageBox(0,’作者:hubdog’ #13#10 ’email:hubdog@263.net’,’关于...’,MB_OK);
源代码网推荐
源代码网推荐   end else if(msg=WM_NOTIFY)then begin
源代码网推荐
源代码网推荐     sheetHwnd:=getparent(hwndDlg);//获得属性页的窗口句柄
源代码网推荐
源代码网推荐     case PNMHdr(lparam)^.code of
源代码网推荐
源代码网推荐   //页面失去焦点
源代码网推荐
源代码网推荐     PSN_KILLACTIVE:
源代码网推荐
源代码网推荐   begin
源代码网推荐
源代码网推荐     SetWindowLong(hwndDlg, DWL_MSGRESULT, 0);
源代码网推荐
源代码网推荐     Result:=TRUE;
源代码网推荐
源代码网推荐   end;
源代码网推荐
源代码网推荐   end;
源代码网推荐
源代码网推荐   end;
源代码网推荐
源代码网推荐     except
源代码网推荐
源代码网推荐     on e: exception do begin
源代码网推荐
源代码网推荐     e.message:=’回调处理’ e.message;
源代码网推荐
源代码网推荐     messagebox(0, pchar(e.message), ’错误’, mb_ok);
源代码网推荐
源代码网推荐   end;
源代码网推荐
源代码网推荐   end;
源代码网推荐
源代码网推荐   end;
源代码网推荐
源代码网推荐   
源代码网推荐
源代码网推荐   建立同驱动器相关联的属性页扩展用
源代码网推荐
源代码网推荐   同上面讲的有两点不同:
源代码网推荐
源代码网推荐   IShellExtInit.Initialize方法传递过来的数据对象包含的驱动器路径可能是CFSTR_MOUNTEDVOLUME格式而不是CF_HDROP格式的。标准驱动器是CF_HDROP格式的,而在NTFS文件系统中映射的远程设备则是CFSTR_MOUNTEDVOLUME格式的。
源代码网推荐
源代码网推荐   注册表项是HKEY_CLASSES_ROOTDriveShellexPropertySheetHandlers子键。
源代码网推荐
源代码网推荐   建立控制面板属性页扩展
源代码网推荐
源代码网推荐   同上面讲的有两点不同:
源代码网推荐
源代码网推荐   控制面板程序调用IShellPropSheetExt.ReplacePage方法来替换页面,它不调用IShellPropSheetExt。AddPages方法。
源代码网推荐
源代码网推荐   注册方式:子键可以在不同位置创建,这依赖于扩展是针对用户还是针对机器的。对用户方式子键是HKEY_CURRENT_USERREGSTR_PATH_CONTROLPANEL,否则子键是HKEY_LOCAL_MACHINEREGSTR_PATH_CONTROLSFOLDER。
源代码网推荐
源代码网推荐   本程序在Delphi5,Win NT 4.0,K6-233系统下调试成功。例子程序可以到http://chaozhi.com/lgc去下载


源代码网推荐

源代码网供稿.
网友评论 (0)
会员中心
网络编程
本站推荐
网络编程之精华