4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "CSearchBar.h"
20 #include <psdk/wingdi.h>
21 #include <commoncontrols.h>
22 #include <../browseui.h>
26 WINE_DEFAULT_DEBUG_CHANNEL(shellfind
);
31 #define UNIMPLEMENTED DbgPrint("%s is UNIMPLEMENTED!\n", __FUNCTION__)
34 CSearchBar::CSearchBar() :
41 CSearchBar::~CSearchBar()
45 LRESULT
CSearchBar::OnInitDialog(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
47 SetSearchInProgress(FALSE
);
49 HWND hCombobox
= GetDlgItem(IDC_SEARCH_COMBOBOX
);
50 IImageList
*pImageList
;
51 HRESULT hResult
= SHGetImageList(SHIL_SMALL
, IID_PPV_ARG(IImageList
, &pImageList
));
52 SendMessage(hCombobox
, CBEM_SETIMAGELIST
, 0, FAILED_UNEXPECTEDLY(hResult
) ? 0 : reinterpret_cast<LPARAM
>(pImageList
));
54 SendMessage(hCombobox
, CBEM_SETEXTENDEDSTYLE
,
55 CBES_EX_CASESENSITIVE
| CBES_EX_NOSIZELIMIT
, CBES_EX_CASESENSITIVE
| CBES_EX_NOSIZELIMIT
);
56 HWND hEditControl
= reinterpret_cast<HWND
>(SendMessage(hCombobox
, CBEM_GETEDITCONTROL
, 0, 0));
57 hResult
= CAddressEditBox_CreateInstance(IID_PPV_ARG(IAddressEditBox
, &m_AddressEditBox
));
58 if (FAILED_UNEXPECTEDLY(hResult
))
61 CComPtr
<IShellService
> pShellService
;
62 hResult
= fAddressEditBox
->QueryInterface(IID_PPV_ARG(IShellService
, &pShellService
));
63 if (FAILED_UNEXPECTEDLY(hResult
))
65 hResult
= fAddressEditBox
->Init(hCombobox
, fEditControl
, 0, pSite
);
66 if (FAILED_UNEXPECTEDLY(hResult
))
69 CComPtr
<IDispatch
> pDispatch
;
70 hResult
= fAddressEditBox
->QueryInterface(IID_PPV_ARG(IDispatch
, &pDispatch
));
71 if (FAILED_UNEXPECTEDLY(hResult
))
73 DISPPARAMS params
= {0};
74 hResult
= pDispatch
->Invoke(DISPID_NAVIGATECOMPLETE2
, GUID_NULL
, 0, DISPATCH_METHOD
, ¶ms
, NULL
, NULL
, NULL
);
76 hResult
= pShellService
->SetOwner(NULL
);
77 if (FAILED_UNEXPECTEDLY(hResult
))
83 HRESULT
CSearchBar::ExecuteCommand(CComPtr
<IContextMenu
>& menu
, UINT nCmd
)
85 CComPtr
<IOleWindow
> pBrowserOleWnd
;
86 CMINVOKECOMMANDINFO cmi
;
90 hr
= IUnknown_QueryService(pSite
, SID_SShellBrowser
, IID_PPV_ARG(IOleWindow
, &pBrowserOleWnd
));
91 if (FAILED_UNEXPECTEDLY(hr
))
94 hr
= pBrowserOleWnd
->GetWindow(&browserWnd
);
95 if (FAILED_UNEXPECTEDLY(hr
))
98 ZeroMemory(&cmi
, sizeof(cmi
));
99 cmi
.cbSize
= sizeof(cmi
);
100 cmi
.lpVerb
= MAKEINTRESOURCEA(nCmd
);
101 cmi
.hwnd
= browserWnd
;
102 if (GetKeyState(VK_SHIFT
) & 0x8000)
103 cmi
.fMask
|= CMIC_MASK_SHIFT_DOWN
;
104 if (GetKeyState(VK_CONTROL
) & 0x8000)
105 cmi
.fMask
|= CMIC_MASK_CONTROL_DOWN
;
107 return menu
->InvokeCommand(&cmi
);
111 // *** ATL event handlers ***
112 LRESULT
CSearchBar::OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
115 IUnknown_OnFocusChangeIS(pSite
, reinterpret_cast<IUnknown
*>(this), TRUE
);
120 HRESULT
CSearchBar::GetSearchResultsFolder(IShellBrowser
**ppShellBrowser
, HWND
*pHwnd
, IShellFolder
**ppShellFolder
)
123 CComPtr
<IShellBrowser
> pShellBrowser
;
125 ppShellBrowser
= &pShellBrowser
;
126 if (!*ppShellBrowser
)
128 hr
= IUnknown_QueryService(m_pSite
, SID_SShellBrowser
, IID_PPV_ARG(IShellBrowser
, ppShellBrowser
));
129 if (FAILED_UNEXPECTEDLY(hr
))
133 CComPtr
<IShellView
> pShellView
;
134 hr
= (*ppShellBrowser
)->QueryActiveShellView(&pShellView
);
135 if (FAILED(hr
) || !pShellView
)
138 CComPtr
<IFolderView
> pFolderView
;
139 hr
= pShellView
->QueryInterface(IID_PPV_ARG(IFolderView
, &pFolderView
));
140 if (FAILED(hr
) || !pFolderView
)
143 CComPtr
<IShellFolder
> pShellFolder
;
145 ppShellFolder
= &pShellFolder
;
146 hr
= pFolderView
->GetFolder(IID_PPV_ARG(IShellFolder
, ppShellFolder
));
147 if (FAILED(hr
) || !pShellFolder
)
151 hr
= IUnknown_GetClassID(*ppShellFolder
, &clsid
);
154 if (clsid
!= CLSID_FindFolder
)
159 hr
= pShellView
->GetWindow(pHwnd
);
160 if (FAILED_UNEXPECTEDLY(hr
))
167 LRESULT
CSearchBar::OnSearchButtonClicked(WORD wNotifyCode
, WORD wID
, HWND hWndCtl
, BOOL
& bHandled
)
169 CComHeapPtr
<SearchStart
> pSearchStart((SearchStart
*)SHAlloc(sizeof(SearchStart
)));
170 GetDlgItemText(IDC_SEARCH_FILENAME
, pSearchStart
->szFileName
, _countof(pSearchStart
->szFileName
));
171 GetDlgItemText(IDC_SEARCH_QUERY
, pSearchStart
->szQuery
, _countof(pSearchStart
->szQuery
));
172 if (!GetAddressEditBoxPath(pSearchStart
->szPath
))
174 ShellMessageBoxW(_AtlBaseModule
.GetResourceInstance(), m_hWnd
, MAKEINTRESOURCEW(IDS_SEARCHINVALID
), MAKEINTRESOURCEW(IDS_SEARCHLABEL
), MB_OK
| MB_ICONERROR
, pSearchStart
->szPath
);
178 CComPtr
<IShellBrowser
> pShellBrowser
;
179 HRESULT hr
= IUnknown_QueryService(pSite
, SID_SShellBrowser
, IID_PPV_ARG(IShellBrowser
, &pShellBrowser
));
180 if (FAILED_UNEXPECTEDLY(hr
))
184 if (FAILED(GetSearchResultsFolder(&pShellBrowser
, &hwnd
, NULL
)))
186 // Open a new search results folder
187 WCHAR szShellGuid
[MAX_PATH
];
188 const WCHAR shellGuidPrefix
[] = L
"shell:::";
189 memcpy(szShellGuid
, shellGuidPrefix
, sizeof(shellGuidPrefix
));
190 hr
= StringFromGUID2(CLSID_FindFolder
, szShellGuid
+ _countof(shellGuidPrefix
) - 1,
191 _countof(szShellGuid
) - _countof(shellGuidPrefix
));
192 if (FAILED_UNEXPECTEDLY(hr
))
195 CComHeapPtr
<ITEMIDLIST
> findFolderPidl
;
196 hr
= SHParseDisplayName(szShellGuid
, NULL
, &findFolderPidl
, 0, NULL
);
197 if (FAILED_UNEXPECTEDLY(hr
))
200 hr
= pShellBrowser
->BrowseObject(findFolderPidl
, 0);
201 if (FAILED_UNEXPECTEDLY(hr
))
204 CComPtr
<IShellFolder
> pShellFolder
;
205 hr
= GetSearchResultsFolder(*pShellBrowser
, &hwnd
, &pShellFolder
);
206 if (FAILED_UNEXPECTEDLY(hr
))
209 // Subscribe to search events
211 hr
= AtlAdvise(pShellFolder
, static_cast<IDispatch
*>(this), DIID_DSearchCommandEvents
, &fAdviseCookie
);
212 if (FAILED_UNEXPECTEDLY(hr
))
216 ::PostMessageW(hwnd
, WM_SEARCH_START
, 0, (LPARAM
) pSearchStart
.Detach());
218 SetSearchInProgress(TRUE
);
223 LRESULT
CSearchBar::OnStopButtonClicked(WORD wNotifyCode
, WORD wID
, HWND hWndCtl
, BOOL
& bHandled
)
226 HRESULT hr
= GetSearchResultsFolder(NULL
, &hwnd
, NULL
);
228 ::PostMessageW(hwnd
, WM_SEARCH_STOP
, 0, 0);
233 BOOL
CSearchBar::GetAddressEditBoxPath(WCHAR (&szPath
)[MAX_PATH
])
235 HWND hComboboxEx
= GetDlgItem(IDC_SEARCH_COMBOBOX
);
236 ::GetWindowTextW(hComboboxEx
, szPath
, _countof(szPath
));
237 INT iSelectedIndex
= SendMessageW(hComboboxEx
, CB_GETCURSEL
, 0, 0);
238 if (iSelectedIndex
!= CB_ERR
)
240 WCHAR szItemText
[MAX_PATH
];
241 COMBOBOXEXITEMW item
= {0};
242 item
.mask
= CBEIF_LPARAM
| CBEIF_TEXT
;
243 item
.iItem
= iSelectedIndex
;
244 item
.pszText
= szItemText
;
245 item
.cchTextMax
= _countof(szItemText
);
246 SendMessageW(hComboboxEx
, CBEM_GETITEMW
, 0, (LPARAM
)&item
);
248 if (!wcscmp(szItemText
, szPath
) && SHGetPathFromIDListW((LPCITEMIDLIST
)item
.lParam
, szPath
))
254 DWORD dwAttributes
= GetFileAttributesW(szPath
);
255 return dwAttributes
!= INVALID_FILE_ATTRIBUTES
256 && (dwAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
259 LRESULT
CSearchBar::OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
261 INT iWidth
= LOWORD(lParam
);
264 ((CWindow
)GetDlgItem(IDC_SEARCH_LABEL
)).SetWindowPos(NULL
, 0, 0, iWidth
- iPadding
, 40, SWP_NOACTIVATE
| SWP_NOCOPYBITS
| SWP_NOMOVE
| SWP_NOOWNERZORDER
| SWP_NOZORDER
);
266 HWND inputs
[] = { GetDlgItem(IDC_SEARCH_FILENAME
), GetDlgItem(IDC_SEARCH_QUERY
), GetDlgItem(IDC_SEARCH_COMBOBOX
), GetDlgItem(IDC_SEARCH_BUTTON
), GetDlgItem(IDC_SEARCH_STOP_BUTTON
), GetDlgItem(IDC_PROGRESS_BAR
) };
267 for (SIZE_T i
= 0; i
< _countof(inputs
); i
++)
269 CWindow wFileName
= (CWindow
) inputs
[i
];
271 wFileName
.GetWindowRect(&rect
);
272 POINT pt
= { rect
.left
, rect
.top
};
274 wFileName
.MoveWindow(iPadding
, pt
.y
, iWidth
- iPadding
* 2, rect
.bottom
- rect
.top
);
281 // *** IOleWindow methods ***
282 HRESULT STDMETHODCALLTYPE
CSearchBar::GetWindow(HWND
*lphwnd
)
290 HRESULT STDMETHODCALLTYPE
CSearchBar::ContextSensitiveHelp(BOOL fEnterMode
)
297 // *** IDockingWindow methods ***
298 HRESULT STDMETHODCALLTYPE
CSearchBar::CloseDW(DWORD dwReserved
)
300 // We do nothing, we don't have anything to save yet
301 TRACE("CloseDW called\n");
305 HRESULT STDMETHODCALLTYPE
CSearchBar::ResizeBorderDW(const RECT
*prcBorder
, IUnknown
*punkToolbarSite
, BOOL fReserved
)
307 /* Must return E_NOTIMPL according to MSDN */
311 HRESULT STDMETHODCALLTYPE
CSearchBar::ShowDW(BOOL fShow
)
319 // *** IDeskBand methods ***
320 HRESULT STDMETHODCALLTYPE
CSearchBar::GetBandInfo(DWORD dwBandID
, DWORD dwViewMode
, DESKBANDINFO
*pdbi
)
327 if (pdbi
->dwMask
& DBIM_MINSIZE
)
329 pdbi
->ptMinSize
.x
= 200;
330 pdbi
->ptMinSize
.y
= 30;
333 if (pdbi
->dwMask
& DBIM_MAXSIZE
)
335 pdbi
->ptMaxSize
.y
= -1;
338 if (pdbi
->dwMask
& DBIM_INTEGRAL
)
340 pdbi
->ptIntegral
.y
= 1;
343 if (pdbi
->dwMask
& DBIM_ACTUAL
)
345 pdbi
->ptActual
.x
= 200;
346 pdbi
->ptActual
.y
= 30;
349 if (pdbi
->dwMask
& DBIM_TITLE
)
351 if (!LoadStringW(_AtlBaseModule
.GetResourceInstance(), IDS_SEARCHLABEL
, pdbi
->wszTitle
, _countof(pdbi
->wszTitle
)))
352 return HRESULT_FROM_WIN32(GetLastError());
355 if (pdbi
->dwMask
& DBIM_MODEFLAGS
)
357 pdbi
->dwModeFlags
= DBIMF_NORMAL
| DBIMF_VARIABLEHEIGHT
;
360 if (pdbi
->dwMask
& DBIM_BKCOLOR
)
362 pdbi
->dwMask
&= ~DBIM_BKCOLOR
;
367 LRESULT CALLBACK
MyWindowProc(
377 // *** IObjectWithSite methods ***
378 HRESULT STDMETHODCALLTYPE
CSearchBar::SetSite(IUnknown
*pUnkSite
)
383 if (pUnkSite
== pSite
)
386 TRACE("SetSite called \n");
393 if (pUnkSite
!= pSite
)
401 hr
= IUnknown_GetWindow(pUnkSite
, &parentWnd
);
404 ERR("Could not get parent's window ! Status: %08lx\n", hr
);
413 SetParent(parentWnd
);
417 CDialogImpl::Create(parentWnd
);
423 HRESULT STDMETHODCALLTYPE
CSearchBar::GetSite(REFIID riid
, void **ppvSite
)
432 // *** IOleCommandTarget methods ***
433 HRESULT STDMETHODCALLTYPE
CSearchBar::QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
439 HRESULT STDMETHODCALLTYPE
CSearchBar::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
446 // *** IServiceProvider methods ***
447 HRESULT STDMETHODCALLTYPE
CSearchBar::QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
)
449 /* FIXME: we probably want to handle more services here */
450 return IUnknown_QueryService(pSite
, SID_SShellBrowser
, riid
, ppvObject
);
454 // *** IInputObject methods ***
455 HRESULT STDMETHODCALLTYPE
CSearchBar::UIActivateIO(BOOL fActivate
, LPMSG lpMsg
)
462 // TODO: handle message
465 TranslateMessage(lpMsg
);
466 DispatchMessage(lpMsg
);
471 HRESULT STDMETHODCALLTYPE
CSearchBar::HasFocusIO()
473 return bFocused
? S_OK
: S_FALSE
;
476 HRESULT STDMETHODCALLTYPE
CSearchBar::TranslateAcceleratorIO(LPMSG lpMsg
)
478 if (IsDialogMessage(lpMsg
))
481 if ((lpMsg
->hwnd
== m_hWnd
|| IsChild(lpMsg
->hwnd
)))
483 TranslateMessage(lpMsg
);
484 DispatchMessage(lpMsg
);
491 // *** IPersist methods ***
492 HRESULT STDMETHODCALLTYPE
CSearchBar::GetClassID(CLSID
*pClassID
)
496 memcpy(pClassID
, &CLSID_FileSearchBand
, sizeof(CLSID
));
501 // *** IPersistStream methods ***
502 HRESULT STDMETHODCALLTYPE
CSearchBar::IsDirty()
508 HRESULT STDMETHODCALLTYPE
CSearchBar::Load(IStream
*pStm
)
514 HRESULT STDMETHODCALLTYPE
CSearchBar::Save(IStream
*pStm
, BOOL fClearDirty
)
520 HRESULT STDMETHODCALLTYPE
CSearchBar::GetSizeMax(ULARGE_INTEGER
*pcbSize
)
522 // TODO: calculate max size
528 // *** IWinEventHandler methods ***
529 HRESULT STDMETHODCALLTYPE
CSearchBar::OnWinEvent(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
534 HRESULT STDMETHODCALLTYPE
CSearchBar::IsWindowOwner(HWND hWnd
)
536 return (hWnd
== m_hWnd
) ? S_OK
: S_FALSE
;
539 // *** IBandNavigate methods ***
540 HRESULT STDMETHODCALLTYPE
CSearchBar::Select(long paramC
)
546 // *** INamespaceProxy ***
547 HRESULT STDMETHODCALLTYPE
CSearchBar::GetNavigateTarget(long paramC
, long param10
, long param14
)
553 HRESULT STDMETHODCALLTYPE
CSearchBar::Invoke(long paramC
)
559 HRESULT STDMETHODCALLTYPE
CSearchBar::OnSelectionChanged(long paramC
)
565 HRESULT STDMETHODCALLTYPE
CSearchBar::RefreshFlags(long paramC
, long param10
, long param14
)
571 HRESULT STDMETHODCALLTYPE
CSearchBar::CacheItem(long paramC
)
577 // *** IDispatch methods ***
578 HRESULT STDMETHODCALLTYPE
CSearchBar::GetTypeInfoCount(UINT
*pctinfo
)
584 HRESULT STDMETHODCALLTYPE
CSearchBar::GetTypeInfo(UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
590 HRESULT STDMETHODCALLTYPE
CSearchBar::GetIDsOfNames(REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
596 void CSearchBar::SetSearchInProgress(BOOL bInProgress
)
598 ::ShowWindow(GetDlgItem(IDC_SEARCH_BUTTON
), bInProgress
? SW_HIDE
: SW_SHOW
);
599 ::ShowWindow(GetDlgItem(IDC_SEARCH_STOP_BUTTON
), bInProgress
? SW_SHOW
: SW_HIDE
);
600 HWND hProgressBar
= GetDlgItem(IDC_PROGRESS_BAR
);
601 ::ShowWindow(hProgressBar
, bInProgress
? SW_SHOW
: SW_HIDE
);
602 ::PostMessage(hProgressBar
, PBM_SETMARQUEE
, bInProgress
, 0);
605 HRESULT STDMETHODCALLTYPE
CSearchBar::Invoke(DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
607 if (dispIdMember
== DISPID_SEARCHCOMPLETE
|| dispIdMember
== DISPID_SEARCHABORT
)
609 SetSearchInProgress(FALSE
);