Author: gadamopoulos
Date: Fri Jun  3 19:35:33 2016
New Revision: 71508

URL: http://svn.reactos.org/svn/reactos?rev=71508&view=rev
Log:
[BROWSEUI]
- CExplorerBand: Implement populating the treeview. You can navigate the shell 
namespace but clicking on an item doesn't do anything yet.
- Part of the work submitted by Sylvain Deverre. CExplorerBand::InsertItem was 
rewritten by me to be efficient.
CORE-10838

Modified:
    trunk/reactos/dll/win32/browseui/explorerband.cpp
    trunk/reactos/dll/win32/browseui/explorerband.h

Modified: trunk/reactos/dll/win32/browseui/explorerband.cpp
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/browseui/explorerband.cpp?rev=71508&r1=71507&r2=71508&view=diff
==============================================================================
--- trunk/reactos/dll/win32/browseui/explorerband.cpp   [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/browseui/explorerband.cpp   [iso-8859-1] Fri Jun  3 
19:35:33 2016
@@ -1,4 +1,26 @@
+/*
+ * ReactOS Explorer
+ *
+ * Copyright 2016 Sylvain Deverre <deverre dot sylv at gmail dot com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
 #include "precomp.h"
+#include <commoncontrols.h>
+#include <undocshell.h>
 
 #if 1
 #undef UNIMPLEMENTED
@@ -23,12 +45,267 @@
 
 void CExplorerBand::InitializeExplorerBand()
 {
-
+    // Init the treeview here
+    HRESULT                             hr;
+    LPITEMIDLIST                        pidl;
+    CComPtr<IWebBrowser2>               browserService;
+    SHChangeNotifyEntry                 shcne;
+
+    hr = SHGetDesktopFolder(&pDesktop);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return;
+
+    hr = SHGetFolderLocation(m_hWnd, CSIDL_DESKTOP, NULL, 0, &pidl);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return;
+
+    IImageList * piml;
+    hr = SHGetImageList(SHIL_SMALL, IID_PPV_ARG(IImageList, &piml));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return;
+
+    TreeView_SetImageList(m_hWnd, (HIMAGELIST)piml, TVSIL_NORMAL);
+
+    // Insert the root node
+    HTREEITEM hItem = InsertItem(0, pDesktop, pidl, pidl, FALSE);
+    if (!hItem)
+    {
+        ERR("Failed to create root item\n");
+        return;
+    }
+
+    NodeInfo* pNodeInfo = GetNodeInfo(hItem);
+
+    // Insert child nodes
+    InsertSubitems(hItem, pNodeInfo);
+    TreeView_Expand(m_hWnd, hItem, TVE_EXPAND);
+
+    // Navigate to current folder position
+    //NavigateToCurrentFolder();
+
+    // Register shell notification
+    shcne.pidl = pidl;
+    shcne.fRecursive = TRUE;
+    shellRegID = SHChangeNotifyRegister(
+        m_hWnd,
+        SHCNRF_ShellLevel | SHCNRF_InterruptLevel | SHCNRF_RecursiveInterrupt,
+        SHCNE_DISKEVENTS | SHCNE_RENAMEFOLDER | SHCNE_RMDIR | SHCNE_MKDIR,
+        WM_USER_SHELLEVENT,
+        1,
+        &shcne);
+    if (!shellRegID)
+    {
+        ERR("Something went wrong, error %08x\n", GetLastError());
+    }
+    // Register browser connection endpoint
+    hr = IUnknown_QueryService(pSite, SID_SWebBrowserApp, 
IID_PPV_ARG(IWebBrowser2, &browserService));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return;
+
+    hr = AtlAdvise(browserService, dynamic_cast<IDispatch*>(this), 
DIID_DWebBrowserEvents, &adviseCookie);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return;
+
+    ILFree(pidl);
 }
 
 void CExplorerBand::DestroyExplorerBand()
 {
-
+    HRESULT hr;
+    CComPtr <IWebBrowser2> browserService;
+
+    TRACE("Cleaning up explorer band ...\n");
+
+    hr = IUnknown_QueryService(pSite, SID_SWebBrowserApp, 
IID_PPV_ARG(IWebBrowser2, &browserService));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return;
+
+    hr = AtlUnadvise(browserService, DIID_DWebBrowserEvents, adviseCookie);
+    /* Remove all items of the treeview */
+    RevokeDragDrop(m_hWnd);
+    TreeView_DeleteAllItems(m_hWnd);
+    pDesktop = NULL;
+    hRoot = NULL;
+    TRACE("Cleanup done !\n");
+}
+
+CExplorerBand::NodeInfo* CExplorerBand::GetNodeInfo(HTREEITEM hItem)
+{
+    TVITEM tvItem;
+
+    tvItem.mask = TVIF_PARAM;
+    tvItem.hItem = hItem;
+
+    if (!TreeView_GetItem(m_hWnd, &tvItem))
+        return 0;
+
+    return reinterpret_cast<NodeInfo*>(tvItem.lParam);
+}
+
+// *** notifications handling ***
+BOOL CExplorerBand::OnTreeItemExpanding(LPNMTREEVIEW pnmtv)
+{
+    NodeInfo *pNodeInfo;
+
+    if (pnmtv->action == TVE_COLLAPSE) {
+        if (pnmtv->itemNew.hItem == hRoot)
+        {
+            // Prenvent root from collapsing
+            pnmtv->itemNew.mask |= TVIF_STATE;
+            pnmtv->itemNew.stateMask |= TVIS_EXPANDED;
+            pnmtv->itemNew.state &= ~TVIS_EXPANDED;
+            pnmtv->action = TVE_EXPAND;
+            return TRUE;
+        }
+    }
+    if (pnmtv->action == TVE_EXPAND) {
+        // Grab our directory PIDL
+        pNodeInfo = GetNodeInfo(pnmtv->itemNew.hItem);
+        // We have it, let's try
+        if (pNodeInfo && !pNodeInfo->expanded)
+            if (!InsertSubitems(pnmtv->itemNew.hItem, pNodeInfo)) {
+                // remove subitem "+" since we failed to add subitems
+                TV_ITEM tvItem;
+
+                tvItem.mask = TVIF_CHILDREN;
+                tvItem.hItem = pnmtv->itemNew.hItem;
+                tvItem.cChildren = 0;
+
+                TreeView_SetItem(m_hWnd, &tvItem);
+            }
+    }
+    return FALSE;
+}
+
+// *** Helper functions ***
+HTREEITEM CExplorerBand::InsertItem(HTREEITEM hParent, IShellFolder 
*psfParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort)
+{
+    TV_INSERTSTRUCT                     tvInsert;
+    HTREEITEM                           htiCreated;
+
+    /* Get the attributes of the node */
+    SFGAOF attrs = SFGAO_STREAM | SFGAO_HASSUBFOLDER;
+    HRESULT hr = psfParent->GetAttributesOf(1, &pEltRelative, &attrs);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return NULL;
+
+    /* Ignore streams */
+    if ((attrs & SFGAO_STREAM))
+    {
+        TRACE("Ignoring stream\n");
+        return NULL;
+    }
+
+    /* Get the name of the node */
+    WCHAR wszDisplayName[MAX_PATH];
+    if (!ILGetDisplayNameEx(psfParent, pEltRelative, wszDisplayName, 
ILGDN_INFOLDER))
+    {
+        ERR("Failed to get node name\n");
+        return NULL;
+    }
+
+    /* Get the icon of the node */
+    INT iIcon = SHMapPIDLToSystemImageListIndex(psfParent, pEltRelative, NULL);
+
+    NodeInfo* pChildInfo = new NodeInfo;
+    if (!pChildInfo)
+    {
+        ERR("Failed to allocate NodeInfo\n");
+        return FALSE;
+    }
+
+    // Store our node info
+    pChildInfo->absolutePidl = ILClone(pElt);
+    pChildInfo->relativePidl = ILClone(pEltRelative);
+    pChildInfo->expanded = FALSE;
+
+    // Set up our treeview template
+    tvInsert.hParent = hParent;
+    tvInsert.hInsertAfter = TVI_LAST;
+    tvInsert.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | 
TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
+    tvInsert.item.cchTextMax = MAX_PATH;
+    tvInsert.item.pszText = wszDisplayName;
+    tvInsert.item.iImage = tvInsert.item.iSelectedImage = iIcon;
+    tvInsert.item.cChildren = (attrs & SFGAO_HASSUBFOLDER) ? 1 : 0;
+    tvInsert.item.lParam = (LPARAM)pChildInfo;
+
+    htiCreated = TreeView_InsertItem(m_hWnd, &tvInsert);
+
+    return htiCreated;
+}
+
+BOOL CExplorerBand::InsertSubitems(HTREEITEM hItem, NodeInfo *pNodeInfo)
+{
+    CComPtr<IEnumIDList>                pEnumIDList;
+    LPITEMIDLIST                        pidlSub;
+    LPITEMIDLIST                        entry;
+    SHCONTF                             EnumFlags;
+    HRESULT                             hr;
+    ULONG                               fetched;
+    ULONG                               uItemCount;
+    CComPtr<IShellFolder>               pFolder;
+
+    entry = pNodeInfo->absolutePidl;
+    fetched = 1;
+    uItemCount = 0;
+    EnumFlags = SHCONTF_FOLDERS;
+
+    hr = SHGetFolderLocation(m_hWnd, CSIDL_DESKTOP, NULL, 0, &pidlSub);
+    if (!SUCCEEDED(hr))
+    {
+        ERR("Can't get desktop PIDL !\n");
+        return FALSE;
+    }
+
+    if (!pDesktop->CompareIDs(NULL, pidlSub, entry))
+    {
+        // We are the desktop, so use pDesktop as pFolder
+        pFolder = pDesktop;
+    }
+    else
+    {
+        // Get an IShellFolder of our pidl
+        hr = pDesktop->BindToObject(entry, NULL, IID_PPV_ARG(IShellFolder, 
&pFolder));
+        if (!SUCCEEDED(hr))
+        {
+            ILFree(pidlSub);
+            ERR("Can't bind folder to desktop !\n");
+            return FALSE;
+        }
+    }
+    ILFree(pidlSub);
+
+    // TODO: handle hidden folders according to settings !
+    EnumFlags |= SHCONTF_INCLUDEHIDDEN;
+
+    // Enum through objects
+    hr = pFolder->EnumObjects(NULL,EnumFlags,&pEnumIDList);
+
+    // avoid broken IShellFolder implementations that return null pointer with 
success
+    if (!SUCCEEDED(hr) || !pEnumIDList)
+    {
+        ERR("Can't enum the folder !\n");
+        return FALSE;
+    }
+
+    /* Don't redraw while we add stuff into the tree */
+    SendMessage(WM_SETREDRAW, FALSE, 0);
+    while(SUCCEEDED(pEnumIDList->Next(1, &pidlSub, &fetched)) && pidlSub && 
fetched)
+    {
+        LPITEMIDLIST pidlSubComplete;
+        pidlSubComplete = ILCombine(entry, pidlSub);
+
+        if (InsertItem(hItem, pFolder, pidlSubComplete, pidlSub, FALSE))
+            uItemCount++;
+        ILFree(pidlSubComplete);
+        ILFree(pidlSub);
+    }
+    pNodeInfo->expanded = TRUE;
+
+    /* Now we can redraw */
+    SendMessage(WM_SETREDRAW, TRUE, 0);
+
+    return (uItemCount > 0) ? TRUE : FALSE;
 }
 
 // *** IOleWindow methods ***
