4 * Copyright 2009 Andrew Hill <ash77 at domain reactos.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 This class handles the combo box of the address band.
29 Handle listbox dropdown message and fill contents
30 Add drag and drop of icon in edit box
31 Handle change notifies to update appropriately
32 Fix so selection in combo listbox navigates
35 CAddressEditBox::CAddressEditBox() :
36 fCombobox(NULL
, this, 1),
37 fEditWindow(NULL
, this, 1),
42 CAddressEditBox::~CAddressEditBox()
46 HRESULT STDMETHODCALLTYPE
CAddressEditBox::SetOwner(IUnknown
*)
48 // connect to browser connection point
52 HRESULT STDMETHODCALLTYPE
CAddressEditBox::FileSysChange(long param8
, long paramC
)
57 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Refresh(long param8
)
62 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Init(HWND comboboxEx
, HWND editControl
, long param14
, IUnknown
*param18
)
64 CComPtr
<IBrowserService
> browserService
;
66 fCombobox
.SubclassWindow(comboboxEx
);
67 fEditWindow
.SubclassWindow(editControl
);
70 SHAutoComplete(fEditWindow
.m_hWnd
, SHACF_FILESYSTEM
| SHACF_URLALL
| SHACF_USETAB
);
72 // take advice to watch events
73 HRESULT hResult
= IUnknown_QueryService(param18
, SID_SShellBrowser
, IID_PPV_ARG(IBrowserService
, &browserService
));
74 if (SUCCEEDED(hResult
))
76 hResult
= AtlAdvise(browserService
, static_cast<IDispatch
*>(this), DIID_DWebBrowserEvents
, &fAdviseCookie
);
82 HRESULT STDMETHODCALLTYPE
CAddressEditBox::SetCurrentDir(long paramC
)
87 HRESULT STDMETHODCALLTYPE
CAddressEditBox::ParseNow(long paramC
)
93 PIDLIST_ABSOLUTE pidlCurrent
= NULL
;
94 PIDLIST_RELATIVE pidlRelative
= NULL
;
95 CComPtr
<IShellFolder
> psfCurrent
;
97 CComPtr
<IBrowserService
> pbs
;
98 hr
= IUnknown_QueryService(fSite
, SID_SShellBrowser
, IID_PPV_ARG(IBrowserService
, &pbs
));
99 if (FAILED_UNEXPECTEDLY(hr
))
102 hr
= IUnknown_GetWindow(pbs
, &topLevelWindow
);
103 if (FAILED_UNEXPECTEDLY(hr
))
106 /* Get the path to browse and expand it if needed */
108 int inputLength
= fCombobox
.GetWindowTextLength() + 2;
110 input
= new WCHAR
[inputLength
];
111 fCombobox
.GetWindowText(input
, inputLength
);
114 int addressLength
= ExpandEnvironmentStrings(input
, NULL
, 0);
116 if (addressLength
<= 0)
123 address
= new WCHAR
[addressLength
];
124 if (!ExpandEnvironmentStrings(input
, address
, addressLength
))
131 /* Try to parse a relative path and if it fails, try to browse an absolute path */
132 CComPtr
<IShellFolder
> psfDesktop
;
133 hr
= SHGetDesktopFolder(&psfDesktop
);
134 if (FAILED_UNEXPECTEDLY(hr
))
137 hr
= pbs
->GetPidl(&pidlCurrent
);
138 if (FAILED_UNEXPECTEDLY(hr
))
141 hr
= psfDesktop
->BindToObject(pidlCurrent
, NULL
, IID_PPV_ARG(IShellFolder
, &psfCurrent
));
142 if (FAILED_UNEXPECTEDLY(hr
))
145 hr
= psfCurrent
->ParseDisplayName(topLevelWindow
, NULL
, address
, &eaten
, &pidlRelative
, &attributes
);
148 pidlLastParsed
= ILCombine(pidlCurrent
, pidlRelative
);
149 ILFree(pidlRelative
);
153 /* We couldn't parse a relative path, attempt to parse an absolute path */
154 hr
= psfDesktop
->ParseDisplayName(topLevelWindow
, NULL
, address
, &eaten
, &pidlLastParsed
, &attributes
);
159 if (address
!= input
)
166 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Execute(long paramC
)
171 * Parse the path is it wasn't parsed
180 * Get the IShellBrowser and IBrowserService interfaces of the shell browser
182 CComPtr
<IShellBrowser
> pisb
;
183 hr
= IUnknown_QueryService(fSite
, SID_SShellBrowser
, IID_PPV_ARG(IShellBrowser
, &pisb
));
187 CComPtr
<IBrowserService
> pbs
;
188 pisb
->QueryInterface(IID_PPV_ARG(IBrowserService
, &pbs
));
193 * Get the current pidl of the shellbrowser and check if it is the same with the parsed one
195 PIDLIST_ABSOLUTE pidl
;
196 hr
= pbs
->GetPidl(&pidl
);
200 CComPtr
<IShellFolder
> psf
;
201 hr
= SHGetDesktopFolder(&psf
);
205 hr
= psf
->CompareIDs(0, pidl
, pidlLastParsed
);
212 * Attempt to browse to the parsed pidl
214 hr
= pisb
->BrowseObject(pidlLastParsed
, 0);
219 * Browsing to the pidl failed so it's not a folder. So invoke its defaule command.
222 hr
= IUnknown_GetWindow(pisb
, &topLevelWindow
);
226 LPCITEMIDLIST pidlChild
;
227 CComPtr
<IShellFolder
> sf
;
228 hr
= SHBindToParent(pidlLastParsed
, IID_PPV_ARG(IShellFolder
, &sf
), &pidlChild
);
232 hr
= SHInvokeDefaultCommand(topLevelWindow
, sf
, pidlChild
);
239 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Save(long paramC
)
244 HRESULT STDMETHODCALLTYPE
CAddressEditBox::OnWinEvent(
245 HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
254 hdr
= (LPNMHDR
) lParam
;
255 if (hdr
->code
== CBEN_ENDEDIT
)
257 NMCBEENDEDITW
*endEdit
= (NMCBEENDEDITW
*) lParam
;
258 if (endEdit
->iWhy
== CBENF_RETURN
)
262 else if (endEdit
->iWhy
== CBENF_ESCAPE
)
264 /* Reset the contents of the combo box */
272 HRESULT STDMETHODCALLTYPE
CAddressEditBox::IsWindowOwner(HWND hWnd
)
274 if (fCombobox
.m_hWnd
== hWnd
)
276 if (fEditWindow
.m_hWnd
== hWnd
)
281 HRESULT STDMETHODCALLTYPE
CAddressEditBox::QueryStatus(
282 const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[ ], OLECMDTEXT
*pCmdText
)
287 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
,
288 DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
293 HRESULT STDMETHODCALLTYPE
CAddressEditBox::GetTypeInfoCount(UINT
*pctinfo
)
298 HRESULT STDMETHODCALLTYPE
CAddressEditBox::GetTypeInfo(UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
303 HRESULT STDMETHODCALLTYPE
CAddressEditBox::GetIDsOfNames(
304 REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
309 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Invoke(DISPID dispIdMember
, REFIID riid
, LCID lcid
,
310 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
312 CComPtr
<IBrowserService
> isb
;
313 CComPtr
<IShellFolder
> sf
;
315 INT indexClosed
, indexOpen
, itemExists
, oldIndex
;
317 COMBOBOXEXITEMW item
;
318 PIDLIST_ABSOLUTE absolutePIDL
;
319 LPCITEMIDLIST pidlChild
;
320 LPITEMIDLIST pidlPrevious
;
324 if (pDispParams
== NULL
)
327 switch (dispIdMember
)
329 case DISPID_NAVIGATECOMPLETE2
:
330 case DISPID_DOCUMENTCOMPLETE
:
331 pidlLastParsed
= NULL
;
333 oldIndex
= fCombobox
.SendMessage(CB_GETCURSEL
, 0, 0);
338 ZeroMemory(&item
, sizeof(item
));
339 item
.mask
= CBEIF_LPARAM
;
341 if (fCombobox
.SendMessage(CBEM_GETITEM
, 0, reinterpret_cast<LPARAM
>(&item
)))
343 pidlPrevious
= reinterpret_cast<LPITEMIDLIST
>(item
.lParam
);
348 hr
= IUnknown_QueryService(fSite
, SID_STopLevelBrowser
, IID_PPV_ARG(IBrowserService
, &isb
));
349 if (FAILED_UNEXPECTEDLY(hr
))
352 hr
= isb
->GetPidl(&absolutePIDL
);
353 if (FAILED_UNEXPECTEDLY(hr
))
356 hr
= SHBindToParent(absolutePIDL
, IID_PPV_ARG(IShellFolder
, &sf
), &pidlChild
);
357 if (FAILED_UNEXPECTEDLY(hr
))
360 hr
= sf
->GetDisplayNameOf(pidlChild
, SHGDN_FORADDRESSBAR
| SHGDN_FORPARSING
, &ret
);
361 if (FAILED_UNEXPECTEDLY(hr
))
364 hr
= StrRetToBufW(&ret
, pidlChild
, buf
, 4095);
365 if (FAILED_UNEXPECTEDLY(hr
))
368 indexClosed
= SHMapPIDLToSystemImageListIndex(sf
, pidlChild
, &indexOpen
);
370 item
.mask
= CBEIF_IMAGE
| CBEIF_SELECTEDIMAGE
| CBEIF_TEXT
| CBEIF_LPARAM
;
372 item
.iImage
= indexClosed
;
373 item
.iSelectedImage
= indexOpen
;
375 item
.lParam
= reinterpret_cast<LPARAM
>(absolutePIDL
);
379 result
= fCombobox
.SendMessage(CBEM_SETITEM
, 0, reinterpret_cast<LPARAM
>(&item
));
384 ILFree(pidlPrevious
);
389 oldIndex
= fCombobox
.SendMessage(CBEM_INSERTITEM
, 0, reinterpret_cast<LPARAM
>(&item
));
392 DbgPrint("ERROR %d\n", GetLastError());
395 fCombobox
.SendMessage(CB_SETCURSEL
, -1, 0);
396 fCombobox
.SendMessage(CB_SETCURSEL
, oldIndex
, 0);
398 //fAddressEditBox->SetCurrentDir(index);
403 HRESULT STDMETHODCALLTYPE
CAddressEditBox::GetClassID(CLSID
*pClassID
)
405 if (pClassID
== NULL
)
407 *pClassID
= CLSID_AddressEditBox
;
411 HRESULT STDMETHODCALLTYPE
CAddressEditBox::IsDirty()
416 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Load(IStream
*pStm
)
421 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Save(IStream
*pStm
, BOOL fClearDirty
)
426 HRESULT STDMETHODCALLTYPE
CAddressEditBox::GetSizeMax(ULARGE_INTEGER
*pcbSize
)