需要将一些特殊路径转换为PIDL,例如“D:\NUL\CON”,或者转换一个暂时不存在的路径。目前SHSimpleIDListFromPath函数可以实现,但不敢保证在未来版本的windows中可用MSDN上介绍的另一种实现方法:An alternative to this function is as follows: 
1.Call SHGetDesktopFolder to obtain IShellFolder for the desktop folder.
2.Get the IShellFolder's bind context (IBindCtx).
3.Call IShellFolder::ParseDisplayName with the IBindCtx and the path.但是我不知道第二步该怎样操作。英文非常菜,靠Google翻译,所以很多东西读不通也就不知道是怎么回事

解决方案 »

  1.   

    http://support.microsoft.com/kb/132750/zh-tw
      

  2.   

    以下这段代码是无效的,不能把一个不存在的路径或特殊路径转换成PIDL(已存在的路径可以转换),原文中通过lpVtbl变量访问成员函数在Microsoft Visual Studio 2010下通不过。 LPITEMIDLIST  pidl;
    LPSHELLFOLDER pDesktopFolder;
    ULONG         chEaten;
    ULONG         dwAttributes=NULL;
    HRESULT       hr; if (SUCCEEDED(SHGetDesktopFolder(&pDesktopFolder)))
    {
     
    hr = pDesktopFolder->ParseDisplayName(
    NULL,
    NULL,
    L"d:\\nul\\con",
    &chEaten,
    &pidl,
    &dwAttributes);
    if (FAILED(hr))
    {
    // Handle error.
    }
    pDesktopFolder->Release();
    }
    return NULL;
    根据MSDN的描述是要创建一个IBindCtx对象的,对IShellFolder::ParseDisplayName函数第二个参数的说明:原文地址:http://msdn.microsoft.com/en-us/library/windows/desktop/bb775090(v=vs.85).aspxpbc [in] 
    Type: IBindCtx*Optional. A pointer to a bind context used to pass parameters as inputs and outputs to the parsing function. These passed parameters are often specific to the data source and are documented by the data source owners. For example, the file system data source accepts the name being parsed (as a WIN32_FIND_DATA structure), using the STR_FILE_SYS_BIND_DATA bind context parameter. STR_PARSE_PREFER_FOLDER_BROWSING can be passed to indicate that URLs are parsed using the file system data source when possible. Construct a bind context object using CreateBindCtx and populate the values using IBindCtx::RegisterObjectParam. See Bind Context String Keys for a complete list of these.
      

  3.   

    这是我写的LPITEMIDLIST GetItemIDListFromFilePath( String const & strFilePath )
    {
    if ( strFilePath.empty() )
    {
    return NULL;
    } // 得到桌面的目录
    LPSHELLFOLDER pDesktopFolder = NULL;
    HRESULT hr = SHGetDesktopFolder(&pDesktopFolder);
    if ( FAILED(hr) )
    {
    return NULL;
    }
    UnicodeString olestr = StringToUnicode(strFilePath);
    // 得到文件路径对应的ItemIDList
    LPITEMIDLIST pItemIDList = NULL;
    hr = pDesktopFolder->ParseDisplayName( NULL, NULL, (LPOLESTR)&olestr[0], NULL, &pItemIDList, NULL );
    pDesktopFolder->Release();
    if ( FAILED(hr) )
    {
    return NULL;
    }
    return pItemIDList;
    }自己依样画瓢吧。
    还有,为一个不存在的目录获得ITEMIDLIST,这是不能的吧。。你可以先mkdir确保它存在,然后再转。
      

  4.   

    你的代码其实跟我上面的差不多,“d:\mul\con”这种路径仍然获取不到,但是这个路径却是真实存在的,你可以调用shell函数SHSimpleIDListFromPath()试试,它可以获得pidl,不管路径是否存在!
      

  5.   

    我哭了,这个功能真复杂。网上搜不到,只有细细的翻MSDN,总算让我翻到线索了。
    你不给我分真对不起我了。class SimpleFileSysBindData : public IFileSystemBindData

    public:
    SimpleFileSysBindData() : _cRef(1)
    {
    ZeroMemory( &_fd, sizeof(_fd) );
    }
    // *** IUnknown methods ***
    STDMETHODIMP QueryInterface( REFIID riid, void * * ppvObj )
    {
    if ( riid == IID_IFileSystemBindData )
    {
    *ppvObj = static_cast<IFileSystemBindData *>(this);
    AddRef();
    return S_OK;
    }
    else if ( riid == IID_IUnknown )
    {
    *ppvObj = static_cast<IUnknown *>(this);
    AddRef();
    return S_OK;
    }
    return E_NOINTERFACE;
    }
    STDMETHODIMP_(ULONG) AddRef(void)
    {
    return InterlockedIncrement(&_cRef);
    }
    STDMETHODIMP_(ULONG) Release(void)
    {
    LONG cRef = InterlockedDecrement(&_cRef);
    if ( !cRef )
    delete this;
    return cRef;
    }

    // *** IFileSystemBindData Methods ***
    STDMETHODIMP SetFindData( WIN32_FIND_DATAW const * pfd )
    {
    _fd = *pfd;
    return S_OK;
    }
    STDMETHODIMP GetFindData( WIN32_FIND_DATAW * pfd )
    {
    *pfd = _fd;
    return S_OK;
    }
    private:
    ~SimpleFileSysBindData()
    {
    }

    LONG _cRef;
    WIN32_FIND_DATAW _fd;
    };static inline IUnknown * CreateFSBD( void )
    {
    IUnknown *pI = static_cast<IFileSystemBindData *>(new SimpleFileSysBindData);
    return pI;
    }HRESULT GetSimpleIDFromPath( LPWSTR pwszPath, WIN32_FIND_DATAW * pfd, LPITEMIDLIST * ppidl )
    {
    HRESULT hr;
    IUnknown * pI;
    IFileSystemBindData * pfsbd;
    pI = CreateFSBD();
    hr = pI->QueryInterface( IID_IFileSystemBindData, (void * *)&pfsbd );
    pI->Release(); if ( SUCCEEDED(hr) )
    {
    if ( pfd )
    {
    pfsbd->SetFindData(pfd);
    } IBindCtx * pbc;
    hr = CreateBindCtx( 0, &pbc );
    if ( SUCCEEDED(hr) )
    {
    hr = (pbc)->RegisterObjectParam( STR_FILE_SYS_BIND_DATA, pfsbd );
    pfsbd->Release();
    }
    else
    {
    pfsbd->Release();
    return hr;
    } // Get the desktop folder and parse the display name.
    IShellFolder * pFolder;
    hr = SHGetDesktopFolder(&pFolder);
    if ( SUCCEEDED(hr) )
    {
    hr = pFolder->ParseDisplayName( NULL, pbc, (LPOLESTR)pwszPath, NULL, ppidl, NULL );
    } pFolder->Release();
    pbc->Release();
    } return hr;
    }
    LPITEMIDLIST pIDList = NULL;
    HRESULT hr; hr = GetSimpleIDFromPath( L"D:\\nul\\con", NULL, &pIDList );
    printf( "%p\n", pIDList );
    TCHAR szPath[MAX_PATH] = "";
    SHGetPathFromIDList( pIDList, szPath );
    printf( "%s\n", szPath );
    OK