今天上午delphi开发遇到了文件PIDL与实际路径转换的方法,漫无目的的搜索了近1小时没什么收获后,认真看了一篇讲PIDL探索的文章,里面一段解决了我的问题:
Delphi深度探索之PItemIDList的基本概念
路径和PIDL之间的相互转换
如何将文件系统的路径转化为外壳形式的PIDL呢?微软公司的文档中记载的标准方式是先获得桌面的IShellFolder 接口,然后把要转化的路径名转化为PWideChar 类型的以null结尾的UNICODE字符串,然后作为参数调用桌面的IShellFolder接口的ParseDisplayName 方法才能获得PIDL。实际应用起来太复杂,不过不要紧,有三个未公开的函数可以帮助我们简化这一功能的实现:
function SHILCreateFromPath(Path: Pointer;PIDL: PItemIDList;
var Attributes: ULONG):HResult; stdcall;
function ILCreateFromPath(Path: Pointer):PItemIDList; stdcall;
function SHSimpleIDListFromPath(Path: Pointer):PItemIDList; stdcall;
SHILCreateFromPath 函数实际上就是对桌面的IShellFolder接口的ParseDisplayName方法进行简单封装,而ILCreateFromPath函数则是对SHILCreateFromPath调用的简单封装,而SHSimpleIDListFromPath函数则实现了整个过程,它们的索引分别是28,157和162。
其中SHSimpleIDListFromPath 相对要快一些,因为它并不校验路径参数的有效性,而SHILCreateFromPath 和ILCreateFromPath 在转化前都要校验路径的有效性。如果提供的路径是无效的,就会返回一个nil。
由于SHSimpleIDListFromPath 不校验路径,所以可以从任何路径获得一个PIDL而不会引起错误,但是有时这个函数返回的PIDL不完全正确,比如用它产生的PIDL来调用SHBrowseForFolder 函数显示浏览对话框的时候,偶尔结果显示的名字和图标是不正确的。
当想从一个绝对PIDL获得一个文件系统路径时,就相对简单多了,有一个公开的函数SHGetPathFromIDList可以实现这一功能,它定义在ShlObj单元中(有AnsiChar和widechar两个版本):
function SHGetPathFromIDList(PIDL: PItemIDList;Path: PAnsiChar): BOOL; stdcall;
function SHGetPathFromIDListW(PIDL: PItemIDList;Path: PWideChar): BOOL; stdcall;
注意:path参数对应的指针应该指向一个可以容纳MAX_PATH+1个字符的缓冲区,以避免越界读写。
显示名称
如果想要获得一个PIDL对应的显示名称,文档中介绍的方法是使用IShellFolder接口的GetDisplayNameOf方法来完成,另外使用SHGetFileInfo API函数也能获得显示名。不过有一个未公开的API调用ILGetDisplayName函数使用起来是最方便的,它实际上就是调用桌面的IShellFolder接口的GetDisplayNameOf 方法,同时调用的标志值为SHGDN_FORPARSING。ILGetDisplayName 函数的索引值为15。不过这个函数不会返回通常的短显示名,而是返回包含了相应路径的长显示名。如果想得到的是短文件名的话,最好使用SHGetFileInfo函数。下面是函数的定义:
function ILGetDisplayName(PIDL: PItemIDList;Name: Pointer): LongBool; stdcall;
下午解决了windows默认共享的问题,最后还是启用administration账户解决问题的;
晚上考虑到ajax传值,考虑到还是要尽量用ajax的交互,最近项目让我对ajax有了更深入的印象,实际项目经历更让我从最开始尽量用form来方便传参的想法改为用ajax提升用户体验