Delphi 中可以操纵 SHELL 吗? (20分)

  • 主题发起人 主题发起人 lwluser
  • 开始时间 开始时间
L

lwluser

Unregistered / Unconfirmed
GUEST, unregistred user!
Delphi 可像 VC 一样操纵 SHELL 吗?比如如查找、运行?
能不能举个例子说明一下,先谢过!
 
可以啊,你可以看看陈省的《Delphi深度探索》。里面有专门一章讲Shell应用的,很详细的
。我贴他网站的一篇文章,希望对你有效:
Delphi深度探索-用外壳接口对系统进行管理
  如果你喜欢惊喜的话,那么随IE 4.01及其以上版本安装的Microsoft Shell Controls and Automation COM对象无疑就是一大惊喜。这个COM对象提供了一系列的功能强大的方法包括打开、浏览文件夹,最小化、还原、级联和平铺系统中打开的窗口,启动控制面板程序,显示系统对话框等等功能。


  1.安装Shell Controls and Automation 对象

  在Delphi中选Project Import Type Library命令,在对话框中选Import Microsoft Shell Controls And Automation类型库(见下图2.18),点Install后,在Delphi的ActiveX控件板上就多了TShellFolderItem,TShellLinkObject,TShellFolderView,TShell,TSearchCommand等几个组件。


  图2.18

  其中TShell组件就是COM对象的核心,先让我们来简单的看看TShell组件都能干些什么来小小的兴奋一下。新建一个项目,在窗体上放置一个TShell组件,然后再放一个按钮,在按钮的OnClick事件中写下下面代码:

procedure TForm1.Button1Click(Sender: TObject);

begin

Shell1.FileRun;

end;

运行后,按下按钮后就会显示一个对话框,见下图2.19:



图2.19
  很眼熟啊,这不就是前面我们费了半天劲使用那些丑陋的未公开的函数调用出来的系统运行对话框吗,现在使用Shell组件,只用一行代码就搞定了,真是很棒吧,还等什么,就让我们来看看TShell组件还提供了些什么好东西吧。下面是TShell组件的定义:

TShell = class(TOleServer)

private

FIntf: IShellDispatch;

{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}

FProps: TShellProperties;

function GetServerProperties: TShellProperties;

{$ENDIF}

function GetDefaultInterface: IShellDispatch;

protected

procedure InitServerData; override;

function Get_Application: IDispatch;

function Get_Parent: IDispatch;

public

constructor Create(AOwner: TComponent); override;

destructor Destroy; override;

procedure Connect; override;

procedure ConnectTo(svrIntf: IShellDispatch);

procedure Disconnect; override;

function NameSpace(vDir: OleVariant): Folder;

function BrowseForFolder(Hwnd: Integer; const Title: WideString; Options: Integer): Folder; overload;

function BrowseForFolder(Hwnd: Integer; const Title: WideString; Options: Integer;

RootFolder: OleVariant): Folder; overload;

function Windows: IDispatch;

procedure Open(vDir: OleVariant);

procedure Explore(vDir: OleVariant);

procedure MinimizeAll;

procedure UndoMinimizeALL;

procedure FileRun;

procedure CascadeWindows;

procedure TileVertically;

procedure TileHorizontally;

procedure ShutdownWindows;

procedure Suspend;

procedure EjectPC;

procedure SetTime;

procedure TrayProperties;

procedure Help;

procedure FindFiles;

procedure FindComputer;

procedure RefreshMenu;

procedure ControlPanelItem(const szDir: WideString);

property DefaultInterface: IShellDispatch read GetDefaultInterface;

property Application: IDispatch read Get_Application;

property Parent: IDispatch read Get_Parent;

published

{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}

property Server: TShellProperties read GetServerProperties;

{$ENDIF}

end;

  其中ControlPanelItem方法可以根据输入的控制面板程序文件名调用相应的程序,用法如下: //调用Internet 选项设定面板

  Shell1.ControlPanelItem('INETCPL.cpl');

  FindFiles和FindComputer方法调用的结果就是显示查找文件和查找电脑对话框,而Help方法是调出系统帮助,其他方法顾名思义比如MinimizeAll就是最小化全部打开的窗口,UndoMinimizeAll显然就是还原全部窗口的状态了,CascadeWindows是级联式排布窗口,而TileVertically和TileHorizontally则是垂直和水平平铺窗口,不过我运行的效果不怎么样,感觉桌面上的窗口一片混乱,不知道是为什么?调用ShutdownWindows方法后会显示关机对话框,而运行Suspend方法后将会把系统挂起,EjectPC命令一般电脑并不支持,这里就不讨论了,SetTime命令则会调出时间设置对话框,而TrayProperties则会调出下图2.20所示意的任务栏属性对话框(这可是用未公开的对话框函数无法调出的系统对话框啊)。


