[BROWSEUI]
[reactos.git] / dll / win32 / browseui / addressband.cpp
index 29f04b4..2f5ef7c 100644 (file)
@@ -23,6 +23,18 @@ Implements the navigation band of the cabinet window
 */
 
 #include "precomp.h"
+#include <commoncontrols.h>
+#include <shlwapi_undoc.h>
+#include <shellapi.h>
+
+HRESULT CreateAddressEditBox(REFIID riid, void **ppv);
+
+extern "C"
+HRESULT WINAPI SHGetImageList(
+    _In_   int iImageList,
+    _In_   REFIID riid,
+    _Out_  void **ppv
+    );
 
 /*
 TODO:
@@ -45,6 +57,7 @@ CAddressBand::CAddressBand()
     fGoButton = NULL;
     fComboBox = NULL;
     fGoButtonShown = false;
+    fAdviseCookie = 0;
 }
 
 CAddressBand::~CAddressBand()
@@ -97,43 +110,45 @@ HRESULT STDMETHODCALLTYPE CAddressBand::GetBandInfo(DWORD dwBandID, DWORD dwView
 
 HRESULT STDMETHODCALLTYPE CAddressBand::SetSite(IUnknown *pUnkSite)
 {
+    CComPtr<IBrowserService>                browserService;
+    CComPtr<IOleWindow>                     oleWindow;
     CComPtr<IShellService>                  shellService;
     CComPtr<IUnknown>                       offset34;
     HWND                                    parentWindow;
-    IOleWindow                              *oleWindow;
-    HWND                                    toolbar;
+    HWND                                    combobox;
     static const TBBUTTON                   buttonInfo[] = { {0, 1, TBSTATE_ENABLED, 0} };
     HIMAGELIST                              normalImagelist;
     HIMAGELIST                              hotImageList;
     HINSTANCE                               shellInstance;
     HRESULT                                 hResult;
 
-    fSite.Release();
     if (pUnkSite == NULL)
+    {
+        hResult = AtlUnadvise(fSite, DIID_DWebBrowserEvents, fAdviseCookie);
+        fSite.Release();
         return S_OK;
+    }
+
+    fSite.Release();
 
-    hResult = pUnkSite->QueryInterface(IID_IDockingWindowSite, reinterpret_cast<void **>(&fSite));
+    hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &fSite));
     if (FAILED(hResult))
         return hResult;
 
     // get window handle of parent
     parentWindow = NULL;
-    hResult = pUnkSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
-    if (SUCCEEDED(hResult))
-    {
-        oleWindow->GetWindow(&parentWindow);
-        oleWindow->Release();
-    }
+    hResult = IUnknown_GetWindow(pUnkSite, &parentWindow);
+
     if (!::IsWindow(parentWindow))
         return E_FAIL;
 
     // create combo box ex
-    toolbar = CreateWindowEx(WS_EX_TOOLWINDOW, WC_COMBOBOXEXW, NULL, WS_CHILD | WS_VISIBLE |
-                    WS_CLIPCHILDREN | WS_TABSTOP | CCS_NODIVIDER | CCS_NOMOVEY,
+    combobox = CreateWindowEx(WS_EX_TOOLWINDOW, WC_COMBOBOXEXW, NULL, WS_CHILD | WS_VISIBLE |
+        WS_CLIPCHILDREN | WS_TABSTOP | CCS_NODIVIDER | CCS_NOMOVEY | CBS_OWNERDRAWFIXED,
                     0, 0, 500, 250, parentWindow, (HMENU)0xa205, _AtlBaseModule.GetModuleInstance(), 0);
-    if (toolbar == NULL)
+    if (combobox == NULL)
         return E_FAIL;
-    SubclassWindow(toolbar);
+    SubclassWindow(combobox);
 
     SendMessage(CBEM_SETEXTENDEDSTYLE,
         CBES_EX_CASESENSITIVE | CBES_EX_NOSIZELIMIT, CBES_EX_CASESENSITIVE | CBES_EX_NOSIZELIMIT);
@@ -142,17 +157,22 @@ HRESULT STDMETHODCALLTYPE CAddressBand::SetSite(IUnknown *pUnkSite)
     fComboBox = reinterpret_cast<HWND>(SendMessage(CBEM_GETCOMBOCONTROL, 0, 0));
 #if 1
     hResult = CoCreateInstance(CLSID_AddressEditBox, NULL, CLSCTX_INPROC_SERVER,
-        IID_IAddressEditBox, reinterpret_cast<void **>(&fAddressEditBox));
-    if (FAILED(hResult))
-        return hResult;
+        IID_PPV_ARG(IAddressEditBox, &fAddressEditBox));
 #else
-    // instantiate new version
+    hResult = E_FAIL;
 #endif
+    if (FAILED(hResult))
+    {
+        // instantiate new version
+        hResult = CreateAddressEditBox(IID_PPV_ARG(IAddressEditBox, &fAddressEditBox));
+        if (FAILED(hResult))
+            return hResult;
+    }
 
-    hResult = fAddressEditBox->QueryInterface(IID_IShellService, reinterpret_cast<void **>(&shellService));
+    hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IShellService, &shellService));
     if (FAILED(hResult))
         return hResult;
-    hResult = fAddressEditBox->Init(toolbar, fEditControl, 8, pUnkSite /*(IAddressBand *)this*/ );
+    hResult = fAddressEditBox->Init(combobox, fEditControl, 8, pUnkSite /*(IAddressBand *)this*/);
     if (FAILED(hResult))
         return hResult;
     hResult = shellService->SetOwner(pUnkSite);
