第一个问题:不同的地址空间。因为LPITEMIDLIST是在控件里分配的内存。

解决方案 »

  1.   

    但都是同一进程啊,我用IMalloc在Heap上将控件里的Copy出来的啊...
    应该不是VMM的问题吧
      

  2.   

    2:SHGetPathFromIDList(LPCITEMIDLIST pidl,LPSTR pszPath)
      

  3.   

    3:  用Desktop的IShellFolder调用ParseDispayName应该可以得到文件的
    Full ItemIDList .
      

  4.   

    没有更好的方法了吗???这样得到的将with Full path,还要解析我只要Full File Name,有没有现成的接口或方法可以用???我主要是怕自己解析遇到unimagable mistake,最好是Windows的API来Parse这个ITEMIDLIST.
      

  5.   

    3:  用Desktop的IShellFolder调用ParseDispayName应该可以得到文件的
    Full ItemIDList .
      

  6.   

    3
    HRESULT ItemIdListFromPath( LPITEMIDLIST& pidl,LPCSTR szPath)
    //szPath is assumpted MAX_PATH size
    {  
    LPSHELLFOLDER pDesktopFolder;
    OLECHAR       olePath[MAX_PATH];
    ULONG         chEaten;
    ULONG         dwAttributes;
    HRESULT       hr;
    //
    // Get a pointer to the Desktop's IShellFolder interface.
    //
    if (FAILED(SHGetDesktopFolder(&pDesktopFolder))){
    return -1;
    }
    //
    // IShellFolder::ParseDisplayName requires the file name be in
    // Unicode.
    //
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, olePath, MAX_PATH);
    // Convert the path to an ITEMIDLIST.
    hr = pDesktopFolder->ParseDisplayName(NULL,NULL,olePath,&chEaten,
    &pidl,&dwAttributes);
    if (FAILED(hr)){
    // Handle error.
    ::AfxMessageBox (IDS_FAIL_PARSING_PATH);
    }
    // pidl now contains a pointer to an ITEMIDLIST for .\readme.txt.
    // This ITEMIDLIST needs to be freed using the IMalloc allocator
    // returned from SHGetMalloc().
    //release the desktop folder object
    pDesktopFolder->Release();
    return 0;
    }SHParseDisplayName Function--------------------------------------------------------------------------------Translates a Shell namespace object's display name into an item identifier list and returns the attributes of the object. This function is the preferred method to convert a string to a pointer to an item identifier list (PIDL). SyntaxHRESULT SHParseDisplayName(
        PCWSTR pszName,
        IBindCtx *pbc,
        LPITEMIDLIST *ppidl,
        SFGAOF sfgaoIn,
        SFGAOF *psfgaoOut
    );ParameterspszName
    [in]  Pointer to a zero-terminated wide string that contains the display name to parse. 
    pbc
    [in]  Optional bind context that controls the parsing operation. This parameter is normally set to NULL. 
    ppidl
    [out]  Address of a pointer to a variable of type ITEMIDLIST that receives the item identifier list for the object. If an error occurs, then this parameter is set to NULL. 
    sfgaoIn
    [in] ULONG value that specifies the attributes to query. To query for one or more attributes, initialize this parameter with the flags that represent the attributes of interest. For a list of available SFGAO flags, see IShellFolder::GetAttributesOf. 
    psfgaoOut
    [out]  Pointer to a ULONG. On return, those attributes that are true for the object and were requested in sfgaoIn will be set. An object's attribute flags may be zero or a combination of SFGAO flags. For a list of available SFGAO flags, see IShellFolder::GetAttributesOf. 
    Return ValueReturns S_OK if successful, or an error value otherwise. 
    Function InformationStock Implementation shell32.dll version 6.0 or later 
    Custom Implementation No 
    Header shlobj.h 
    Import library shell32.lib 
    Minimum operating systems Windows XP 
      

  7.   

    3
    HRESULT ItemIdListFromPath( LPITEMIDLIST& pidl,LPCSTR szPath)
    //szPath is assumpted MAX_PATH size
    {  
    LPSHELLFOLDER pDesktopFolder;
    OLECHAR       olePath[MAX_PATH];
    ULONG         chEaten;
    ULONG         dwAttributes;
    HRESULT       hr;
    //
    // Get a pointer to the Desktop's IShellFolder interface.
    //
    if (FAILED(SHGetDesktopFolder(&pDesktopFolder))){
    return -1;
    }
    //
    // IShellFolder::ParseDisplayName requires the file name be in
    // Unicode.
    //
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, olePath, MAX_PATH);
    // Convert the path to an ITEMIDLIST.
    hr = pDesktopFolder->ParseDisplayName(NULL,NULL,olePath,&chEaten,
    &pidl,&dwAttributes);
    if (FAILED(hr)){
    // Handle error.
    ::AfxMessageBox (IDS_FAIL_PARSING_PATH);
    }
    // pidl now contains a pointer to an ITEMIDLIST for .\readme.txt.
    // This ITEMIDLIST needs to be freed using the IMalloc allocator
    // returned from SHGetMalloc().
    //release the desktop folder object
    pDesktopFolder->Release();
    return 0;
    }SHParseDisplayName Function--------------------------------------------------------------------------------Translates a Shell namespace object's display name into an item identifier list and returns the attributes of the object. This function is the preferred method to convert a string to a pointer to an item identifier list (PIDL). SyntaxHRESULT SHParseDisplayName(
        PCWSTR pszName,
        IBindCtx *pbc,
        LPITEMIDLIST *ppidl,
        SFGAOF sfgaoIn,
        SFGAOF *psfgaoOut
    );ParameterspszName
    [in]  Pointer to a zero-terminated wide string that contains the display name to parse. 
    pbc
    [in]  Optional bind context that controls the parsing operation. This parameter is normally set to NULL. 
    ppidl
    [out]  Address of a pointer to a variable of type ITEMIDLIST that receives the item identifier list for the object. If an error occurs, then this parameter is set to NULL. 
    sfgaoIn
    [in] ULONG value that specifies the attributes to query. To query for one or more attributes, initialize this parameter with the flags that represent the attributes of interest. For a list of available SFGAO flags, see IShellFolder::GetAttributesOf. 
    psfgaoOut
    [out]  Pointer to a ULONG. On return, those attributes that are true for the object and were requested in sfgaoIn will be set. An object's attribute flags may be zero or a combination of SFGAO flags. For a list of available SFGAO flags, see IShellFolder::GetAttributesOf. 
    Return ValueReturns S_OK if successful, or an error value otherwise. 
    Function InformationStock Implementation shell32.dll version 6.0 or later 
    Custom Implementation No 
    Header shlobj.h 
    Import library shell32.lib 
    Minimum operating systems Windows XP 
      

  8.   

    PathFindFileName
    Searches a path for a file name. LPTSTR PathFindFileName(
        LPCTSTR pPath
        );Parameters
    pPath 
    [in] Pointer to a null-terminated string of maximum length MAX_PATH that contains the path to search. 
    Return Values
    Returns a pointer to the address in the string if successful, or a pointer to the beginning of the path otherwise. 
    Example
    #include <windows.h>
    #include <iostream.h>
    #include "Shlwapi.h"void main( void )
    {
        // Path that contains a file part.
        char buffer_1[ ] = "c:\\path\\file"; 
        char *lpStr1;
        lpStr1 = buffer_1;    cout << "Search for the file in path        " << lpStr1
             << "\nReturns the file part of the path \""
             <<  PathFindFileName(lpStr1) << "\"" << endl;    cout << "\nSearch for the file in path       \"c:\\path\"" << endl;
        cout << "Returns the file part of the path \""
             <<  PathFindFileName("c:\\path") << "\"" << endl;    cout << "\nSearch for the file in path       \"c:\\path\\\"" << endl;
        cout << "Returns the file part of the path \""
             <<  PathFindFileName("c:\\path\\") << "\"" << endl;    cout << "\nSearch for the file in path       \"c:\\\"" << endl;
        cout << "Returns the file part of the path \""
             <<  PathFindFileName("c:\\") << "\"" << endl;    cout << "\nSearch for the file in path       \"c:\"" << endl;
        cout << "Returns the file part of the path \""
             <<  PathFindFileName("c:") << "\"" << endl;    cout << "\nSearch for the file in path       \"path\"" << endl;
        cout << "Returns the file part of the path \""
             <<  PathFindFileName("path") << "\"" << endl;
    }
    OUTPUT:
    ==========
    Search for the file in path        c:\path\file
    Returns the file part of the path "file"Search for the file in path       "c:\path"
    Returns the file part of the path "path"Search for the file in path       "c:\path\"
    Returns the file part of the path "path\"Search for the file in path       "c:\"
    Returns the file part of the path "c:\"Search for the file in path       "c:"
    Returns the file part of the path "c:"Search for the file in path       "path"
    Returns the file part of the path "path"Requirements 
      Version 4.71 and later of Shlwapi.dll  Windows NT/2000: Requires Windows 2000 (or Windows NT 4.0 with Internet Explorer 4.0 or later). 
      Windows 95/98/Me: Requires Windows 98 (or Windows 95 with Internet Explorer 4.0 or later). 
      Header: Declared in Shlwapi.h. 
      Import Library: Shlwapi.lib.
      

  9.   

    你可以用PathFindFileName从全路径中得到文件名嘛。
      

  10.   

    感谢大家。2,3没问题了。
    第一个我是想将OCX中的一个ITEMIDLIST Copy出来,但不知为何上述方法出错???有没有好的解决方法???
    再次感谢。
      

  11.   

    感觉上这个不应该错的,因为控件里的LPSHELLFOLDER都由LPUNKNOWN导出到client,而且works well....
      

  12.   

    // Given a VARIANT, pull out the PIDL using brute force
    LPITEMIDLIST PidlFromVARIANT(LPVARIANT pvarLoc)//&acute;&Oacute;VARIENT±&auml;&Aacute;&iquest;&Ouml;&ETH;&micro;&Atilde;&micro;&frac12;PIDL
    {
    if (pvarLoc){
    if (V_VT(pvarLoc) == (VT_ARRAY|VT_UI1)){
    LPITEMIDLIST pidl = (LPITEMIDLIST)pvarLoc->parray->pvData;
    return pidl;
    }
    }
    return NULL;
    }// Pack a PIDL into a VARIANT
    HRESULT InitVARIANTFromPidl(LPVARIANT pvar, LPITEMIDLIST pidl)//&Ocirc;&Uacute;VARIENT±&auml;&Aacute;&iquest;&Ouml;&ETH;&acute;&aelig;·&Aring;PIDL
    {
    if (!pidl || !pvar) {
    return E_POINTER;
    }
    // Get the size of the pidl and allocate a SAFEARRAY of
    // equivalent size
    UINT cb = ILGetSize(pidl);
    LPSAFEARRAY psa = MakeSafeArrayFromData((LPBYTE)pidl, cb);
    if (!psa){
    VariantInit(pvar);
    return E_OUTOFMEMORY;
    }
    V_VT(pvar) = VT_ARRAY|VT_UI1;
    V_ARRAY(pvar) = psa;
    return NOERROR;
    }// Allocate a SAFEARRAY of cbData size and pack pData into it
    LPSAFEARRAY MakeSafeArrayFromData(LPBYTE pData, DWORD cbData)//°&sup2;&Egrave;&laquo;·&Ouml;&Aring;&auml;cbData&acute;ó&ETH;&iexcl;&micro;&Auml;°&sup2;&Egrave;&laquo;&Ecirc;&yacute;×é&pound;&not;&sup2;&cent;&Ccedil;&Ograve;&acute;&aelig;·&Aring;pData&iexcl;&pound;
    {
    LPSAFEARRAY psa;
    if (!pData || 0 == cbData){
    return NULL;  // nothing to do
    }
    // create a one-dimensional safe array of BYTEs
    psa = SafeArrayCreateVector(VT_UI1, 0, cbData);
    if (psa){
    // copy data into the area in safe array reserved for data
    // Note we party directly on the pointer instead of using locking/
    // unlocking functions.  Since we just created this and no one
    // else could possibly know about it or be using it, this is okay.
    memcpy(psa->pvData,pData,cbData);
    }
    return psa;
    }
      

  13.   

    faint
    中文贴出来也会乱码
      

  14.   

    哎。发现错误是那个CopyPidl函数,他只Copy了一层的ITEMIDLIST连最后的NULL terminate也没有。更改后返回OLE_HANDLE可以工作了。
    还是感谢jiangsheng的大力帮助,Variant方法感觉更加安全些.谢谢!