本帖最后由 xinhao1991 于 2014-02-17 13:36:21 编辑

解决方案 »

  1.   

    让 FillTreeView(lpsf, NULL, hParent);
    返回 E:盘 的 hItemEdrive 即:
    HTREEITEM hItemEdrive=FillTreeView(lpsf, NULL, hParent);
    GetTreeCtrl().Expand (hItemEdrive,TVE_EXPAND);//展开“E:”节点
    至于 hItemEdrive 就是 name=“E:” 的item 
      

  2.   

     hItemEdrive 就是 name=“E:” 的item——————关键就是怎么实现这一步????????????
      

  3.   

    看看 你的 FillTreeView(lpsf, NULL, hParent);
      

  4.   

    //树控件节点展开时,加入各个子节点的名称及图标
    void DirTreeView::FillTreeView(LPSHELLFOLDER lpsf, LPITEMIDLIST  lpifq, HTREEITEM  hParent)
    {
        TV_ITEM         tvi;                          // TreeView Item.
        TV_INSERTSTRUCT tvins;                        // TreeView Insert Struct.
        HTREEITEM       hPrev = NULL;                 // Previous Item Added.//
        LPENUMIDLIST    lpe=NULL;
        LPITEMIDLIST    lpi=NULL, lpiTemp=NULL, lpifqThisItem=NULL;
        LPTVITEMDATA    lptvid=NULL;
        LPMALLOC        lpMalloc=NULL;
        ULONG           ulFetched;
        HRESULT         hr;
        char            szBuff[256];
      
    HWND            hwnd=::GetParent(m_hWnd);
    //分配一个shell内存对象
        hr=::SHGetMalloc(&lpMalloc);
        if (FAILED(hr))
           return; //如果成功地分配了空间
        if (SUCCEEDED(hr))
        {
            hr=lpsf->EnumObjects(hwnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &lpe);
            if (SUCCEEDED(hr))
            {
                //枚举出其中的文件夹
                while (S_OK==lpe->Next(1, &lpi, &ulFetched))
                {
                    ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;
    lpsf->GetAttributesOf(1, (LPCITEMIDLIST*) &lpi, &ulAttrs);
    if (ulAttrs & (SFGAO_HASSUBFOLDER | SFGAO_FOLDER))
    {
                      tvi.mask= TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
     //如果有子文件夹
     if (ulAttrs & SFGAO_HASSUBFOLDER)
     {
                            tvi.cChildren=1;
    tvi.mask |= TVIF_CHILDREN;
     }
                         lptvid = (LPTVITEMDATA)lpMalloc->Alloc(sizeof(TVITEMDATA));                     if (!lptvid)
                            goto Done;                         
                         if (!GetName(lpsf, lpi, SHGDN_NORMAL, szBuff))
                            goto Done;    
     
     //所插入项的名称
                         tvi.pszText    = szBuff;                     lpifqThisItem=ConcatPidls(lpifq, lpi);
     
     lptvid->lpi=(LPITEMIDLIST)lpMalloc->
     Alloc(lpi->mkid.cb+sizeof(lpi->mkid.cb));                     CopyMemory((PVOID)lptvid->lpi, (CONST VOID *)lpi, 
     lpi->mkid.cb+sizeof(lpi->mkid.cb));
     
                         GetNormalAndSelectedIcons(lpifqThisItem, &tvi);
       
                         lptvid->lpsfParent=lpsf;
                         lptvid->lpifq=ConcatPidls(lpifq, lpi);                     tvi.lParam = (LPARAM)lptvid;
                        tvins.item         = tvi;
                         tvins.hInsertAfter = hPrev;
                         tvins.hParent      = hParent;
     
     //插入树的节点
     hPrev = GetTreeCtrl().InsertItem(&tvins);   
     }
    lpMalloc->Free(lpifqThisItem);  
    lpifqThisItem=0;
    }
    lpMalloc->Free(lpi); 
    return;
    }         
        }
        else
           return;
    Done: 
        if (lpe)  
            lpe->Release();
        if (lpi && lpMalloc)           
            lpMalloc->Free(lpi);
        if (lpifqThisItem && lpMalloc) 
            lpMalloc->Free(lpifqThisItem);  
        if (lpMalloc) 
            lpMalloc->Release();
    }
      

  5.   


    void CLeftView::FillTreeView(LPSHELLFOLDER lpsf,LPITEMIDLIST lpifq,HTREEITEM hParent)
    {
        TV_ITEM         tvi;                          // TreeView Item.
        TV_INSERTSTRUCT tvins;                        // TreeView Insert Struct.
        HTREEITEM       hPrev = NULL;
    HTREEITEM       hItemEdrive=0;
        LPSHELLFOLDER   lpsf2=NULL;
        LPENUMIDLIST    lpe=NULL;
        LPITEMIDLIST    lpi=NULL, lpiTemp=NULL, lpifqThisItem=NULL;
        LPTVITEMDATA    lptvid=NULL;
        LPMALLOC        lpMalloc=NULL;
        ULONG           ulFetched;
        UINT            uCount=0;
        HRESULT         hr;
        char            szBuff[256];
        HWND            hwnd=::GetParent(m_hWnd);
    CTreeCtrl      &Tree=GetTreeCtrl();       // Allocate a shell memory object. 
        hr=::SHGetMalloc(&lpMalloc);
        if (FAILED(hr))
           return;    if (SUCCEEDED(hr))
        {
            // Get the IEnumIDList object for the given folder.
            hr=lpsf->EnumObjects(hwnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &lpe);        if (SUCCEEDED(hr))
            {
                // Enumerate throught the list of folder and non-folder objects.
                while (S_OK==lpe->Next(1, &lpi, &ulFetched))
                {
                    //Create a fully qualified path to the current item
                    //The SH* shell api's take a fully qualified path pidl,
                    //(see GetIcon above where I call SHGetFileInfo) whereas the
                    //interface methods take a relative path pidl.
                    ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;                // Determine what type of object we have.
                    lpsf->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lpi, &ulAttrs);                if (ulAttrs & (SFGAO_HASSUBFOLDER | SFGAO_FOLDER))
                    {
                       //We need this next if statement so that we don't add things like
                       //the MSN to our tree.  MSN is not a folder, but according to the
                       //shell it has subfolders.
                       if (ulAttrs & SFGAO_FOLDER)
                       {
                          tvi.mask= TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;                      if (ulAttrs & SFGAO_HASSUBFOLDER)
                          {
                             //This item has sub-folders, so let's put the + in the TreeView.
                             //The first time the user clicks on the item, we'll populate the
                             //sub-folders.
                             tvi.cChildren=1;
                             tvi.mask |= TVIF_CHILDREN;
                          }
                            
                          //OK, let's get some memory for our ITEMDATA struct
                          lptvid = (LPTVITEMDATA)lpMalloc->Alloc(sizeof(TVITEMDATA));
                          if (!lptvid)
                             goto Done;  // Error - could not allocate memory.
       
                          //Now get the friendly name that we'll put in the treeview.
                          if (!GetName(lpsf, lpi, SHGDN_NORMAL, szBuff))
                             goto Done; // Error - could not get friendly name.
                          tvi.pszText    = szBuff;
                          tvi.cchTextMax = MAX_PATH;
        
                          lpifqThisItem=ConcatPidls(lpifq, lpi);
          
                          //Now, make a copy of the ITEMIDLIST
                          lptvid->lpi=CopyITEMID(lpMalloc, lpi);
       
                          GetNormalAndSelectedIcons(lpifqThisItem, &tvi);
       
                          lptvid->lpsfParent=lpsf;    //Store the parent folders SF
                          lpsf->AddRef();                      lptvid->lpifq=ConcatPidls(lpifq, lpi);
       
                          tvi.lParam = (LPARAM)lptvid;
       
                          // Populate the TreeVeiw Insert Struct
                          // The item is the one filled above.
                          // Insert it after the last item inserted at this level.
                          // And indicate this is a root entry.
                          tvins.item         = tvi;
                          tvins.hInsertAfter = hPrev;
                          tvins.hParent      = hParent;
       
                          // Add the item to the tree
                          hPrev = Tree.InsertItem(&tvins);
    if(strstr(szBuff,"E:") && !strchr(szBuff,'\\'))
    {
    hItemEdrive=hPrev;
    }
                       }
                       // Free this items task allocator.
                       lpMalloc->Free(lpifqThisItem);  
                       lpifqThisItem=0;
                    }                lpMalloc->Free(lpi);  //Free the pidl that the shell gave us.
                    lpi=0;
                }
            }    }
        else
           return;Done:
     
        if (lpe)  
            lpe->Release();    //The following 2 if statements will only be TRUE if we got here on an
        //error condition from the "goto" statement.  Otherwise, we free this memory
        //at the end of the while loop above.
        if (lpi && lpMalloc)           
            lpMalloc->Free(lpi);
        if (lpifqThisItem && lpMalloc) 
            lpMalloc->Free(lpifqThisItem);      if (lpMalloc) 
            lpMalloc->Release();
    }
    注意:if(strstr(szBuff,"E:") && !strchr(szBuff,'\\'))
    {
    hItemEdrive=hPrev;// 这个就是要返回的
    }
      

  6.   

    首先,感谢老师孜孜不倦的教我,然后,我把这句话加上去后,设置断点执行时发现,本程序初始化,是遍历不到E盘的节点的,如图,只遍历了如上节点,所以,这句话被直接跳过了,“hItemEdrive=hPrev;// 这个就是要返回的”没有被执行,怎么办呢?
      

  7.   

    首先,感谢老师孜孜不倦的教我,然后,我把这句话加上去后,设置断点执行时发现,本程序初始化,是遍历不到E盘的节点的,如图,只遍历了如上节点,所以,这句话被直接跳过了,“hItemEdrive=hPrev;// 这个就是要返回的”没有被执行,怎么办呢?
      

  8.   

    在“计算机”下 吧 ?
    那就要 展开 “计算机”后才能 看到 E:看看 你的 Expend 代码。
      

  9.   

    void DirTreeView::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; LPTVITEMDATA   lptvid;  
    HRESULT        hr;
    LPSHELLFOLDER  lpsf=NULL;

        if ((pNMTreeView->itemNew.state & TVIS_EXPANDEDONCE))
             return;

        lptvid=(LPTVITEMDATA)pNMTreeView->itemNew.lParam;
        if (lptvid)
    {
    hr=lptvid->lpsfParent->BindToObject(lptvid->lpi,
                    0, IID_IShellFolder,(LPVOID *)&lpsf);

    if (SUCCEEDED(hr))
    {
    FillTreeView(lpsf,lptvid->lpifq,pNMTreeView->itemNew.hItem);
    }         
        }
    *pResult = 0;
    }
      

  10.   

    HTREEITEM hItemEdrive=FillTreeView(lpsf, NULL, hParent);这句代码也是运行不成功的,“'=' : cannot convert from 'void' to 'struct _TREEITEM *'”,
    求解释!
      

  11.   

    那就先展开 ‘计算机’
           hParent = GetTreeCtrl().InsertItem(&tvis);//插入根节点
           h_计算机=FillTreeView(lpsf, NULL, hParent);
           GetTreeCtrl().Expand (hParent,TVE_EXPAND);//展开“桌面”节点
     在 FillTreeView 里 先查 ‘计算机’即:
    if(strcmp(szBuff,"计算机")==0)
    {
        h_计算机=hPrev;
    }
    然后再展开 ‘计算机’
      

  12.   

    HTREEITEM hItemEdrive=FillTreeView(lpsf, NULL, hParent);这句代码也是运行不成功的,“'=' : cannot convert from 'void' to 'struct _TREEITEM *'”, 求解释!
      

  13.   

    “'=' : cannot convert from 'void' to 'struct _TREEITEM *'”, 求解释!
    叫你把 void FillTreeView() 改 HTREEITEM FillTreeView() 你没改。
    hItemEdrive=hPrev;// 这个就是要返回的
    即 return hItemEdrive;
      

  14.   

    上面的办法不好。
    我给你写了一段:放在:
          lpsf->Release ();
        }
    后,FillTreeView 就不用改了(改 回去)。
    CTreeCtrl &Tree=GetTreeCtrl(); 
    #if 1
    HTREEITEM hChild=Tree.GetChildItem(hParent);//hParent=桌面
    CString str=Tree.GetItemText(hChild);
    while(str != "计算机")
    {// 查找 '计算机'
        hChild=Tree.GetNextSiblingItem(hChild);
        str=Tree.GetItemText(hChild);
        afxDump << str << "\n";
    }
    // 找到 “计算机”, 展开他
    Tree.Expand(hChild,TVE_EXPAND);
    // 再找 ’E:"
    HTREEITEM hEdrive=Tree.GetChildItem(hChild);// hChild="计算机"
    str=Tree.GetItemText(hEdrive);
    while(str.Find("E:") < 0)
    {// 查找 'E:'
        hEdrive=Tree.GetNextSiblingItem(hEdrive);
        str=Tree.GetItemText(hEdrive);
        afxDump << str << "\n";
    }
    // 找到 “E:”
    Tree.Expand(hEdrive,TVE_EXPAND);
    Tree.Select(hEdrive,TVGN_FIRSTVISIBLE);
    #endif