|
end;
initialization
TShellExComObjectFactory.Create( ComServer, TTShellExecuteHook, Class_TShellExecuteHook,''''TShellExecuteHook'''', ''''ShellExecute hook sample'''', ciMultiInstance, tmApartment);
end.
如果系统中有多个ShellExecuteHook的话,外壳会按照ShellExecuteHook的安装顺序进行调用,如果要想使某个外壳扩展优先运行,可先删除其他扩展然后添加优先扩展,原来的扩展依次放在后面,不过这样做也可能意义不大,因为别人也会这么干。最后,程序运行的结果。

记住ShellExecuteHook并不是一个完善的用于监视系统运行的扩展。它只能监视ShellExecute和ShellExecuteEx的运行,它不能保证记录系统所有的行为。特别是很多情况下外壳并不使用ShellExecute来进行一些常用的操作,比如我们在资源管理器中选择一个文件,然后调用右键菜单的属性命令后,记录器没有记录这个动作,但如果直接调用ShellExecute(如下示)的话,ShellExecuteHook却会正确执行。
ShellExecute(nil, ''''properties'''', ''''foo.txt'''',nil,nil,SW_SHOW);
这说明外壳并不使用ShellExecute函数显示属性对话框。总之一定要谨慎使用这项技术,确保它确实符合工作的需求。
Delphi深度探索之自动完成外壳扩展
作者: 哈巴狗的小窝 来源:希赛网 http://www.csai.cn 2006年01月20日
自动完成简介

大家一定都非常熟悉IE浏览器的地址输入编辑框,它提供了自动完成的功能。自动完成(Auto Complete)功能简化了编辑框的输入功能,它可以根据已经输入的部分字符串进行预测和匹配。图2.7的例子,演示了自动完成可以依据输入的“pro”,给出Pascal的保留字中与其相匹配的字符串列表"procedure"、"program"、"property"。
在利用自动完成功能前,必须要知道自动完成并不是任意版本的Windows都支持,自动完成功能实际上是由Internet Explorer 4.0引入并必须有4.71版及以上的Shell32.dll的支持。很多早期的系统,包括很多安装了IE 4的系统并不支持这项特性,所以使用自动完成功能时必须确保要安装的系统支持这项功能,如果不支持就需要安装IE和集成外壳。
自动完成功能是通过一组COM接口来实现的。这些接口使我们可以连接自动完成到编辑框,添加编辑框可以枚举的字符串列表并配置其显示属性。
1. 自动完成的用途
使用自动完成功能可以增强程序的易用性,它可以节省用户反复输入一些常用字符串的时间,并减少输入错误。它还可以用于部分字符匹配的查找系统,可以用它实现对数据库内容的快速查找。另外,它还支持向浏览器历史、最近运行程序和外壳目录输入等功能中添加自定义的完成列表。
2. 配置自动完成
需要知道的是在Delphi里并没有提供自动完成功能相关COM接口的pascal声明单元。由于一般这类接口在微软都是以C语言的头文件形式提供接口,Delphi不可能及时提供最新的相应的Pascal包装单元。所以为了使用这项功能,本文中额外提供了一个shlintf单元翻译了相应的头文件的声明。下表总结了Shlintf的内容:
COM对象
接 口
CLSID_AutoComplete
IAutoComplete
CLSID_ACLHistory
IAutoComplete2
CLSID_ACListISF
IACList
CLSID_ACLMRU
IACList2
CLSID_ACLMulti
ICurrentWorkingDirectory
IObjMgr
自动完成功能最基本的一个接口就是IAutoComplete接口,它的声明如下:
type IAutoComplete = interface(IUnknown) [SID_IAutoComplete] function Init(hwndEdit: HWND; punkACL: IUnknown; pwszRegKeyPath: PWideChar; pwszQuickComplete: PWideChar): HResult; stdcall; function Enable(fEnable: Boolean): HResult; stdcall; end;
IautoComplete接口有两个方法:Init和Enable。
Init方法用来把IAutoComple接口以及自动完成列表同编辑框相连接。参数pwszRegKeyPath和pwszQuickComplete使得IAutoComplete接口可以按预定义的格式扩展部分输入的字符串,快捷键为CTRL+ENTER。比如设定pwszQuickComplete为”http://www.%s.cn/”后,当用户输入"csai" 到编辑框,并按下快捷键CTRL+ENTER,编辑框中的文本就会更新为http://www.csai.cn/。
Enable方法是根据fEnable标识来切换自动完成功能的开关状态的。缺省时是激活的。
下图显示了IAutoComplete接口是如何自动完成字符串的,当用户在编辑框中输入字符时,一种可能是最能匹配已经输入字符串的候选字符会被反白显示。

回过头再来看看Init方法的punkACL参数,它是一个必须的参数而且必须指向一个提供字符串的接口。注意不是我们熟悉的Delphi中提供的TStrings对象,而是一个IEnumString字符串接口。IEnumString接口负责生成一个用于自动完成的候选字符串列表。除了IEnumString接口外,punkACL参数还可以是IACList和IACList2等其他接口。
IACList接口简单地说就是可以对候选字符串分类来改善自动完成的效率,本文中将不加介绍。
要注意的是Microsoft并没有停止对自动完成功能的改进,在Internet Explorer 5.0中,Microsoft 还提供了IAutoComplete2接口。IAutoComplete2接口进行了进一步的扩展,它使得我们可以设定一系列的选项来设定自动完成的可视化表达以及操作。下面是 IAutoComplete2接口的声明:
type IAutoComplete2 = interface(IAutoComplete) [SID_IAutoComplete2] function SetOptions(dwFlag: DWORD): HResult; stdcall; function GetOptions(out dwFlag: DWORD):HResult; stdcall; end;
IAutoComplete2接口引入了两种新的方法,这两种方法使用同样的标识组合作为参数,下表列出了可用的标识及其意义。
标 识
说 明
ACO_NONE
不使用自动完成
ACO_AUTOSUGGEST
使用下拉列表
ACO_AUTOAPPEND
允许自动附加在init方法中pwszQuickComplete参数所代表的字符串
ACO_SEARCH
在下拉列表最后添加"查找"文本
ACO_FILTERPREFIXES
防止自动完成匹配常用前缀比如"www.", "http://"等
ACO_USETAB
TAB键可以用来选择下拉列表项
ACF_UPDOWNKEYDROPSLIST
上下按键可以用来调出下拉列表框
ACO_RTLREADING
按由右到左的顺序读
就像下图所显示的那样,IAutoComplete2同IAutoComplete的显示方式有一点不同,就是因为IAutoComplete2支持不同的显示模式,这些模式可以通过SetOptions 方法来设定。

3. 实现自动完成
自动完成功能是通过COM对象来实现的,下面代码用As操作符来获得IAutoComplete2接口:
FAutoComplete := CreateComObject(CLSID_AutoComplete) as IAutoComplete2;
获得接口后我们就可以实现自动完成功能了,下面代码是一个简单的例子:
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ShlIntf, ActiveX, ComObj, StdCtrls, StrTools; type TAutoCompleteForm = class(TForm) CompletionEdit: TEdit; CompletionLabel: TLabel; SourceGroupBox: TGroupBox; SourceMemo: TMemo; procedure FormCreate(Sender: TObject); private FAutoComplete: IAutoComplete2; FStrings: IUnknown; end; var AutoCompleteForm: TAutoCompleteForm; implementation {$R *.DFM} { TAutoCompleteForm } procedure TAutoCompleteForm.FormCreate(Sender: TObject); begin FAutoComplete := CreateComObject(CLSID_AutoComplete) as IAutoComplete2; FStrings := TEnumString.Create(SourceMemo.Lines) as IUnknown;
OleCheck(FAutoComplete.SetOptions(ACO_AUTOSUGGESTor ACO_UPDOWNKEYDROPSLIST));
OleCheck(FAutoComplete.Init(CompletionEdit.Handle, FStrings, nil, nil)); end; end.
上面的例程首先获得IAutoComplete2接口,如果系统不支持IAutoComplete2接口,as操作符将引发EinvalidCastError异常。接下来的一行代码会创建一个TEnumString类的实例并取得IUnknown接口,这个接口将作为FAutoComplete的Init方法的punkACL参数,TEnumString类是从TInterfacedObject类继承的,实现在StrTools单元中,实现它的目的是使TStrings类同IEnumString接口兼容。然后,设定显示选项使自动完成支持下拉列表和自动建议。最后初始化FAutoComplete并同编辑框相连接,被连接的编辑框就支持自动完成了。
4. 标准自动完成列表
除了支持标准的编辑框的自动完成,Microsoft还允许通过下表中的一组COM对象来存取标准自动完成列表。
COM对象
说 明
CLSID_History
允许存取历史列表项
CLSID_ACListISF
允许操作外壳命名空间的内容
CLSID_MRU
提供最近运行过的程序列表
上面列出的COM对象提供了一个IUnknown接口,接口可以作为IAutoComplete接口的Init方法的punkACL参数。每个IUnknown接口都支持IEnumString和IACList接口,同时还支持其他特殊接口。比如,外壳空间的IUnknown接口还公开了ICurrentWorkingDirectory和IPersistFolder接口。使用这些对象可以根据外壳空间的变化动态地改变候选字符串列表。
ICurrentWorkingDirectory和IPersistFolder接口的区别在于IPersistFolder使用item lists 而不是字符串。Item lists 便于存取虚拟文件夹比如控制面板。
下面的代码演示了如何使用自动完成功能来设定C:\下的外壳内容为候选字符串列表:
var WorkingDirectory: ICurrentWorkingDirectory; begin FAutoComplete := CreateComObject(CLSID_AutoComplete) as IAutoComplete2; FStrings := CreateComObject( 上一页 [1] [2] [3] 下一页 |