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