@@ -273,8 +550,19 @@
 // *** IWinEventHandler methods ***
 HRESULT STDMETHODCALLTYPE CExplorerBand::OnWinEvent(HWND hWnd, UINT uMsg, 
WPARAM wParam, LPARAM lParam, LRESULT *theResult)
 {
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
+    if (uMsg == WM_NOTIFY)
+    {
+        NMHDR *pNotifyHeader = (NMHDR*)lParam;
+        switch (pNotifyHeader->code)
+        {
+            case TVN_ITEMEXPANDING:
+                *theResult = OnTreeItemExpanding((LPNMTREEVIEW)lParam);
+                break;
+            default:
+                break;
+        }
+    }
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE CExplorerBand::IsWindowOwner(HWND hWnd)

Modified: trunk/reactos/dll/win32/browseui/explorerband.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/browseui/explorerband.h?rev=71508&r1=71507&r2=71508&view=diff
==============================================================================
--- trunk/reactos/dll/win32/browseui/explorerband.h     [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/browseui/explorerband.h     [iso-8859-1] Fri Jun  3 
19:35:33 2016
@@ -1,3 +1,23 @@
+/*
+ * ReactOS Explorer
+ *
+ * Copyright 2016 Sylvain Deverre <deverre dot sylv at gmail dot com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
 #pragma once
 
 #define WM_USER_SHELLEVENT WM_USER+88
@@ -32,14 +52,28 @@
 
     // *** BaseBarSite information ***
     CComPtr<IUnknown> pSite;
-
+    CComPtr<IShellFolder> pDesktop;
+    
     // *** tree explorer band stuff ***
     BOOL fVisible;
     BOOL bFocused;
     DWORD dwBandID;
-
+    HIMAGELIST hImageList;
+    HTREEITEM  hRoot;
+    
+    // *** notification cookies ***
+    DWORD adviseCookie;
+    ULONG shellRegID;
+    
     void InitializeExplorerBand();
     void DestroyExplorerBand();
+
+    BOOL OnTreeItemExpanding(LPNMTREEVIEW pnmtv);
+
+    // *** Helper functions ***
+    NodeInfo* GetNodeInfo(HTREEITEM hItem);
+    HTREEITEM InsertItem(HTREEITEM hParent, IShellFolder *psfParent, 
LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort);
+    BOOL InsertSubitems(HTREEITEM hItem, NodeInfo *pNodeInfo); 
 
 public:
     CExplorerBand();


Reply via email to