[SHELLFIND] Set status bar text after opening search results folder
[reactos.git] / dll / win32 / browseui / shellfind / CSearchBar.cpp
1 /*
2 * ReactOS Explorer
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #include "CSearchBar.h"
20 #include <psdk/wingdi.h>
21
22 WINE_DEFAULT_DEBUG_CHANNEL(shellfind);
23
24 #if 1
25 #undef UNIMPLEMENTED
26
27 #define UNIMPLEMENTED DbgPrint("%s is UNIMPLEMENTED!\n", __FUNCTION__)
28 #endif
29
30 CSearchBar::CSearchBar() :
31 pSite(NULL),
32 fVisible(FALSE),
33 bFocused(FALSE)
34 {
35 }
36
37 CSearchBar::~CSearchBar()
38 {
39 }
40
41 void CSearchBar::InitializeSearchBar()
42 {
43 CreateWindowExW(0, WC_STATIC, L"Search by any or all of the criteria below.",
44 WS_CHILD | WS_VISIBLE,
45 10, 10, 200, 40,
46 m_hWnd, NULL,
47 _AtlBaseModule.GetModuleInstance(), NULL);
48
49 CreateWindowExW(0, WC_STATIC, L"A &word or phrase in the file:",
50 WS_CHILD | WS_VISIBLE,
51 10, 50, 500, 20,
52 m_hWnd, NULL,
53 _AtlBaseModule.GetModuleInstance(), NULL);
54 CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, NULL,
55 WS_BORDER | WS_CHILD | WS_VISIBLE,
56 10, 70, 100, 20,
57 m_hWnd, NULL,
58 _AtlBaseModule.GetModuleInstance(), NULL);
59
60 CreateWindowExW(0, WC_STATIC, L"&Look in:",
61 WS_CHILD | WS_VISIBLE,
62 10, 100, 500, 20,
63 m_hWnd, NULL,
64 _AtlBaseModule.GetModuleInstance(), NULL);
65 CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, NULL,
66 WS_BORDER | WS_CHILD | WS_VISIBLE,
67 10, 120, 100, 20,
68 m_hWnd, NULL,
69 _AtlBaseModule.GetModuleInstance(), NULL);
70
71 CreateWindowExW(0, WC_BUTTON, L"Sea&rch",
72 WS_BORDER | WS_CHILD | WS_VISIBLE,
73 10, 150, 100, 20,
74 m_hWnd, NULL,
75 _AtlBaseModule.GetModuleInstance(), NULL);
76 }
77
78 HRESULT CSearchBar::ExecuteCommand(CComPtr<IContextMenu>& menu, UINT nCmd)
79 {
80 CComPtr<IOleWindow> pBrowserOleWnd;
81 CMINVOKECOMMANDINFO cmi;
82 HWND browserWnd;
83 HRESULT hr;
84
85 hr = IUnknown_QueryService(pSite, SID_SShellBrowser, IID_PPV_ARG(IOleWindow, &pBrowserOleWnd));
86 if (FAILED_UNEXPECTEDLY(hr))
87 return hr;
88
89 hr = pBrowserOleWnd->GetWindow(&browserWnd);
90 if (FAILED_UNEXPECTEDLY(hr))
91 return hr;
92
93 ZeroMemory(&cmi, sizeof(cmi));
94 cmi.cbSize = sizeof(cmi);
95 cmi.lpVerb = MAKEINTRESOURCEA(nCmd);
96 cmi.hwnd = browserWnd;
97 if (GetKeyState(VK_SHIFT) & 0x8000)
98 cmi.fMask |= CMIC_MASK_SHIFT_DOWN;
99 if (GetKeyState(VK_CONTROL) & 0x8000)
100 cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
101
102 return menu->InvokeCommand(&cmi);
103 }
104
105
106 // *** ATL event handlers ***
107 LRESULT CSearchBar::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
108 {
109 bFocused = TRUE;
110 IUnknown_OnFocusChangeIS(pSite, reinterpret_cast<IUnknown*>(this), TRUE);
111 bHandled = FALSE;
112 return TRUE;
113 }
114
115 HRESULT CSearchBar::GetSearchResultsFolder(IShellBrowser **ppShellBrowser, HWND *pHwnd, IShellFolder **ppShellFolder)
116 {
117 HRESULT hr;
118 CComPtr<IShellBrowser> pShellBrowser;
119 if (!ppShellBrowser)
120 ppShellBrowser = &pShellBrowser;
121 if (!*ppShellBrowser)
122 {
123 hr = IUnknown_QueryService(m_pSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, ppShellBrowser));
124 if (FAILED_UNEXPECTEDLY(hr))
125 return hr;
126 }
127
128 CComPtr<IShellView> pShellView;
129 hr = (*ppShellBrowser)->QueryActiveShellView(&pShellView);
130 if (FAILED(hr) || !pShellView)
131 return hr;
132
133 CComPtr<IFolderView> pFolderView;
134 hr = pShellView->QueryInterface(IID_PPV_ARG(IFolderView, &pFolderView));
135 if (FAILED(hr) || !pFolderView)
136 return hr;
137
138 CComPtr<IShellFolder> pShellFolder;
139 if (!ppShellFolder)
140 ppShellFolder = &pShellFolder;
141 hr = pFolderView->GetFolder(IID_PPV_ARG(IShellFolder, ppShellFolder));
142 if (FAILED(hr) || !pShellFolder)
143 return hr;
144
145 CLSID clsid;
146 hr = IUnknown_GetClassID(*ppShellFolder, &clsid);
147 if (FAILED(hr))
148 return hr;
149 if (clsid != CLSID_FindFolder)
150 return E_FAIL;
151
152 if (pHwnd)
153 {
154 hr = pShellView->GetWindow(pHwnd);
155 if (FAILED_UNEXPECTEDLY(hr))
156 return hr;
157 }
158
159 return S_OK;
160 }
161
162 LRESULT CSearchBar::OnSearchButtonClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
163 {
164 CComPtr<IShellBrowser> pShellBrowser;
165 HRESULT hr = IUnknown_QueryService(pSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &pShellBrowser));
166 if (FAILED_UNEXPECTEDLY(hr))
167 return hr;
168
169 HWND hwnd;
170 if (FAILED(GetSearchResultsFolder(&pShellBrowser, &hwnd, NULL)))
171 {
172 WCHAR szShellGuid[MAX_PATH];
173 const WCHAR shellGuidPrefix[] = L"shell:::";
174 memcpy(szShellGuid, shellGuidPrefix, sizeof(shellGuidPrefix));
175 hr = StringFromGUID2(CLSID_FindFolder, szShellGuid + _countof(shellGuidPrefix) - 1,
176 _countof(szShellGuid) - _countof(shellGuidPrefix));
177 if (FAILED_UNEXPECTEDLY(hr))
178 return hr;
179
180 LPITEMIDLIST findFolderPidl;
181 hr = SHParseDisplayName(szShellGuid, NULL, &findFolderPidl, 0, NULL);
182 if (FAILED_UNEXPECTEDLY(hr))
183 return hr;
184
185 hr = pShellBrowser->BrowseObject(findFolderPidl, 0);
186 if (FAILED_UNEXPECTEDLY(hr))
187 return hr;
188 }
189
190 GetSearchResultsFolder(&pShellBrowser, &hwnd, NULL);
191 if (hwnd)
192 // TODO: Use message ID in header file
193 ::PostMessageW(hwnd, WM_USER + 1, 0, (LPARAM) StrDupW(L"Starting search..."));
194
195 return S_OK;
196 }
197
198 LRESULT CSearchBar::OnClicked(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
199 {
200 HWND hwnd;
201 HRESULT hr = GetSearchResultsFolder(NULL, &hwnd, NULL);
202 if (SUCCEEDED(hr))
203 {
204 LPCWSTR path = L"C:\\readme.txt";
205 // TODO: Use message ID in header file
206 ::PostMessageW(hwnd, WM_USER, 0, (LPARAM) StrDupW(path));
207 }
208
209 return 0;
210 }
211
212
213 // *** IOleWindow methods ***
214 HRESULT STDMETHODCALLTYPE CSearchBar::GetWindow(HWND *lphwnd)
215 {
216 if (!lphwnd)
217 return E_INVALIDARG;
218 *lphwnd = m_hWnd;
219 return S_OK;
220 }
221
222 HRESULT STDMETHODCALLTYPE CSearchBar::ContextSensitiveHelp(BOOL fEnterMode)
223 {
224 UNIMPLEMENTED;
225 return E_NOTIMPL;
226 }
227
228
229 // *** IDockingWindow methods ***
230 HRESULT STDMETHODCALLTYPE CSearchBar::CloseDW(DWORD dwReserved)
231 {
232 // We do nothing, we don't have anything to save yet
233 TRACE("CloseDW called\n");
234 return S_OK;
235 }
236
237 HRESULT STDMETHODCALLTYPE CSearchBar::ResizeBorderDW(const RECT *prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
238 {
239 /* Must return E_NOTIMPL according to MSDN */
240 return E_NOTIMPL;
241 }
242
243 HRESULT STDMETHODCALLTYPE CSearchBar::ShowDW(BOOL fShow)
244 {
245 fVisible = fShow;
246 ShowWindow(fShow);
247 return S_OK;
248 }
249
250
251 // *** IDeskBand methods ***
252 HRESULT STDMETHODCALLTYPE CSearchBar::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi)
253 {
254 if (!pdbi)
255 {
256 return E_INVALIDARG;
257 }
258
259 if (pdbi->dwMask & DBIM_MINSIZE)
260 {
261 pdbi->ptMinSize.x = 200;
262 pdbi->ptMinSize.y = 30;
263 }
264
265 if (pdbi->dwMask & DBIM_MAXSIZE)
266 {
267 pdbi->ptMaxSize.y = -1;
268 }
269
270 if (pdbi->dwMask & DBIM_INTEGRAL)
271 {
272 pdbi->ptIntegral.y = 1;
273 }
274
275 if (pdbi->dwMask & DBIM_ACTUAL)
276 {
277 pdbi->ptActual.x = 200;
278 pdbi->ptActual.y = 30;
279 }
280
281 if (pdbi->dwMask & DBIM_TITLE)
282 {
283 if (!LoadStringW(_AtlBaseModule.GetResourceInstance(), IDS_SEARCHLABEL, pdbi->wszTitle, _countof(pdbi->wszTitle)))
284 return HRESULT_FROM_WIN32(GetLastError());
285 }
286
287 if (pdbi->dwMask & DBIM_MODEFLAGS)
288 {
289 pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
290 }
291
292 if (pdbi->dwMask & DBIM_BKCOLOR)
293 {
294 pdbi->dwMask &= ~DBIM_BKCOLOR;
295 }
296 return S_OK;
297 }
298
299 LRESULT CALLBACK MyWindowProc(
300 _In_ HWND hwnd,
301 _In_ UINT uMsg,
302 _In_ WPARAM wParam,
303 _In_ LPARAM lParam
304 )
305 {
306 return 0;
307 }
308
309 // *** IObjectWithSite methods ***
310 HRESULT STDMETHODCALLTYPE CSearchBar::SetSite(IUnknown *pUnkSite)
311 {
312 HRESULT hr;
313 HWND parentWnd;
314
315 if (pUnkSite == pSite)
316 return S_OK;
317
318 TRACE("SetSite called \n");
319 if (!pUnkSite)
320 {
321 DestroyWindow();
322 m_hWnd = NULL;
323 }
324
325 if (pUnkSite != pSite)
326 {
327 pSite = NULL;
328 }
329
330 if(!pUnkSite)
331 return S_OK;
332
333 hr = IUnknown_GetWindow(pUnkSite, &parentWnd);
334 if (!SUCCEEDED(hr))
335 {
336 ERR("Could not get parent's window ! Status: %08lx\n", hr);
337 return E_INVALIDARG;
338 }
339
340 pSite = pUnkSite;
341
342 if (m_hWnd)
343 {
344 // Change its parent
345 SetParent(parentWnd);
346 }
347 else
348 {
349 CWindowImpl::Create(parentWnd);
350
351 InitializeSearchBar();
352 }
353 return S_OK;
354 }
355
356 HRESULT STDMETHODCALLTYPE CSearchBar::GetSite(REFIID riid, void **ppvSite)
357 {
358 if (!ppvSite)
359 return E_POINTER;
360 *ppvSite = pSite;
361 return S_OK;
362 }
363
364
365 // *** IOleCommandTarget methods ***
366 HRESULT STDMETHODCALLTYPE CSearchBar::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
367 {
368 UNIMPLEMENTED;
369 return E_NOTIMPL;
370 }
371
372 HRESULT STDMETHODCALLTYPE CSearchBar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
373 {
374 UNIMPLEMENTED;
375 return E_NOTIMPL;
376 }
377
378
379 // *** IServiceProvider methods ***
380 HRESULT STDMETHODCALLTYPE CSearchBar::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
381 {
382 /* FIXME: we probably want to handle more services here */
383 return IUnknown_QueryService(pSite, SID_SShellBrowser, riid, ppvObject);
384 }
385
386
387 // *** IInputObject methods ***
388 HRESULT STDMETHODCALLTYPE CSearchBar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
389 {
390 if (fActivate)
391 {
392 //SetFocus();
393 SetActiveWindow();
394 }
395 // TODO: handle message
396 if(lpMsg)
397 {
398 TranslateMessage(lpMsg);
399 DispatchMessage(lpMsg);
400 }
401 return S_OK;
402 }
403
404 HRESULT STDMETHODCALLTYPE CSearchBar::HasFocusIO()
405 {
406 return bFocused ? S_OK : S_FALSE;
407 }
408
409 HRESULT STDMETHODCALLTYPE CSearchBar::TranslateAcceleratorIO(LPMSG lpMsg)
410 {
411 if (lpMsg->hwnd == m_hWnd)
412 {
413 TranslateMessage(lpMsg);
414 DispatchMessage(lpMsg);
415 return S_OK;
416 }
417
418 return S_FALSE;
419 }
420
421 // *** IPersist methods ***
422 HRESULT STDMETHODCALLTYPE CSearchBar::GetClassID(CLSID *pClassID)
423 {
424 if (!pClassID)
425 return E_POINTER;
426 memcpy(pClassID, &CLSID_FileSearchBand, sizeof(CLSID));
427 return S_OK;
428 }
429
430
431 // *** IPersistStream methods ***
432 HRESULT STDMETHODCALLTYPE CSearchBar::IsDirty()
433 {
434 UNIMPLEMENTED;
435 return E_NOTIMPL;
436 }
437
438 HRESULT STDMETHODCALLTYPE CSearchBar::Load(IStream *pStm)
439 {
440 UNIMPLEMENTED;
441 return E_NOTIMPL;
442 }
443
444 HRESULT STDMETHODCALLTYPE CSearchBar::Save(IStream *pStm, BOOL fClearDirty)
445 {
446 UNIMPLEMENTED;
447 return E_NOTIMPL;
448 }
449
450 HRESULT STDMETHODCALLTYPE CSearchBar::GetSizeMax(ULARGE_INTEGER *pcbSize)
451 {
452 // TODO: calculate max size
453 UNIMPLEMENTED;
454 return E_NOTIMPL;
455 }
456
457
458 // *** IWinEventHandler methods ***
459 HRESULT STDMETHODCALLTYPE CSearchBar::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
460 {
461 return S_OK;
462 }
463
464 HRESULT STDMETHODCALLTYPE CSearchBar::IsWindowOwner(HWND hWnd)
465 {
466 return (hWnd == m_hWnd) ? S_OK : S_FALSE;
467 }
468
469 // *** IBandNavigate methods ***
470 HRESULT STDMETHODCALLTYPE CSearchBar::Select(long paramC)
471 {
472 UNIMPLEMENTED;
473 return E_NOTIMPL;
474 }
475
476 // *** INamespaceProxy ***
477 HRESULT STDMETHODCALLTYPE CSearchBar::GetNavigateTarget(long paramC, long param10, long param14)
478 {
479 UNIMPLEMENTED;
480 return E_NOTIMPL;
481 }
482
483 HRESULT STDMETHODCALLTYPE CSearchBar::Invoke(long paramC)
484 {
485 UNIMPLEMENTED;
486 return E_NOTIMPL;
487 }
488
489 HRESULT STDMETHODCALLTYPE CSearchBar::OnSelectionChanged(long paramC)
490 {
491 UNIMPLEMENTED;
492 return E_NOTIMPL;
493 }
494
495 HRESULT STDMETHODCALLTYPE CSearchBar::RefreshFlags(long paramC, long param10, long param14)
496 {
497 UNIMPLEMENTED;
498 return E_NOTIMPL;
499 }
500
501 HRESULT STDMETHODCALLTYPE CSearchBar::CacheItem(long paramC)
502 {
503 UNIMPLEMENTED;
504 return E_NOTIMPL;
505 }
506
507 // *** IDispatch methods ***
508 HRESULT STDMETHODCALLTYPE CSearchBar::GetTypeInfoCount(UINT *pctinfo)
509 {
510 UNIMPLEMENTED;
511 return E_NOTIMPL;
512 }
513
514 HRESULT STDMETHODCALLTYPE CSearchBar::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
515 {
516 UNIMPLEMENTED;
517 return E_NOTIMPL;
518 }
519
520 HRESULT STDMETHODCALLTYPE CSearchBar::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
521 {
522 UNIMPLEMENTED;
523 return E_NOTIMPL;
524 }
525
526 HRESULT STDMETHODCALLTYPE CSearchBar::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
527 {
528 TRACE("Unknown dispid requested: %08x\n", dispIdMember);
529 return E_INVALIDARG;
530 }