@@ -174,12 +194,32 @@ HRESULT STDMETHODCALLTYPE CAddressBand::SetSite(IUnknown *pUnkSite)
         0, 0, 0, 0, m_hWnd, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
     SendMessage(fGoButton, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
     SendMessage(fGoButton, TB_SETMAXTEXTROWS, 1, 0);
-    SendMessage(fGoButton, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(normalImagelist));
-    SendMessage(fGoButton, TB_SETHOTIMAGELIST, 0, reinterpret_cast<LPARAM>(hotImageList));
+    if (normalImagelist)
+        SendMessage(fGoButton, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(normalImagelist));
+    if (hotImageList)
+        SendMessage(fGoButton, TB_SETHOTIMAGELIST, 0, reinterpret_cast<LPARAM>(hotImageList));
     SendMessage(fGoButton, TB_ADDSTRINGW,
         reinterpret_cast<WPARAM>(_AtlBaseModule.GetResourceInstance()), IDS_GOBUTTONLABEL);
     SendMessage(fGoButton, TB_ADDBUTTONSW, 1, (LPARAM)&buttonInfo);
 
+    IImageList * piml;
+    HRESULT hr = SHGetImageList(SHIL_SMALL, IID_PPV_ARG(IImageList, &piml));
+    if (FAILED_UNEXPECTEDLY(hr))
+    {
+        SendMessageW(combobox, CBEM_SETIMAGELIST, 0, 0);
+    }
+    else
+    {
+        SendMessageW(combobox, CBEM_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(piml));
+    }
+
+    // take advice to watch events
+    hResult = IUnknown_QueryService(pUnkSite, SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService));
+    if (SUCCEEDED(hResult))
+    {
+        hResult = AtlAdvise(browserService, static_cast<IDispatch *>(this), DIID_DWebBrowserEvents, &fAdviseCookie);
+    }
+
     return hResult;
 }
 
@@ -239,7 +279,7 @@ HRESULT STDMETHODCALLTYPE CAddressBand::QueryStatus(
     CComPtr<IOleCommandTarget>              oleCommandTarget;
     HRESULT                                 hResult;
 
-    hResult = fAddressEditBox->QueryInterface(IID_IOleCommandTarget, reinterpret_cast<void **>(&oleCommandTarget));
+    hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
     if (FAILED(hResult))
         return hResult;
     return oleCommandTarget->QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText);
@@ -272,7 +312,7 @@ HRESULT STDMETHODCALLTYPE CAddressBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg
 
     if (fActivate)
     {
-        hResult = fSite->QueryInterface(IID_IInputObjectSite, reinterpret_cast<void **>(&inputObjectSite));
+        hResult = fSite->QueryInterface(IID_PPV_ARG(IInputObjectSite, &inputObjectSite));
         if (FAILED(hResult))
             return hResult;
         hResult = inputObjectSite->OnFocusChangeIS(static_cast<IDeskBand *>(this), fActivate);
@@ -300,7 +340,7 @@ HRESULT STDMETHODCALLTYPE CAddressBand::OnWinEvent(
             }
             break;
     }
-    hResult = fAddressEditBox->QueryInterface(IID_IWinEventHandler, reinterpret_cast<void **>(&winEventHandler));
+    hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
     if (FAILED(hResult))
         return hResult;
     return winEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