图2.20

  接下来的方法就稍微复杂些了,其中Open方法可以用来打开文件夹或文件,用法如下:

Shell1.Open('c:/FRUNLOG.TXT');//或 Shell1.Open('c:/');

Expoler方法主要用来调用资源管理器来浏览文件夹,用法如下:

Shell1.Explore('c:/windows');

  Windows方法则会创建并返回一个ShellWindow对象,它代表属于外壳的全部打开的窗口。其实我发现它代表的只是Internet Explorer,下面代码可以返回系统中已经打开的IE窗口数目:

implementation

uses shdocvw;

...

procedure TForm1.Button1Click(Sender: TObject);

var

ShWin:IShellWindows;

begin

ShWin:=Shell1.windows as IShellWindows;

ShowMessage(IntToStr(ShWin.Get_Count));

end;

  进一步的我们甚至可以通过这个接口来完全控制系统中的Internet Explorer,下面代码获得对系统中第一个IE的引用,并返回缺省的主页:

procedure TForm1.Button1Click(Sender: TObject);

var

ShWin:IShellWindows;

Wb:IWebBrowser2;

begin

ShWin:=Shell1.windows as IShellWindows;

Wb:=ShWin.Item(0) as IWebBrowser2;

Wb.GoHome;

end;

  BrowseForFolder用来显示前面外壳对话框中提到的浏览文件夹对话框,其中Hwnd是对话框父窗口的句柄,这个值可以为0。Title是用来设定浏览对话框的标题。Options则可以是0或前文中提到的BIF_xxxx的常数的组合。RootFolder可任选,可以设置为特定的文件夹的路径或特殊文件夹常数值从ssfDESKTOP到ssfPROFILE。用法示意如下:

Shell1.BrowseForFolder(0,'demo',0);

  必须指出的是既然外壳COM对象名为Shell Controls and Automation,它自然也就支持自动化控制,下面就是通过自动化调用它的FileRun方法的例子:

procedure TForm1.Button2Click(Sender: TObject);

var

v:Variant;

begin

v:=CreateOleObject('Shell.Application');

v.filerun;

end;

  此外,它还支持使用脚本语言如Jscript和VBScript进行控制,因此又被称为可脚本化的对象,不过既然本书是关于Delphi的,脚本语言已经超出了本书的范围,这里就不详细介绍了,感兴趣的朋友可以自己查阅相关资料。

  2.Folder对象

  前面提到了TShell组件的全部方法,唯独剩下了NameSpace函数没有介绍,接下来我们就介绍这个可以用来创建Folder对象的方法,它的用法很简单,只要给定一个路径字符串或同特殊文件夹相关的ssfxxx常数就可以了,代码示意如下:

procedure TForm1.Button2Click(Sender: TObject);

var

F:Folder;

begin

F:=Shell1.NameSpace('c:/temp');

end;

  那么获得的Folder对象有什么用呢?Folder对象实际上就代表着一个外壳文件夹对象,我们可以使用Folder对象暴露的方法来获得文件夹的信息,创建子文件夹,移动或复制文件对象到文件夹中。比如下面的代码就实现了移动C:/Scandisk.Log文件到C:/temp目录下:

procedure TForm1.Button2Click(Sender: TObject);

var

F:Folder;

begin

F:=Shell1.NameSpace('c:/temp') as folder ;

F.MoveHere('c:/SCANDISK.LOG',0);

end;

  Folder对象同资源浏览器的文件夹视图是密切相关的,Folder的GetDetailsOf 方法可以返回相应视图的栏目信息。通常来说Column 0 是名字,column 1是文件大小,接着是文件类型和上次修改时间。由于它是同视图相关的,因此对于特殊的文件夹返回的信息是不同的,比如回收站的第二栏就是文件的原始位置。下面代码演示了如果获得相关信息:

var

sFolder:Folder;

sItem:FolderItem;

begin

sFolder:=Shell1.NameSpace('c:/temp');

//获得第一个外壳对象的名字

Edit1.Text:=sFolder.GetDetailsOf(sFolder.Items.Item(0),0);

end;

  Folder对象同时还在Items属性中返回它所包含的外壳对象的集合,大多数情况下这些外壳对象是文件。每个Folder中的外壳对象对应于一个FolderItem对象,它提供了很多属性象Path, Size, ModifyDate 和Type等来获得外壳对象的有用信息以及一堆方法来检验外壳对象是一个联接、标准文件、还是目录或虚拟文件夹。

  下面的例子演示了如何获得外壳对象的路径,当用户点下按钮会显示一个文件夹浏览对话框,用户选择一个文件夹后,文件夹中第一个外壳对象的路径会显示在文本框中。代码如下:

