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
*pOwner
)
50 CComPtr
<IBrowserService
> browserService
;
51 HRESULT hResult
= IUnknown_QueryService(fSite
, SID_SShellBrowser
, IID_PPV_ARG(IBrowserService
, &browserService
));
52 if (SUCCEEDED(hResult
))
53 AtlUnadvise(browserService
, DIID_DWebBrowserEvents
, fAdviseCookie
);
56 // connect to browser connection point
60 HRESULT STDMETHODCALLTYPE
CAddressEditBox::FileSysChange(long param8
, long paramC
)
65 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Refresh(long param8
)
70 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Init(HWND comboboxEx
, HWND editControl
, long param14
, IUnknown
*param18
)
72 CComPtr
<IBrowserService
> browserService
;
74 fCombobox
.SubclassWindow(comboboxEx
);
75 fEditWindow
.SubclassWindow(editControl
);
78 SHAutoComplete(fEditWindow
.m_hWnd
, SHACF_FILESYSTEM
| SHACF_URLALL
| SHACF_USETAB
);
80 // take advice to watch events
81 HRESULT hResult
= IUnknown_QueryService(param18
, SID_SShellBrowser
, IID_PPV_ARG(IBrowserService
, &browserService
));
82 if (SUCCEEDED(hResult
))
84 hResult
= AtlAdvise(browserService
, static_cast<IDispatch
*>(this), DIID_DWebBrowserEvents
, &fAdviseCookie
);
90 HRESULT STDMETHODCALLTYPE
CAddressEditBox::SetCurrentDir(long paramC
)
95 HRESULT STDMETHODCALLTYPE
CAddressEditBox::ParseNow(long paramC
)
101 PIDLIST_ABSOLUTE pidlCurrent
= NULL
;
102 PIDLIST_RELATIVE pidlRelative
= NULL
;
103 CComPtr
<IShellFolder
> psfCurrent
;
105 CComPtr
<IBrowserService
> pbs
;
106 hr
= IUnknown_QueryService(fSite
, SID_SShellBrowser
, IID_PPV_ARG(IBrowserService
, &pbs
));
107 if (FAILED_UNEXPECTEDLY(hr
))
110 hr
= IUnknown_GetWindow(pbs
, &topLevelWindow
);
111 if (FAILED_UNEXPECTEDLY(hr
))
114 /* Get the path to browse and expand it if needed */
116 int inputLength
= fCombobox
.GetWindowTextLength() + 2;
118 input
= new WCHAR
[inputLength
];
119 fCombobox
.GetWindowText(input
, inputLength
);
122 int addressLength
= ExpandEnvironmentStrings(input
, NULL
, 0);
124 if (addressLength
<= 0)
131 address
= new WCHAR
[addressLength
];
132 if (!ExpandEnvironmentStrings(input
, address
, addressLength
))
139 /* Try to parse a relative path and if it fails, try to browse an absolute path */
140 CComPtr
<IShellFolder
> psfDesktop
;
141 hr
= SHGetDesktopFolder(&psfDesktop
);
142 if (FAILED_UNEXPECTEDLY(hr
))
145 hr
= pbs
->GetPidl(&pidlCurrent
);
146 if (FAILED_UNEXPECTEDLY(hr
))
149 hr
= psfDesktop
->BindToObject(pidlCurrent
, NULL
, IID_PPV_ARG(IShellFolder
, &psfCurrent
));
150 if (FAILED_UNEXPECTEDLY(hr
))
153 hr
= psfCurrent
->ParseDisplayName(topLevelWindow
, NULL
, address
, &eaten
, &pidlRelative
, &attributes
);
156 pidlLastParsed
= ILCombine(pidlCurrent
, pidlRelative
);
157 ILFree(pidlRelative
);
161 /* We couldn't parse a relative path, attempt to parse an absolute path */
162 hr
= psfDesktop
->ParseDisplayName(topLevelWindow
, NULL
, address
, &eaten
, &pidlLastParsed
, &attributes
);
167 if (address
!= input
)
174 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Execute(long paramC
)
179 * Parse the path is it wasn't parsed
188 * Get the IShellBrowser and IBrowserService interfaces of the shell browser
190 CComPtr
<IShellBrowser
> pisb
;
191 hr
= IUnknown_QueryService(fSite
, SID_SShellBrowser
, IID_PPV_ARG(IShellBrowser
, &pisb
));
195 CComPtr
<IBrowserService
> pbs
;
196 pisb
->QueryInterface(IID_PPV_ARG(IBrowserService
, &pbs
));
201 * Get the current pidl of the shellbrowser and check if it is the same with the parsed one
203 PIDLIST_ABSOLUTE pidl
;
204 hr
= pbs
->GetPidl(&pidl
);
208 CComPtr
<IShellFolder
> psf
;
209 hr
= SHGetDesktopFolder(&psf
);
213 hr
= psf
->CompareIDs(0, pidl
, pidlLastParsed
);
220 * Attempt to browse to the parsed pidl
222 hr
= pisb
->BrowseObject(pidlLastParsed
, 0);
227 * Browsing to the pidl failed so it's not a folder. So invoke its defaule command.
230 hr
= IUnknown_GetWindow(pisb
, &topLevelWindow
);
234 LPCITEMIDLIST pidlChild
;
235 CComPtr
<IShellFolder
> sf
;
236 hr
= SHBindToParent(pidlLastParsed
, IID_PPV_ARG(IShellFolder
, &sf
), &pidlChild
);
240 hr
= SHInvokeDefaultCommand(topLevelWindow
, sf
, pidlChild
);
247 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Save(long paramC
)
252 HRESULT STDMETHODCALLTYPE
CAddressEditBox::OnWinEvent(
253 HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
262 hdr
= (LPNMHDR
) lParam
;
263 if (hdr
->code
== CBEN_ENDEDIT
)
265 NMCBEENDEDITW
*endEdit
= (NMCBEENDEDITW
*) lParam
;
266 if (endEdit
->iWhy
== CBENF_RETURN
)
270 else if (endEdit
->iWhy
== CBENF_ESCAPE
)
272 /* Reset the contents of the combo box */
280 HRESULT STDMETHODCALLTYPE
CAddressEditBox::IsWindowOwner(HWND hWnd
)
282 if (fCombobox
.m_hWnd
== hWnd
)
284 if (fEditWindow
.m_hWnd
== hWnd
)
289 HRESULT STDMETHODCALLTYPE
CAddressEditBox::QueryStatus(
290 const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[ ], OLECMDTEXT
*pCmdText
)
295 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
,
296 DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
301 HRESULT STDMETHODCALLTYPE
CAddressEditBox::GetTypeInfoCount(UINT
*pctinfo
)
306 HRESULT STDMETHODCALLTYPE
CAddressEditBox::GetTypeInfo(UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
311 HRESULT STDMETHODCALLTYPE
CAddressEditBox::GetIDsOfNames(
312 REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
317 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Invoke(DISPID dispIdMember
, REFIID riid
, LCID lcid
,
318 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
320 CComPtr
<IBrowserService
> isb
;
321 CComPtr
<IShellFolder
> sf
;
323 INT indexClosed
, indexOpen
, itemExists
, oldIndex
;
325 COMBOBOXEXITEMW item
;
326 PIDLIST_ABSOLUTE absolutePIDL
;
327 LPCITEMIDLIST pidlChild
;
328 LPITEMIDLIST pidlPrevious
;
332 if (pDispParams
== NULL
)
335 switch (dispIdMember
)
337 case DISPID_NAVIGATECOMPLETE2
:
338 case DISPID_DOCUMENTCOMPLETE
:
339 pidlLastParsed
= NULL
;
341 oldIndex
= fCombobox
.SendMessage(CB_GETCURSEL
, 0, 0);
346 ZeroMemory(&item
, sizeof(item
));
347 item
.mask
= CBEIF_LPARAM
;
349 if (fCombobox
.SendMessage(CBEM_GETITEM
, 0, reinterpret_cast<LPARAM
>(&item
)))
351 pidlPrevious
= reinterpret_cast<LPITEMIDLIST
>(item
.lParam
);
356 hr
= IUnknown_QueryService(fSite
, SID_STopLevelBrowser
, IID_PPV_ARG(IBrowserService
, &isb
));
357 if (FAILED_UNEXPECTEDLY(hr
))
360 hr
= isb
->GetPidl(&absolutePIDL
);
361 if (FAILED_UNEXPECTEDLY(hr
))
364 hr
= SHBindToParent(absolutePIDL
, IID_PPV_ARG(IShellFolder
, &sf
), &pidlChild
);
365 if (FAILED_UNEXPECTEDLY(hr
))
368 hr
= sf
->GetDisplayNameOf(pidlChild
, SHGDN_FORADDRESSBAR
| SHGDN_FORPARSING
, &ret
);
369 if (FAILED_UNEXPECTEDLY(hr
))
372 hr
= StrRetToBufW(&ret
, pidlChild
, buf
, 4095);
373 if (FAILED_UNEXPECTEDLY(hr
))
376 indexClosed
= SHMapPIDLToSystemImageListIndex(sf
, pidlChild
, &indexOpen
);
378 item
.mask
= CBEIF_IMAGE
| CBEIF_SELECTEDIMAGE
| CBEIF_TEXT
| CBEIF_LPARAM
;
380 item
.iImage
= indexClosed
;
381 item
.iSelectedImage
= indexOpen
;
383 item
.lParam
= reinterpret_cast<LPARAM
>(absolutePIDL
);
387 result
= fCombobox
.SendMessage(CBEM_SETITEM
, 0, reinterpret_cast<LPARAM
>(&item
));
392 ILFree(pidlPrevious
);
397 oldIndex
= fCombobox
.SendMessage(CBEM_INSERTITEM
, 0, reinterpret_cast<LPARAM
>(&item
));
400 DbgPrint("ERROR %d\n", GetLastError());
403 fCombobox
.SendMessage(CB_SETCURSEL
, -1, 0);
404 fCombobox
.SendMessage(CB_SETCURSEL
, oldIndex
, 0);
406 //fAddressEditBox->SetCurrentDir(index);
411 HRESULT STDMETHODCALLTYPE
CAddressEditBox::GetClassID(CLSID
*pClassID
)
413 if (pClassID
== NULL
)
415 *pClassID
= CLSID_AddressEditBox
;
419 HRESULT STDMETHODCALLTYPE
CAddressEditBox::IsDirty()
424 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Load(IStream
*pStm
)
429 HRESULT STDMETHODCALLTYPE
CAddressEditBox::Save(IStream
*pStm
, BOOL fClearDirty
)
434 HRESULT STDMETHODCALLTYPE
CAddressEditBox::GetSizeMax(ULARGE_INTEGER
*pcbSize
)