@@ -313,7 +353,7 @@ HRESULT STDMETHODCALLTYPE CAddressBand::IsWindowOwner(HWND hWnd)
 
     if (fAddressEditBox)
     {
-        hResult = fAddressEditBox->QueryInterface(IID_IWinEventHandler, reinterpret_cast<void **>(&winEventHandler));
+        hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
         if (FAILED(hResult))
             return hResult;
         return winEventHandler->IsWindowOwner(hWnd);
@@ -326,7 +366,7 @@ HRESULT STDMETHODCALLTYPE CAddressBand::FileSysChange(long param8, long paramC)
     CComPtr<IAddressBand>                   addressBand;
     HRESULT                                 hResult;
 
-    hResult = fAddressEditBox->QueryInterface(IID_IAddressBand, reinterpret_cast<void **>(&addressBand));
+    hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IAddressBand, &addressBand));
     if (FAILED(hResult))
         return hResult;
     return addressBand->FileSysChange(param8, paramC);
@@ -337,7 +377,7 @@ HRESULT STDMETHODCALLTYPE CAddressBand::Refresh(long param8)
     CComPtr<IAddressBand>                   addressBand;
     HRESULT                                 hResult;
 
-    hResult = fAddressEditBox->QueryInterface(IID_IAddressBand, reinterpret_cast<void **>(&addressBand));
+    hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IAddressBand, &addressBand));
     if (FAILED(hResult))
         return hResult;
     return addressBand->Refresh(param8);
@@ -384,12 +424,107 @@ HRESULT STDMETHODCALLTYPE CAddressBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
     return E_NOTIMPL;
 }
 
+HRESULT STDMETHODCALLTYPE CAddressBand::GetTypeInfoCount(UINT *pctinfo)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE CAddressBand::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE CAddressBand::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
+    LCID lcid, DISPID *rgDispId)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE CAddressBand::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
+    DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+    CComPtr<IBrowserService> isb;
+    CComPtr<IShellFolder> sf;
+    HRESULT hr;
+    INT indexClosed, indexOpen, itemExists, oldIndex;
+    DWORD result;
+    COMBOBOXEXITEMW item;
+    PIDLIST_ABSOLUTE absolutePIDL;
+    LPCITEMIDLIST pidlChild;
+    LPITEMIDLIST pidlPrevious;
+    STRRET ret;
+    WCHAR buf[4096];
+
+    if (pDispParams == NULL)
+        return E_INVALIDARG;
+
+    switch (dispIdMember)
+    {
+    case DISPID_NAVIGATECOMPLETE2:
+    case DISPID_DOCUMENTCOMPLETE:
+
+        oldIndex = SendMessage(m_hWnd, CB_GETCURSEL, 0, 0);
+
+        item.mask = CBEIF_LPARAM;
+        item.iItem = 0;
+        itemExists = SendMessage(m_hWnd, CBEM_GETITEM, 0, reinterpret_cast<LPARAM>(&item));
+        if (itemExists)
+        {
+            pidlPrevious = reinterpret_cast<LPITEMIDLIST>(item.lParam);
+        }
+
+        hr = IUnknown_QueryService(fSite, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &isb));
+        if (FAILED(hr))
+            return hr;
+        isb->GetPidl(&absolutePIDL);
+
+        SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
+
+        sf->GetDisplayNameOf(pidlChild, SHGDN_FORADDRESSBAR | SHGDN_FORPARSING, &ret);
+
+        StrRetToBufW(&ret, pidlChild, buf, 4095);
+
+        indexClosed = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &indexOpen);
+
+        item.mask = CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_TEXT | CBEIF_LPARAM;
+        item.iItem = 0;
+        item.iImage = indexClosed;
+        item.iSelectedImage = indexOpen;
+        item.pszText = buf;
+        item.lParam = reinterpret_cast<LPARAM>(absolutePIDL);
+
+        if (itemExists)
+        {
+            result = SendMessage(m_hWnd, CBEM_SETITEM, 0, reinterpret_cast<LPARAM>(&item));
+
+            if (result)
+            {
+                ILFree(pidlPrevious);
+            }
+        }
+        else
+        {
+            oldIndex = SendMessage(m_hWnd, CBEM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&item));
+
+            if (oldIndex < 0)
+                DbgPrint("ERROR %d\n", GetLastError());
+        }
+
+        SendMessage(m_hWnd, CB_SETCURSEL, oldIndex, 0);
+
+        //fAddressEditBox->SetCurrentDir(index);
+
+        break;
+    }
+    return S_OK;
+}
+
 LRESULT CAddressBand::OnNotifyClick(WPARAM wParam, NMHDR *notifyHeader, BOOL &bHandled)
 {
     if (notifyHeader->hwndFrom == fGoButton)
     {
-        SendMessage(fEditControl, WM_KEYDOWN, 13, 0);
-        SendMessage(fEditControl, WM_KEYUP, 13, 0);
+        fAddressEditBox->ParseNow(0);
+        fAddressEditBox->Execute(0);
     }
     return 0;
 }