procedure TForm1.Button1Click(Sender: TObject);

var

sFolder:Folder;

sItem:FolderItem;

begin

sFolder:=Shell1.BrowseForFolder(Self.Handle,'选择目录',0,ssfDRIVES);

sItem:=sFolder.Items.Item(0);

Edit1.Text:=sItem.Path;

end;

  还有一个很有用的特性就是可以使用对象的方法来执行外壳对象的上下文相关的菜单命令,或者通过FolderItemVerbs对象获得上下文相关的菜单信息。调用上下文菜单命令非常简单,只需要调用命令的菜单项字符串,然后调用FolderItem的InvokeVerb方法即可

var

Form1: TForm1;

sFolder:Folder;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);

var

I:integer;

Begin

//获得外壳对象的上下文菜单命令字符串

sFolder:=Shell1.NameSpace('c:/temp');

for I:=0 to sFolder.Items.item(0).verbs.Count-1 do

Listbox1.Items.Add(sFolder.Items.Item(0).verbs.Item(i).Name);

end;


procedure TForm1.Button2Click(Sender: TObject);

begin

//执行选中的菜单命令

sFolder.Items.Item(0).InvokeVerb(ListBox1.Items.Strings[ListBox1.ItemIndex]);

end;

运行结果见下图2.21所示:



图2.21
注意,菜单命令中通常有”&”的快捷按键符号,这个符号在调用InvokeVerb时是不能省略的,否则命令不会被调用。

  3.Windows 2000的新特性

  在windows 2000上,Shell对象进一步扩展了对外壳的支持,支持IShellDispatch2和Folder2、FolderItems2等等接口。其中IShellDispatch2接口声明如下:

IShellDispatch2 = interface(IShellDispatch)

['{A4C6892C-3BA9-11D2-9DEA-00C04FB16162}']

function IsRestricted(const Group: WideString; const Restriction: WideString):

Integer; safecall;

procedure ShellExecute(const File_: WideString; vArgs: OleVariant; vDir: OleVariant;

vOperation: OleVariant; vShow: OleVariant); safecall;

procedure FindPrinter(const Name: WideString; const location: WideString;

const model: WideString); safecall;

function GetSystemInformation(const Name: WideString): OleVariant; safecall;

function ServiceStart(const ServiceName: WideString; Persistent: OleVariant):

OleVariant; safecall;

function ServiceStop(const ServiceName: WideString; Persistent: OleVariant):

OleVariant; safecall;

function IsServiceRunning(const ServiceName: WideString): OleVariant; safecall;

function CanStartStopService(const ServiceName: WideString): OleVariant; safecall;

function ShowBrowserBar(const bstrClsid: WideString; bShow: OleVariant):

OleVariant; safecall;

end;

  下表2.10列出了所有新接口方法的说明:

表2.10

方法          功能

CanStartStopService  确定当前用户是否有启动和停止服务的权限。

FindPrinter      在目录服务中查找一个打印机。

GetSystemInformation  获得系统信息。

IsRestricted      当前还没实现。

IsServiceRunning    确定指定名字的服务正在运行。

ServiceStart      根据服务名启动服务。

ServiceStop       停止服务。

ShellExecute      执行命令。

ShowBrowserBar     显示或隐藏浏览器工具条。


①获得接口

  同前面只需要简单地在窗体上放置TShell组件就可以调用IShellDispatch接口的方法不同,IShellDispatch2接口需要从CoShell对象获得,下面代码演示了如何获得IShellDispatch2接口并调用ShellExecute方法打开C:/下的一个文本文件:

implementation

//must include Shell controls and Automation type library unit

uses Shell32_tlb;

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);

var

sShell:IShellDispatch2;

begin

sShell:=CoShell.Create as IShelldispatch2;

sShell.ShellExecute('c:/demo.txt',0,0,'open',SW_SHOW );

end;

  注意:别忘了在uses部分添加对Shell32_tlb单元的引用(就是引入Shell Controls and Automation类型库时,创建的接口单元)。

结论

  Shell组件封装了很多有用的外壳相关的功能,熟练的使用它将使我们的开发变得非常愉快和简单。在本文中,我们简单的探索了一下它的应用潜力,只是涉及到了它的皮毛,很多有趣的接口像IShellDispatch2、IShellLinkDual2等以及Folder2、ShellFolderView、ShellFolderViewOC等对象是本文短小的篇幅所无法涵盖的,感兴趣的朋友可以自行去研究,你越深入,你就越会发现它就像一个大金库一样,内容非常丰富。
-----------------------------------
更详细的内容到http://hubdog.myrice.com/看看吧!
 
接受答案了.
 
后退
顶部