[SHELLFIND] Improve search bar UI
[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 #include <commoncontrols.h>
22 #include <../browseui.h>
23 #include <shellapi.h>
24 #include <exdispid.h>
25
26 WINE_DEFAULT_DEBUG_CHANNEL(shellfind);
27
28 #if 1
29 #undef UNIMPLEMENTED
30
31 #define UNIMPLEMENTED DbgPrint("%s is UNIMPLEMENTED!\n", __FUNCTION__)
32 #endif
33
34 CSearchBar::CSearchBar() :
35 pSite(NULL),
36 fVisible(FALSE),
37 bFocused(FALSE)
38 {
39 }
40
41 CSearchBar::~CSearchBar()
42 {
43 }
44
45 LRESULT CSearchBar::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
46 {
47 SetSearchInProgress(FALSE);
48
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));
53
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))
59 return hResult;
60
61 CComPtr<IShellService> pShellService;
62 hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IShellService, &pShellService));
63 if (FAILED_UNEXPECTEDLY(hResult))
64 return hResult;
65 hResult = fAddressEditBox->Init(hCombobox, fEditControl, 0, pSite);
66 if (FAILED_UNEXPECTEDLY(hResult))
67 return hResult;
68
69 CComPtr<IDispatch> pDispatch;
70 hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IDispatch, &pDispatch));
71 if (FAILED_UNEXPECTEDLY(hResult))
72 return hResult;
73 DISPPARAMS params = {0};
74 hResult = pDispatch->Invoke(DISPID_NAVIGATECOMPLETE2, GUID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, NULL);
75
76 hResult = pShellService->SetOwner(NULL);
77 if (FAILED_UNEXPECTEDLY(hResult))
78 return hResult;
79
80 return 0;
81 }
82
83 HRESULT CSearchBar::ExecuteCommand(CComPtr<IContextMenu>& menu, UINT nCmd)
84 {
85 CComPtr<IOleWindow> pBrowserOleWnd;
86 CMINVOKECOMMANDINFO cmi;
87 HWND browserWnd;
88 HRESULT hr;
89
90 hr = IUnknown_QueryService(pSite, SID_SShellBrowser, IID_PPV_ARG(IOleWindow, &pBrowserOleWnd));
91 if (FAILED_UNEXPECTEDLY(hr))
92 return hr;
93
94 hr = pBrowserOleWnd->GetWindow(&browserWnd);
95 if (FAILED_UNEXPECTEDLY(hr))
96 return hr;
97
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;
106
107 return menu->InvokeCommand(&cmi);
108 }
109
110
111 // *** ATL event handlers ***
112 LRESULT CSearchBar::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
113 {
114 bFocused = TRUE;
115 IUnknown_OnFocusChangeIS(pSite, reinterpret_cast<IUnknown*>(this), TRUE);
116 bHandled = FALSE;
117 return TRUE;
118 }
119
120 HRESULT CSearchBar::GetSearchResultsFolder(IShellBrowser **ppShellBrowser, HWND *pHwnd, IShellFolder **ppShellFolder)
121 {
122 HRESULT hr;
123 CComPtr<IShellBrowser> pShellBrowser;
124 if (!ppShellBrowser)
125 ppShellBrowser = &pShellBrowser;
126 if (!*ppShellBrowser)
127 {
128 hr = IUnknown_QueryService(m_pSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, ppShellBrowser));
129 if (FAILED_UNEXPECTEDLY(hr))
130 return hr;
131 }
132
133 CComPtr<IShellView> pShellView;
134 hr = (*ppShellBrowser)->QueryActiveShellView(&pShellView);
135 if (FAILED(hr) || !pShellView)
136 return hr;
137
138 CComPtr<IFolderView> pFolderView;
139 hr = pShellView->QueryInterface(IID_PPV_ARG(IFolderView, &pFolderView));
140 if (FAILED(hr) || !pFolderView)
141 return hr;
142
143 CComPtr<IShellFolder> pShellFolder;
144 if (!ppShellFolder)
145 ppShellFolder = &pShellFolder;
146 hr = pFolderView->GetFolder(IID_PPV_ARG(IShellFolder, ppShellFolder));
147 if (FAILED(hr) || !pShellFolder)
148 return hr;
149
150 CLSID clsid;
151 hr = IUnknown_GetClassID(*ppShellFolder, &clsid);
152 if (FAILED(hr))
153 return hr;
154 if (clsid != CLSID_FindFolder)
155 return E_FAIL;
156
157 if (pHwnd)
158 {
159 hr = pShellView->GetWindow(pHwnd);
160 if (FAILED_UNEXPECTEDLY(hr))
161 return hr;
162 }
163
164 return S_OK;
165 }
166
167 LRESULT CSearchBar::OnSearchButtonClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
168 {
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))
173 {
174 ShellMessageBoxW(_AtlBaseModule.GetResourceInstance(), m_hWnd, MAKEINTRESOURCEW(IDS_SEARCHINVALID), MAKEINTRESOURCEW(IDS_SEARCHLABEL), MB_OK | MB_ICONERROR, pSearchStart->szPath);
175 return TRUE;
176 }
177
178 CComPtr<IShellBrowser> pShellBrowser;
179 HRESULT hr = IUnknown_QueryService(pSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &pShellBrowser));
180 if (FAILED_UNEXPECTEDLY(hr))
181 return hr;
182
183 HWND hwnd;
184 if (FAILED(GetSearchResultsFolder(&pShellBrowser, &hwnd, NULL)))
185 {
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))
193 return hr;
194
195 CComHeapPtr<ITEMIDLIST> findFolderPidl;
196 hr = SHParseDisplayName(szShellGuid, NULL, &findFolderPidl, 0, NULL);
197 if (FAILED_UNEXPECTEDLY(hr))
198 return hr;
199
200 hr = pShellBrowser->BrowseObject(findFolderPidl, 0);
201 if (FAILED_UNEXPECTEDLY(hr))
202 return hr;
203
204 CComPtr<IShellFolder> pShellFolder;
205 hr = GetSearchResultsFolder(*pShellBrowser, &hwnd, &pShellFolder);
206 if (FAILED_UNEXPECTEDLY(hr))
207 return hr;
208
209 // Subscribe to search events
210 DWORD fAdviseCookie;
211 hr = AtlAdvise(pShellFolder, static_cast<IDispatch *>(this), DIID_DSearchCommandEvents, &fAdviseCookie);
212 if (FAILED_UNEXPECTEDLY(hr))
213 return hr;
214 }
215
216 ::PostMessageW(hwnd, WM_SEARCH_START, 0, (LPARAM) pSearchStart.Detach());
217
218 SetSearchInProgress(TRUE);
219
220 return TRUE;
221 }
222
223 LRESULT CSearchBar::OnStopButtonClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
224 {
225 HWND hwnd;
226 HRESULT hr = GetSearchResultsFolder(NULL, &hwnd, NULL);
227 if (SUCCEEDED(hr))
228 ::PostMessageW(hwnd, WM_SEARCH_STOP, 0, 0);
229
230 return TRUE;
231 }
232
233 BOOL CSearchBar::GetAddressEditBoxPath(WCHAR (&szPath)[MAX_PATH])
234 {
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)
239 {
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);
247
248 if (!wcscmp(szItemText, szPath) && SHGetPathFromIDListW((LPCITEMIDLIST)item.lParam, szPath))
249 {
250 return TRUE;
251 }
252 }
253
254 DWORD dwAttributes = GetFileAttributesW(szPath);
255 return dwAttributes != INVALID_FILE_ATTRIBUTES
256 && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY);
257 }
258
259 LRESULT CSearchBar::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
260 {
261 INT iWidth = LOWORD(lParam);
262 INT iPadding = 10;
263
264 ((CWindow)GetDlgItem(IDC_SEARCH_LABEL)).SetWindowPos(NULL, 0, 0, iWidth - iPadding, 40, SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
265
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++)
268 {
269 CWindow wFileName = (CWindow) inputs[i];
270 RECT rect;
271 wFileName.GetWindowRect(&rect);
272 POINT pt = { rect.left, rect.top };
273 ScreenToClient(&pt);
274 wFileName.MoveWindow(iPadding, pt.y, iWidth - iPadding * 2, rect.bottom - rect.top);
275 }
276
277 return 0;
278 }
279
280
281 // *** IOleWindow methods ***
282 HRESULT STDMETHODCALLTYPE CSearchBar::GetWindow(HWND *lphwnd)
283 {
284 if (!lphwnd)
285 return E_INVALIDARG;
286 *lphwnd = m_hWnd;
287 return S_OK;
288 }
289
290 HRESULT STDMETHODCALLTYPE CSearchBar::ContextSensitiveHelp(BOOL fEnterMode)
291 {
292 UNIMPLEMENTED;
293 return E_NOTIMPL;
294 }
295
296
297 // *** IDockingWindow methods ***
298 HRESULT STDMETHODCALLTYPE CSearchBar::CloseDW(DWORD dwReserved)
299 {
300 // We do nothing, we don't have anything to save yet
301 TRACE("CloseDW called\n");
302 return S_OK;
303 }
304
305 HRESULT STDMETHODCALLTYPE CSearchBar::ResizeBorderDW(const RECT *prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
306 {
307 /* Must return E_NOTIMPL according to MSDN */
308 return E_NOTIMPL;
309 }
310
311 HRESULT STDMETHODCALLTYPE CSearchBar::ShowDW(BOOL fShow)
312 {
313 fVisible = fShow;
314 ShowWindow(fShow);
315 return S_OK;
316 }
317
318
319 // *** IDeskBand methods ***
320 HRESULT STDMETHODCALLTYPE CSearchBar::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi)
321 {
322 if (!pdbi)
323 {
324 return E_INVALIDARG;
325 }
326
327 if (pdbi->dwMask & DBIM_MINSIZE)
328 {
329 pdbi->ptMinSize.x = 200;
330 pdbi->ptMinSize.y = 30;
331 }
332
333 if (pdbi->dwMask & DBIM_MAXSIZE)
334 {
335 pdbi->ptMaxSize.y = -1;
336 }
337
338 if (pdbi->dwMask & DBIM_INTEGRAL)
339 {
340 pdbi->ptIntegral.y = 1;
341 }
342
343 if (pdbi->dwMask & DBIM_ACTUAL)
344 {
345 pdbi->ptActual.x = 200;
346 pdbi->ptActual.y = 30;
347 }
348
349 if (pdbi->dwMask & DBIM_TITLE)
350 {
351 if (!LoadStringW(_AtlBaseModule.GetResourceInstance(), IDS_SEARCHLABEL, pdbi->wszTitle, _countof(pdbi->wszTitle)))
352 return HRESULT_FROM_WIN32(GetLastError());
353 }
354
355 if (pdbi->dwMask & DBIM_MODEFLAGS)
356 {
357 pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
358 }
359
360 if (pdbi->dwMask & DBIM_BKCOLOR)
361 {
362 pdbi->dwMask &= ~DBIM_BKCOLOR;
363 }
364 return S_OK;
365 }
366
367 LRESULT CALLBACK MyWindowProc(
368 _In_ HWND hwnd,
369 _In_ UINT uMsg,
370 _In_ WPARAM wParam,
371 _In_ LPARAM lParam
372 )
373 {
374 return 0;
375 }
376
377 // *** IObjectWithSite methods ***
378 HRESULT STDMETHODCALLTYPE CSearchBar::SetSite(IUnknown *pUnkSite)
379 {
380 HRESULT hr;
381 HWND parentWnd;
382
383 if (pUnkSite == pSite)
384 return S_OK;
385
386 TRACE("SetSite called \n");
387 if (!pUnkSite)
388 {
389 DestroyWindow();
390 m_hWnd = NULL;
391 }
392
393 if (pUnkSite != pSite)
394 {
395 pSite = NULL;
396 }
397
398 if(!pUnkSite)
399 return S_OK;
400
401 hr = IUnknown_GetWindow(pUnkSite, &parentWnd);
402 if (!SUCCEEDED(hr))
403 {
404 ERR("Could not get parent's window ! Status: %08lx\n", hr);
405 return E_INVALIDARG;
406 }
407
408 pSite = pUnkSite;
409
410 if (m_hWnd)
411 {
412 // Change its parent
413 SetParent(parentWnd);
414 }
415 else
416 {
417 CDialogImpl::Create(parentWnd);
418
419 }
420 return S_OK;
421 }
422
423 HRESULT STDMETHODCALLTYPE CSearchBar::GetSite(REFIID riid, void **ppvSite)
424 {
425 if (!ppvSite)
426 return E_POINTER;
427 *ppvSite = pSite;
428 return S_OK;
429 }
430
431
432 // *** IOleCommandTarget methods ***
433 HRESULT STDMETHODCALLTYPE CSearchBar::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
434 {
435 UNIMPLEMENTED;
436 return E_NOTIMPL;
437 }
438
439 HRESULT STDMETHODCALLTYPE CSearchBar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
440 {
441 UNIMPLEMENTED;
442 return E_NOTIMPL;
443 }
444
445
446 // *** IServiceProvider methods ***
447 HRESULT STDMETHODCALLTYPE CSearchBar::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
448 {
449 /* FIXME: we probably want to handle more services here */
450 return IUnknown_QueryService(pSite, SID_SShellBrowser, riid, ppvObject);
451 }
452
453
454 // *** IInputObject methods ***
455 HRESULT STDMETHODCALLTYPE CSearchBar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
456 {
457 if (fActivate)
458 {
459 //SetFocus();
460 SetActiveWindow();
461 }
462 // TODO: handle message
463 if(lpMsg)
464 {
465 TranslateMessage(lpMsg);
466 DispatchMessage(lpMsg);
467 }
468 return S_OK;
469 }
470
471 HRESULT STDMETHODCALLTYPE CSearchBar::HasFocusIO()
472 {
473 return bFocused ? S_OK : S_FALSE;
474 }
475
476 HRESULT STDMETHODCALLTYPE CSearchBar::TranslateAcceleratorIO(LPMSG lpMsg)
477 {
478 if (IsDialogMessage(lpMsg))
479 return S_OK;
480
481 if ((lpMsg->hwnd == m_hWnd || IsChild(lpMsg->hwnd)))
482 {
483 TranslateMessage(lpMsg);
484 DispatchMessage(lpMsg);
485 return S_OK;
486 }
487
488 return S_FALSE;
489 }
490
491 // *** IPersist methods ***
492 HRESULT STDMETHODCALLTYPE CSearchBar::GetClassID(CLSID *pClassID)
493 {
494 if (!pClassID)
495 return E_POINTER;
496 memcpy(pClassID, &CLSID_FileSearchBand, sizeof(CLSID));
497 return S_OK;
498 }
499
500
501 // *** IPersistStream methods ***
502 HRESULT STDMETHODCALLTYPE CSearchBar::IsDirty()
503 {
504 UNIMPLEMENTED;
505 return E_NOTIMPL;
506 }
507
508 HRESULT STDMETHODCALLTYPE CSearchBar::Load(IStream *pStm)
509 {
510 UNIMPLEMENTED;
511 return E_NOTIMPL;
512 }
513
514 HRESULT STDMETHODCALLTYPE CSearchBar::Save(IStream *pStm, BOOL fClearDirty)
515 {
516 UNIMPLEMENTED;
517 return E_NOTIMPL;
518 }
519
520 HRESULT STDMETHODCALLTYPE CSearchBar::GetSizeMax(ULARGE_INTEGER *pcbSize)
521 {
522 // TODO: calculate max size
523 UNIMPLEMENTED;
524 return E_NOTIMPL;
525 }
526
527
528 // *** IWinEventHandler methods ***
529 HRESULT STDMETHODCALLTYPE CSearchBar::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
530 {
531 return S_OK;
532 }
533
534 HRESULT STDMETHODCALLTYPE CSearchBar::IsWindowOwner(HWND hWnd)
535 {
536 return (hWnd == m_hWnd) ? S_OK : S_FALSE;
537 }
538
539 // *** IBandNavigate methods ***
540 HRESULT STDMETHODCALLTYPE CSearchBar::Select(long paramC)
541 {
542 UNIMPLEMENTED;
543 return E_NOTIMPL;
544 }
545
546 // *** INamespaceProxy ***
547 HRESULT STDMETHODCALLTYPE CSearchBar::GetNavigateTarget(long paramC, long param10, long param14)
548 {
549 UNIMPLEMENTED;
550 return E_NOTIMPL;
551 }
552
553 HRESULT STDMETHODCALLTYPE CSearchBar::Invoke(long paramC)
554 {
555 UNIMPLEMENTED;
556 return E_NOTIMPL;
557 }
558
559 HRESULT STDMETHODCALLTYPE CSearchBar::OnSelectionChanged(long paramC)
560 {
561 UNIMPLEMENTED;
562 return E_NOTIMPL;
563 }
564
565 HRESULT STDMETHODCALLTYPE CSearchBar::RefreshFlags(long paramC, long param10, long param14)
566 {
567 UNIMPLEMENTED;
568 return E_NOTIMPL;
569 }
570
571 HRESULT STDMETHODCALLTYPE CSearchBar::CacheItem(long paramC)
572 {
573 UNIMPLEMENTED;
574 return E_NOTIMPL;
575 }
576
577 // *** IDispatch methods ***
578 HRESULT STDMETHODCALLTYPE CSearchBar::GetTypeInfoCount(UINT *pctinfo)
579 {
580 UNIMPLEMENTED;
581 return E_NOTIMPL;
582 }
583
584 HRESULT STDMETHODCALLTYPE CSearchBar::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
585 {
586 UNIMPLEMENTED;
587 return E_NOTIMPL;
588 }
589
590 HRESULT STDMETHODCALLTYPE CSearchBar::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
591 {
592 UNIMPLEMENTED;
593 return E_NOTIMPL;
594 }
595
596 void CSearchBar::SetSearchInProgress(BOOL bInProgress)
597 {
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);
603 }
604
605 HRESULT STDMETHODCALLTYPE CSearchBar::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
606 {
607 if (dispIdMember == DISPID_SEARCHCOMPLETE || dispIdMember == DISPID_SEARCHABORT)
608 {
609 SetSearchInProgress(FALSE);
610 return S_OK;
611 }
612 return E_INVALIDARG;
613 }