知识大全 利用COM技术实现外壳扩展的属性页
Posted 属性
篇首语:博学之,审问之,慎思之,明辨之,笃行之。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 利用COM技术实现外壳扩展的属性页相关的知识,希望对你有一定的参考价值。
利用COM技术实现外壳扩展的属性页 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
当用户在资源管理器中调用右键菜单时 会显示一个 属性 菜单项 点击属性菜单项会显示一个属性页 用户可以获得甚至修改文件信息 我们可以定制属性页通过实现属性页扩展 如下图所示 本文实现了一个显示wave(波形)文件的信息如声道数等信息的属性页扩展
属性页扩展通常是同某类文件相关联的来实现同之相关的操作和信息显示 另外可以同驱动器相关联 我们还可以用属性页扩展来替换控制面板程序的属性页 象其他外壳扩展程序一样 属性页扩展也是以动态连接库形式实现的进程内对象 它除了IUnknown接口外还要实现IShellExtInit和IShellPropSheetExt接口
一 建立同文件关联的属性页扩展
首先 我们用命令File|New 创建一个ActiveX Library 然后新建一个 Object 实现的接口为IShellExtInit和IShellPropSheetExt
同文件建立关联需要注册属性页 要在注册表中同相应文件对应的表项下添加Shellex/PropertySheetHandlers子键 每增加一个页面就需要注册一个表项 最大可以添加的页面数是 我们可以用一个扩展实现多个页面 这里我们通过从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+ \\shellex\\Propert eetHandlers\\Wav TRUE);
WriteString( Classid);
finally
Free;
end;
if(Win Platform=VER_PLATFORM_WIN _NT)then
begin
with TRegistry Create do
try
RootKey:=HKEY_LOCAL_MACHINE;
OpenKey( SOFARE\\Microsoft\\Windows\\CurrentVersion\\Shell 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[ MAX_PATH+ ]of Char;
filecount: integer;begin
Result:=E_FAIL;
if(lpdobj=nil)then
begin
Result:=E_INVALIDARG;
messagebox( 错误 mb_ok);
Exit;
end;
with FormatEtc do
begin
cfFormat:=CF_HDROP;
ptd:=nil;
dwAspect:=DVASPECT_CONTENT;
lindex:= ;
tymed:=TYMED_HGLOBAL;
end;
Result:=lpdobj GetData(FormatEtc StgMedium);
if Failed(Result)then
Exit;
//如果只有一个文件被选中 获得文件名并保存
filecount:=DragQueryFile(stgmedium hGlobal $FFFFFFFF nil );
if filecount= then
begin
Result:=NOERROR;
DragQueryFile(stgmedium hGlobal szFile SizeOf(szFile));
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中的对话框模板 模板是用delphi 自带的
//resource workshop编辑的 使用delphi \\bin\\brcc exe编译的
psp pszTemplate:=MakeIntResource( );
//标题名
psp pszTitle:= 波文件信息 ;
//设定回调函数
psp pfnDlgProc:=@DialogProc;
psp pfnCallBack:=@PropCallback;
//设定对象引用记数变量
psp pcRefParent:=@server objectcount;
//用lParam向回调函数传递对象
psp lParam:=integer(self);
HPSP:=CreatePropertySheetPage(psp);
if HPSP$#@ ;$#@ ;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( 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_MAND消息来处理用户交互 响应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 PChar(ExtractFileName(PageObj FFileName)));
OpenMedia(PageObj FFileName);
SetDlgItemText(hwndDlg PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_AVGBYTESPERSEC))));
SetDlgItemText(hwndDlg PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_BITSPERSAMPLE))));
SetDlgItemText(hwndDlg PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_CHANNELS))));
CloseMedia;
SetWindowLong(hwndDlg DWL_MSGRESULT );
Result:=TRUE;
end
else if(Msg=WM_MAND)then begin
if Lo(wParam)= then//用户点击了关于按钮(id= )
MessageBox( 作者:hubdog +# # + email:hubdog@ 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 );
Result:=TRUE;
end;
end;
end;
except
on e: exception do begin
e message:= 回调处理 +e message;
messagebox( pchar(e message) 错误 mb_ok);
end;
end;
end;
二 建立同驱动器相关联的属性页扩展
同上面讲的有两点不同
IShellExtInit Initialize方法传递过来的数据对象包含的驱动器路径可能是CFSTR_MOUNTEDVOLUME格式而不是CF_HDROP格式的 标准驱动器是CF_HDROP格式的 而在NTFS文件系统中映射的远程设备则是CFSTR_MOUNTEDVOLUME格式的
注册表项是HKEY_CLASSES_ROOT\\Drive\\Shellex\\PropertySheetHandlers子键
三 建立控制面板属性页扩展
同上面讲的有两点不同
控制面板程序调用IShellPropSheetExt ReplacePage方法来替换页面 它不调用IShellPropSheetExt AddPages方法
cha138/Article/program/Delphi/201311/25066相关参考
Delphi深度探索之自动完成外壳扩展 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &
重点总结 在ASPNET中要想从目标页获取源页的数据信息可以使用两种方法 一是通过获取源页的控件进而获取控件的属性值 二是直接通过获取源页公开的公共属性来获取源页数据 本示例代码则演示如何
利用JS在asp.net中实现左导航页的隐藏 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nbs
DELPHI中利用对象的常用属性制作动画 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 在DEL
知识大全 asp.net利用NamingContainer属性获取GridView行号的方法
asp.net利用NamingContainer属性获取GridView行号的方法 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内
编写与.NET属性窗口交互的RAD组件(二) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 扩展
透彻掌握ASP分页技术 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 近段时间看了一些论坛上面关
.Net技术开发中两个“属性”引起的歧异 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 对于pr
第步在解决方案上添加一个窗体Form;并添加textBoxtextBoxButton将Button的标题设为确定DialogResult属性设为OK 第步在窗体Form的类代
利用继承技术可方便地为一个接口添加新的方法声明也可以将几个接口合并成一个新接口在这两种情况下最终得到的都是一个新接口如下例所示 //:HorrorShowjava //Extendinga