Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4100 lines
130 KiB

  1. #include "pch.h"
  2. #include "uxtheme.h"
  3. #pragma hdrstop
  4. /*-----------------------------------------------------------------------------
  5. / Private data and helper functions
  6. /----------------------------------------------------------------------------*/
  7. //
  8. // ICommonQuery stuff
  9. //
  10. class CCommonQuery : public ICommonQuery, IObjectWithSite
  11. {
  12. private:
  13. LONG _cRef;
  14. IUnknown* _punkSite;
  15. public:
  16. CCommonQuery();
  17. ~CCommonQuery();
  18. // IUnknown
  19. STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObject);
  20. STDMETHOD_(ULONG, AddRef)();
  21. STDMETHOD_(ULONG, Release)();
  22. // ICommonQuery
  23. STDMETHOD(OpenQueryWindow)(THIS_ HWND hwndParent, LPOPENQUERYWINDOW pOpenQueryWnd, IDataObject** ppDataObject);
  24. // IObjectWithSite
  25. STDMETHODIMP SetSite(IUnknown* punk);
  26. STDMETHODIMP GetSite(REFIID riid, void **ppv);
  27. };
  28. //
  29. // View layout constants used by our dialogs
  30. //
  31. #define VIEWER_DEFAULT_CY 200
  32. #define COMBOEX_IMAGE_CX 16
  33. #define COMBOEX_IMAGE_CY 16
  34. typedef struct
  35. {
  36. HDSA hdsaPages; // DSA containing page entries
  37. DWORD dwFlags; // flags
  38. CLSID clsidForm; // CLSID identifier for this form
  39. LPTSTR pTitle; // title used for drop down / title bar
  40. HICON hIcon; // hIcon passed by caller
  41. INT iImage; // image list index of icon
  42. INT iForm; // visible index of form in control
  43. INT iPage; // currently selected page on form
  44. } QUERYFORM, * LPQUERYFORM;
  45. typedef struct
  46. {
  47. CLSID clsidForm; // CLSID to associate this form with
  48. LPCQPAGE pPage; // CQPAGE structures
  49. LPCQPAGEPROC pPageProc; // PageProc's used by thunking layer
  50. LPARAM lParam; // PAGEPROC lParam
  51. HWND hwndPage; // hWnd of page dialog // = NULL if none
  52. } QUERYFORMPAGE, * LPQUERYFORMPAGE;
  53. typedef struct
  54. {
  55. LPCQSCOPE pScope;
  56. INT iImage;
  57. } QUERYSCOPE, * LPQUERYSCOPE;
  58. class CQueryFrame : public IQueryFrame
  59. {
  60. friend INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg);
  61. friend INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  62. public:
  63. CQueryFrame(IUnknown* punkSite, LPOPENQUERYWINDOW pOpenQueryWindow, IDataObject** ppDataObject);
  64. ~CQueryFrame();
  65. // IUnknown
  66. STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObject);
  67. STDMETHOD_(ULONG, AddRef)();
  68. STDMETHOD_(ULONG, Release)();
  69. // Internal helper functions
  70. STDMETHOD(DoModal)(HWND hwndParent);
  71. // IQueryFrame
  72. STDMETHOD(AddScope)(THIS_ LPCQSCOPE pScope, INT i, BOOL fSelect);
  73. STDMETHOD(GetWindow)(THIS_ HWND* phWnd);
  74. STDMETHOD(InsertMenus)(THIS_ HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidth);
  75. STDMETHOD(RemoveMenus)(THIS_ HMENU hmenuShared);
  76. STDMETHOD(SetMenu)(THIS_ HMENU hmenuShared, HOLEMENU holereservedMenu);
  77. STDMETHOD(SetStatusText)(THIS_ LPCTSTR pszStatusText);
  78. STDMETHOD(StartQuery)(THIS_ BOOL fStarting);
  79. STDMETHOD(LoadQuery)(THIS_ IPersistQuery* pPersistQuery);
  80. STDMETHOD(SaveQuery)(THIS_ IPersistQuery* pPersistQuery);
  81. STDMETHOD(CallForm)(THIS_ LPCLSID pclsidForm, UINT uMsg, WPARAM wParam, LPARAM lParam);
  82. STDMETHOD(GetScope)(THIS_ LPCQSCOPE* ppScope);
  83. STDMETHOD(GetHandler)(THIS_ REFIID riid, void **ppv);
  84. protected:
  85. // Helper functions
  86. VOID CloseQueryFrame(HRESULT hres);
  87. INT FrameMessageBox(LPCTSTR pPrompt, UINT uType);
  88. // Message handlers
  89. HRESULT OnInitDialog(HWND hwnd);
  90. VOID DoEnableControls(VOID);
  91. LRESULT OnNotify(INT idCtrl, LPNMHDR pNotify);
  92. VOID OnSize(INT cx, INT cy);
  93. VOID OnGetMinMaxInfo(LPMINMAXINFO lpmmi);
  94. VOID OnCommand(WPARAM wParam, LPARAM lParam);
  95. VOID OnInitMenu(HMENU hMenu);
  96. VOID OnEnterMenuLoop(BOOL fEntering);
  97. VOID OnMenuSelect(HMENU hMenu, UINT uID);
  98. HRESULT OnFindNow(VOID);
  99. BOOL OnNewQuery(BOOL fAlwaysPrompt);
  100. HRESULT OnBrowse(VOID);
  101. HRESULT OnHelp(LPHELPINFO pHelpInfo);
  102. // Form/Scope helper fucntions
  103. HRESULT InsertScopeIntoList(LPCQSCOPE pScope, INT i, BOOL fAddToControl);
  104. HRESULT AddScopeToControl(LPQUERYSCOPE pQueryScope, INT i);
  105. HRESULT PopulateScopeControl(VOID);
  106. HRESULT GetSelectedScope(LPQUERYSCOPE* ppQueryScope);
  107. HRESULT AddFromIQueryForm(IQueryForm* pQueryForm, HKEY hkeyForm);
  108. HRESULT GatherForms(VOID);
  109. HRESULT GetForms(HKEY hKeyForms, LPTSTR pName);
  110. HRESULT PopulateFormControl(BOOL fIncludeHidden);
  111. HRESULT SelectForm(REFCLSID clsidForm);
  112. VOID SelectFormPage(LPQUERYFORM pQueryForm, INT iPage);
  113. HRESULT CallFormPages(LPQUERYFORM pQueryForm, UINT uMsg, WPARAM wParam, LPARAM lParam);
  114. LPQUERYFORM FindQueryForm(REFCLSID clsidForm);
  115. private:
  116. LONG _cRef; // reference count for the object
  117. IUnknown* _punkSite; // site object we need to pass through
  118. IQueryHandler* _pQueryHandler; // IQueryHandler object we need to interact with
  119. LPOPENQUERYWINDOW _pOpenQueryWnd; // copy of initial parameters provided by caller
  120. IDataObject** _ppDataObject; // receives the resulting data object from handler
  121. DWORD _dwHandlerViewFlags; // flags from the handler
  122. BOOL _fQueryRunning:1; // = 1 => query has been started, via IQueryFrame::StartQuery(TRUE)
  123. BOOL _fExitModalLoop:1; // = 1 => must leave modal loop
  124. BOOL _fScopesPopulated:1; // = 1 => scope control has been populated
  125. BOOL _fTrackingMenuBar:1; // = 1 => then we are tracking the menu bar, therefore send activates etc
  126. BOOL _fAddScopesNYI:1; // = 1 => did AddScopes return E_NOTIMPL
  127. BOOL _fScopesAddedAsync:1; // = 1 => scopes added async by the handler
  128. BOOL _fScopeImageListSet:1; // = 1 => scope image list has been set
  129. BOOL _fFormFirstEnable:1; // = 1 => enabling controls for first item, so ensure we set focus
  130. HRESULT _hResult; // result value stored by CloseQueryFrame
  131. HKEY _hkHandler; // registry key for the handler
  132. HWND _hwnd; // main window handle
  133. HWND _hwndResults; // result viewer
  134. HWND _hwndStatus; // status bar
  135. HWND _hwndFrame; // Query Pages tab control
  136. HWND _hwndLookForLabel; // "Find:"
  137. HWND _hwndLookFor; // Form combo
  138. HWND _hwndLookInLabel; // "In:"
  139. HWND _hwndLookIn; // Scope combo
  140. HWND _hwndBrowse; // "Browse"
  141. HWND _hwndFindNow; // "Find now"
  142. HWND _hwndStop; // "Stop"
  143. HWND _hwndNewQuery; // "New Query"
  144. HWND _hwndOK; // "OK"
  145. HWND _hwndCancel; // "Cancel"
  146. HWND _hwndFindAnimation; // Query issued animation
  147. HICON _hiconSmall; // large/small app icons
  148. HICON _hiconLarge;
  149. HMENU _hmenuFile; // handle of the frames menu bar
  150. HIMAGELIST _himlForms; // image list for query form objects
  151. SIZE _szMinTrack; // minimum track size of the window
  152. INT _dxFormAreaLeft; // offset to left edge of form area (from window left)
  153. INT _dxFormAreaRight; // offset to right edge of form area (from window right)
  154. INT _dxButtonsLeft; // offset to left edge of buttons (from window right)
  155. INT _dxAnimationLeft; // offset to left edge of aniimation (from window right)
  156. INT _dyResultsTop; // offset to top of results (from top of window)
  157. INT _dyOKTop; // offset to top of "OK" buttom (from results top)
  158. INT _dxGap; // gap between OK + Cancel / LookIn + Browse
  159. INT _dyGap; // gap between bottom of OK,Cancel and the frame.
  160. INT _cyStatus; // height of the status bar
  161. HDSA _hdsaForms; // forms DSA
  162. HDSA _hdsaPages; // pages DSA
  163. SIZE _szForm; // size of the (current form we are displaying)
  164. HDSA _hdsaScopes; // scopes DSA
  165. INT _iDefaultScope; // index of the defualt scope to select (into DSA)
  166. LPQUERYFORM _pCurrentForm; // == NULL if none / else -> form structure
  167. LPQUERYFORMPAGE _pCurrentFormPage; // == NULL if none / else -> page structure
  168. };
  169. //
  170. // Helper functions
  171. //
  172. INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  173. INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg);
  174. HRESULT _CallScopeProc(LPQUERYSCOPE pQueryScope, UINT uMsg, LPVOID pVoid);
  175. INT _FreeScope(LPQUERYSCOPE pQueryScope);
  176. INT _FreeScopeCB(LPVOID pItem, LPVOID pData);
  177. HRESULT _CallPageProc(LPQUERYFORMPAGE pQueryFormPage, UINT uMsg, WPARAM wParam, LPARAM lParam);
  178. INT _FreeQueryFormCB(LPVOID pItem, LPVOID pData);
  179. INT _FreeQueryForm(LPQUERYFORM pQueryForm);
  180. INT _FreeQueryFormPageCB(LPVOID pItem, LPVOID pData);
  181. INT _FreeQueryFormPage(LPQUERYFORMPAGE pQueryFormPage);
  182. HRESULT _AddFormsProc(LPARAM lParam, LPCQFORM pForm);
  183. HRESULT _AddPagesProc(LPARAM lParam, REFCLSID clsidForm, LPCQPAGE pPage);
  184. //
  185. // Help stuff
  186. //
  187. #define HELP_FILE (NULL)
  188. static DWORD const aHelpIDs[] =
  189. {
  190. 0, 0
  191. };
  192. //
  193. // constant strings
  194. //
  195. TCHAR const c_szCLSID[] = TEXT("CLSID");
  196. TCHAR const c_szForms[] = TEXT("Forms");
  197. TCHAR const c_szFlags[] = TEXT("Flags");
  198. TCHAR const c_szCommonQuery[] = TEXT("CommonQuery");
  199. TCHAR const c_szHandlerIs[] = TEXT("Handler");
  200. TCHAR const c_szFormIs[] = TEXT("Form");
  201. TCHAR const c_szSearchPaneHidden[] = TEXT("SearchPaneHidden");
  202. /*-----------------------------------------------------------------------------
  203. / CCommonQuery
  204. /----------------------------------------------------------------------------*/
  205. CCommonQuery::CCommonQuery() :
  206. _punkSite(NULL), _cRef(1)
  207. {
  208. DllAddRef();
  209. }
  210. CCommonQuery::~CCommonQuery()
  211. {
  212. DoRelease(_punkSite);
  213. DllRelease();
  214. }
  215. // QI handling
  216. ULONG CCommonQuery::AddRef()
  217. {
  218. return InterlockedIncrement(&_cRef);
  219. }
  220. ULONG CCommonQuery::Release()
  221. {
  222. if (InterlockedDecrement(&_cRef))
  223. return _cRef;
  224. delete this;
  225. return 0;
  226. }
  227. HRESULT CCommonQuery::QueryInterface(REFIID riid, void **ppv)
  228. {
  229. static const QITAB qit[] =
  230. {
  231. QITABENT(CCommonQuery, ICommonQuery), // IID_ICommonQuery
  232. QITABENT(CCommonQuery, IObjectWithSite), // IID_IObjectWithSite
  233. {0, 0 },
  234. };
  235. return QISearch(this, qit, riid, ppv);
  236. }
  237. STDAPI CCommonQuery_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  238. {
  239. CCommonQuery *pcq = new CCommonQuery;
  240. if (!pcq)
  241. return E_OUTOFMEMORY;
  242. HRESULT hres = pcq->QueryInterface(IID_IUnknown, (void **)ppunk);
  243. pcq->Release();
  244. return hres;
  245. }
  246. // ICommonQuery methods
  247. STDMETHODIMP CCommonQuery::OpenQueryWindow(THIS_ HWND hwndParent, LPOPENQUERYWINDOW pOpenQueryWnd, IDataObject** ppDataObject)
  248. {
  249. HRESULT hres;
  250. CQueryFrame* pQueryFrame = NULL;
  251. TraceEnter(TRACE_QUERY, "CCommonQuery::OpenQueryWindow");
  252. if (!pOpenQueryWnd || (hwndParent && !IsWindow(hwndParent)))
  253. ExitGracefully(hres, E_INVALIDARG, "Bad parameters");
  254. if (ppDataObject)
  255. *(ppDataObject) = NULL;
  256. pQueryFrame = new CQueryFrame(_punkSite, pOpenQueryWnd, ppDataObject);
  257. TraceAssert(pQueryFrame);
  258. if (!pQueryFrame)
  259. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to construct the query window object");
  260. hres = pQueryFrame->DoModal(hwndParent); // don't bother fail gracefully etc
  261. FailGracefully(hres, "Failed on calling DoModal");
  262. exit_gracefully:
  263. DoRelease(pQueryFrame);
  264. TraceLeaveResult(hres);
  265. }
  266. // IObjectWithSite
  267. STDMETHODIMP CCommonQuery::SetSite(IUnknown* punk)
  268. {
  269. HRESULT hres = S_OK;
  270. TraceEnter(TRACE_QUERY, "CCommonQuery::SetSite");
  271. DoRelease(_punkSite);
  272. if (punk)
  273. {
  274. TraceMsg("QIing for IUnknown from the site object");
  275. hres = punk->QueryInterface(IID_IUnknown, (void **)&_punkSite);
  276. FailGracefully(hres, "Failed to get IUnknown from the site object");
  277. }
  278. exit_gracefully:
  279. TraceLeaveResult(hres);
  280. }
  281. STDMETHODIMP CCommonQuery::GetSite(REFIID riid, void **ppv)
  282. {
  283. HRESULT hres;
  284. TraceEnter(TRACE_QUERY, "CCommonQuery::GetSite");
  285. if (!_punkSite)
  286. ExitGracefully(hres, E_NOINTERFACE, "No site to QI from");
  287. hres = _punkSite->QueryInterface(riid, ppv);
  288. FailGracefully(hres, "QI failed on the site unknown object");
  289. exit_gracefully:
  290. TraceLeaveResult(hres);
  291. }
  292. // IQueryFrame stuff
  293. CQueryFrame::CQueryFrame(IUnknown *punkSite, LPOPENQUERYWINDOW pOpenQueryWindow, IDataObject** ppDataObject) :
  294. _cRef(1), _punkSite(punkSite), _pOpenQueryWnd(pOpenQueryWindow),
  295. _ppDataObject(ppDataObject), _hiconLarge(NULL), _hiconSmall(NULL)
  296. {
  297. if (_punkSite)
  298. _punkSite->AddRef();
  299. DllAddRef();
  300. }
  301. CQueryFrame::~CQueryFrame()
  302. {
  303. DoRelease(_punkSite);
  304. if (_hiconLarge)
  305. DestroyIcon(_hiconLarge);
  306. if (_hiconSmall)
  307. DestroyIcon(_hiconSmall);
  308. if (_hkHandler)
  309. RegCloseKey(_hkHandler);
  310. if (_hmenuFile)
  311. DestroyMenu(_hmenuFile);
  312. if (_himlForms)
  313. ImageList_Destroy(_himlForms);
  314. if (_hdsaForms)
  315. {
  316. Trace(TEXT("Destroying QUERYFORM DSA (%d)"), DSA_GetItemCount(_hdsaForms));
  317. DSA_DestroyCallback(_hdsaForms, _FreeQueryFormCB, NULL);
  318. _hdsaForms = NULL;
  319. }
  320. if (_hdsaPages)
  321. {
  322. Trace(TEXT("Destroying QUERYFORMPAGE DSA (%d)"), DSA_GetItemCount(_hdsaPages));
  323. DSA_DestroyCallback(_hdsaPages, _FreeQueryFormPageCB, NULL);
  324. _hdsaPages = NULL;
  325. }
  326. if (_hdsaScopes)
  327. {
  328. Trace(TEXT("Destroying QUERYSCOPE DSA (%d)"), DSA_GetItemCount(_hdsaScopes));
  329. DSA_DestroyCallback(_hdsaScopes, _FreeScopeCB, NULL);
  330. _hdsaScopes = NULL;
  331. }
  332. _pCurrentForm = NULL;
  333. _pCurrentFormPage = NULL;
  334. // Now discard the handler and its window (if we have one), if
  335. // we don't do this they will never kill their objects
  336. if (_hwndResults)
  337. {
  338. DestroyWindow(_hwndResults);
  339. _hwndResults = NULL;
  340. }
  341. DllRelease();
  342. }
  343. // QI handling
  344. ULONG CQueryFrame::AddRef()
  345. {
  346. return InterlockedIncrement(&_cRef);
  347. }
  348. ULONG CQueryFrame::Release()
  349. {
  350. if (InterlockedDecrement(&_cRef))
  351. return _cRef;
  352. delete this;
  353. return 0;
  354. }
  355. HRESULT CQueryFrame::QueryInterface(REFIID riid, void **ppv)
  356. {
  357. static const QITAB qit[] =
  358. {
  359. QITABENT(CQueryFrame, IQueryFrame), // IID_IQueryFrame
  360. {0, 0 },
  361. };
  362. return QISearch(this, qit, riid, ppv);
  363. }
  364. /*-----------------------------------------------------------------------------
  365. / IQueryFrame
  366. /----------------------------------------------------------------------------*/
  367. STDMETHODIMP CQueryFrame::DoModal(HWND hwndParent)
  368. {
  369. HRESULT hres;
  370. HWND hwndFrame = NULL;
  371. HWND hwndFocus = NULL;
  372. HWND hwndTopOwner = hwndParent;
  373. MSG msg;
  374. INITCOMMONCONTROLSEX iccex;
  375. TraceEnter(TRACE_FRAME, "CQueryFrame::DoModal");
  376. // initialize with the query handler we need
  377. hres = CoCreateInstance(_pOpenQueryWnd->clsidHandler, NULL, CLSCTX_INPROC_SERVER, IID_IQueryHandler, (LPVOID*)&_pQueryHandler);
  378. FailGracefully(hres, "Failed to get IQueryHandler for the given CLSID");
  379. hres = _pQueryHandler->Initialize(this, _pOpenQueryWnd->dwFlags, _pOpenQueryWnd->pHandlerParameters);
  380. FailGracefully(hres, "Failed to initialize the handler");
  381. // mimic the behaviour of DialogBox by working out which control previously
  382. // had focus, which window to disable and then running a message
  383. // pump for our dialog. Having done this we can then restore the state
  384. // back to something sensible.
  385. _fExitModalLoop = FALSE; // can be changed from hear down
  386. iccex.dwSize = SIZEOF(iccex);
  387. iccex.dwICC = ICC_USEREX_CLASSES;
  388. InitCommonControlsEx(&iccex);
  389. if (_pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHUI)
  390. {
  391. hwndFrame = CreateDialogParam(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDD_FILTER),
  392. hwndParent,
  393. QueryWnd_DlgProc, (LPARAM)this);
  394. }
  395. else
  396. {
  397. hwndFrame = CreateDialogParam(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDD_FIND),
  398. hwndParent,
  399. QueryWnd_DlgProc, (LPARAM)this);
  400. }
  401. if (!hwndFrame)
  402. ExitGracefully(hres, E_FAIL, "Failed to create the dialog");
  403. hwndFocus = GetFocus();
  404. if (hwndTopOwner)
  405. {
  406. // walk up the window stack looking for the window to be disabled, this must
  407. // be the top-most non-child window. If the resulting window is either
  408. // the desktop or is already disabled then don't bother.
  409. while (GetWindowLong(hwndTopOwner, GWL_STYLE) & WS_CHILD)
  410. hwndTopOwner = GetParent(hwndTopOwner);
  411. TraceAssert(hwndTopOwner);
  412. if ((hwndTopOwner == GetDesktopWindow())
  413. || EnableWindow(hwndTopOwner, FALSE))
  414. {
  415. TraceMsg("Parent is disabled or the desktop window, therefore setting to NULL");
  416. hwndTopOwner = NULL;
  417. }
  418. }
  419. ShowWindow(hwndFrame, SW_SHOW); // show the query window
  420. while (!_fExitModalLoop && GetMessage(&msg, NULL, 0, 0) > 0)
  421. {
  422. if (!QueryWnd_MessageProc(hwndFrame, &msg) && !IsDialogMessage(hwndFrame, &msg))
  423. {
  424. TranslateMessage(&msg);
  425. DispatchMessage(&msg);
  426. }
  427. }
  428. // Now tidy up, make the parent the active window, enable the top most
  429. // window if there is one and restore focus as required.
  430. if (hwndTopOwner)
  431. EnableWindow(hwndTopOwner, TRUE);
  432. if (hwndParent && (GetActiveWindow() == hwndFrame))
  433. {
  434. TraceMsg("Passing activation to parent");
  435. SetActiveWindow(hwndParent);
  436. }
  437. if (IsWindow(hwndFocus))
  438. SetFocus(hwndFocus);
  439. DestroyWindow(hwndFrame); // discard the current frame window
  440. exit_gracefully:
  441. DoRelease(_pQueryHandler);
  442. TraceLeaveResult(_hResult);
  443. }
  444. /*---------------------------------------------------------------------------*/
  445. STDMETHODIMP CQueryFrame::AddScope(THIS_ LPCQSCOPE pScope, INT i, BOOL fSelect)
  446. {
  447. HRESULT hres;
  448. TraceEnter(TRACE_FRAME, "CQueryFrame::AddScope");
  449. if (!pScope)
  450. ExitGracefully(hres, E_INVALIDARG, "No scope to add to the list");
  451. // Add the scope to the control and then ensure that we either have
  452. // its index stored (for default selection) or we select the
  453. // item.
  454. if (!_hdsaScopes || !DSA_GetItemCount(_hdsaScopes))
  455. {
  456. TraceMsg("First scope being added, thefore selecting");
  457. fSelect = TRUE;
  458. }
  459. hres = InsertScopeIntoList(pScope, i, _fScopesPopulated);
  460. FailGracefully(hres, "Failed to add scope to control");
  461. if (fSelect)
  462. {
  463. if (!_fScopesPopulated)
  464. {
  465. Trace(TEXT("Storing default scope index %d"), ShortFromResult(hres));
  466. _iDefaultScope = ShortFromResult(hres);
  467. }
  468. else
  469. {
  470. Trace(TEXT("Selecting scope index %d"), ShortFromResult(hres));
  471. ComboBox_SetCurSel(_hwndLookIn, ShortFromResult(hres));
  472. }
  473. }
  474. // hres = S_OK;
  475. exit_gracefully:
  476. TraceLeaveResult(hres);
  477. }
  478. /*---------------------------------------------------------------------------*/
  479. STDMETHODIMP CQueryFrame::GetWindow(THIS_ HWND* phWnd)
  480. {
  481. TraceEnter(TRACE_FRAME, "CQueryFrame::GetWindow");
  482. TraceAssert(phWnd);
  483. *phWnd = _hwnd;
  484. TraceLeaveResult(S_OK);
  485. }
  486. /*---------------------------------------------------------------------------*/
  487. // Add a menu group to the given menu bar, updating the width index accordingly
  488. // so that other people can merge in accordingly
  489. VOID _DoInsertMenu(HMENU hMenu, INT iIndexTo, HMENU hMenuToInsert, INT iIndexFrom)
  490. {
  491. TCHAR szBuffer[MAX_PATH];
  492. HMENU hPopupMenu = NULL;
  493. TraceEnter(TRACE_FRAME, "_DoInsertMenu");
  494. hPopupMenu = CreatePopupMenu();
  495. if (hPopupMenu)
  496. {
  497. Shell_MergeMenus(hPopupMenu, GetSubMenu(hMenuToInsert, iIndexFrom), 0x0, 0x0, 0x7fff, 0);
  498. GetMenuString(hMenuToInsert, iIndexFrom, szBuffer, ARRAYSIZE(szBuffer), MF_BYPOSITION);
  499. InsertMenu(hMenu, iIndexTo, MF_BYPOSITION|MF_POPUP, (UINT_PTR)hPopupMenu, szBuffer);
  500. }
  501. TraceLeave();
  502. }
  503. VOID _AddMenuGroup(HMENU hMenuShared, HMENU hMenuGroup, LONG iInsertAt, LPLONG pWidth)
  504. {
  505. HRESULT hres;
  506. TCHAR szBuffer[MAX_PATH];
  507. HMENU hMenu;
  508. INT i;
  509. TraceEnter(TRACE_FRAME, "_AddMenuGroup");
  510. TraceAssert(hMenuShared);
  511. TraceAssert(hMenuGroup);
  512. TraceAssert(pWidth);
  513. for (i = 0 ; i < GetMenuItemCount(hMenuGroup) ; i++)
  514. {
  515. _DoInsertMenu(hMenuShared, iInsertAt+i, hMenuGroup, i);
  516. *pWidth += 1;
  517. }
  518. TraceLeave();
  519. }
  520. STDMETHODIMP CQueryFrame::InsertMenus(THIS_ HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidth)
  521. {
  522. HRESULT hres;
  523. TraceEnter(TRACE_FRAME, "CQueryFrame::InsertMenus");
  524. if (!hmenuShared || !lpMenuWidth)
  525. ExitGracefully(hres, E_INVALIDARG, "Unable to insert menus");
  526. // if we don't have the menu bar already loaded then lets load it,
  527. // having done that we can then add our menu to the bar (we only
  528. // provide entries for the file menu).
  529. if (!_hmenuFile)
  530. {
  531. _hmenuFile = LoadMenu(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDR_FILEMENUGROUP));
  532. if (!_hmenuFile)
  533. ExitGracefully(hres, E_FAIL, "Failed to load base menu defn");
  534. }
  535. _AddMenuGroup(hmenuShared, _hmenuFile, 0, &lpMenuWidth->width[0]);
  536. hres = S_OK; // success
  537. exit_gracefully:
  538. TraceLeaveResult(hres);
  539. }
  540. /*---------------------------------------------------------------------------*/
  541. STDMETHODIMP CQueryFrame::RemoveMenus(THIS_ HMENU hmenuShared)
  542. {
  543. TraceEnter(TRACE_FRAME, "CQueryFrame::RemoveMenus");
  544. // We don't need to implement this as we copy or menus into the
  545. // menu that the handler supplies - fix DSQUERY if this ever
  546. // changes.
  547. TraceLeaveResult(S_OK);
  548. }
  549. /*---------------------------------------------------------------------------*/
  550. STDMETHODIMP CQueryFrame::SetMenu(THIS_ HMENU hmenuShared, HOLEMENU holereservedMenu)
  551. {
  552. TraceEnter(TRACE_FRAME, "CQueryFrame::SetMenu");
  553. if (!(_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS))
  554. {
  555. HMENU hmenuOld = ::GetMenu(_hwnd);
  556. if (!hmenuShared)
  557. hmenuShared = _hmenuFile;
  558. ::SetMenu(_hwnd, hmenuShared);
  559. DoEnableControls(); // ensure the menu state is valid
  560. ::DrawMenuBar(_hwnd);
  561. if (hmenuOld && (hmenuOld != _hmenuFile) && (hmenuOld != hmenuShared))
  562. {
  563. TraceMsg("Destroying old menu");
  564. DestroyMenu(hmenuOld);
  565. }
  566. }
  567. TraceLeaveResult(S_OK);
  568. }
  569. /*---------------------------------------------------------------------------*/
  570. STDMETHODIMP CQueryFrame::SetStatusText(THIS_ LPCTSTR pszStatusText)
  571. {
  572. TraceEnter(TRACE_FRAME, "CQueryFrame::SetStatusText");
  573. Trace(TEXT("Setting status text to: %s"), pszStatusText);
  574. if (_hwndStatus)
  575. SendMessage(_hwndStatus, SB_SETTEXT, 0, (LPARAM)pszStatusText);
  576. TraceLeaveResult(S_OK);
  577. }
  578. /*---------------------------------------------------------------------------*/
  579. STDMETHODIMP CQueryFrame::StartQuery(THIS_ BOOL fStarting)
  580. {
  581. TraceEnter(TRACE_FRAME, "CQueryFrame::StartQuery");
  582. if (fStarting)
  583. {
  584. Animate_Play(_hwndFindAnimation, 0, -1, -1);
  585. }
  586. else
  587. {
  588. Animate_Stop(_hwndFindAnimation);
  589. Animate_Seek(_hwndFindAnimation, 0); // go to start
  590. }
  591. if (_pQueryHandler)
  592. _pQueryHandler->ActivateView(CQRVA_STARTQUERY, (WPARAM)fStarting, 0);
  593. // now set the controls into a sensble state
  594. _fQueryRunning = fStarting;
  595. DoEnableControls();
  596. TraceLeaveResult(S_OK);
  597. }
  598. /*---------------------------------------------------------------------------*/
  599. STDMETHODIMP CQueryFrame::LoadQuery(THIS_ IPersistQuery* pPersistQuery)
  600. {
  601. HRESULT hres;
  602. TCHAR szGUID[GUIDSTR_MAX+1];
  603. LPQUERYFORM pQueryForm = NULL;
  604. GUID guid;
  605. TraceEnter(TRACE_FRAME, "CQueryFrame::LoadQuery");
  606. _pQueryHandler->StopQuery(); // ensure that the handler stops its processing
  607. // Attempt to read the handler GUID from the query stream, first try reading it as
  608. // as string then parsing it into something that we can use, if that fails then
  609. // try again, but this time read it as a structure.
  610. //
  611. // having aquired the GUID for the handler make sure that we have the correct handler
  612. // selected.
  613. if (FAILED(pPersistQuery->ReadString(c_szCommonQuery, c_szHandlerIs, szGUID, ARRAYSIZE(szGUID))) ||
  614. !GetGUIDFromString(szGUID, &guid))
  615. {
  616. TraceMsg("Trying new style handler GUID as struct");
  617. hres = pPersistQuery->ReadStruct(c_szCommonQuery, c_szHandlerIs, &guid, SIZEOF(guid));
  618. FailGracefully(hres, "Failed to read handler GUID as struct");
  619. }
  620. if (guid != _pOpenQueryWnd->clsidHandler)
  621. ExitGracefully(hres, E_FAIL, "Persisted handler GUID and specified handler GUID don't match");
  622. hres = _pQueryHandler->LoadQuery(pPersistQuery);
  623. FailGracefully(hres, "Handler failed to load its query data");
  624. // Get the form ID, then look up the form to see if we have one that matches,
  625. // if not then we cannot load any thing else. If we do haved that form then
  626. // ensure that we clear it and then load away.
  627. if (FAILED(pPersistQuery->ReadString(c_szCommonQuery, c_szFormIs, szGUID, ARRAYSIZE(szGUID))) ||
  628. !GetGUIDFromString(szGUID, &guid))
  629. {
  630. TraceMsg("Trying new style form GUID as struct");
  631. hres = pPersistQuery->ReadStruct(c_szCommonQuery, c_szFormIs, &guid, SIZEOF(guid));
  632. FailGracefully(hres, "Failed to read handler GUID as struct");
  633. }
  634. hres = SelectForm(guid);
  635. FailGracefully(hres, "Failed to select the query form");
  636. if (hres == S_FALSE)
  637. ExitGracefully(hres, E_FAIL, "Failed to select the query form to read the query info");
  638. hres = CallFormPages(_pCurrentForm, CQPM_CLEARFORM, 0, 0);
  639. FailGracefully(hres, "Failed to clear form before loading");
  640. // Load the persisted query from the stream, coping correctly with the
  641. // UNICODE / ANSI issue. We will be passed an IPersistQuery object which
  642. // we must then thunk accordingly if we are UNICODE for the pages we
  643. // are going to talk to.
  644. hres = CallFormPages(_pCurrentForm, CQPM_PERSIST, TRUE, (LPARAM)pPersistQuery);
  645. FailGracefully(hres, "Failed to load page data (UNICODE)");
  646. hres = S_OK; // success
  647. exit_gracefully:
  648. if (SUCCEEDED(hres))
  649. {
  650. TraceMsg("Query loaded successfully, select form query");
  651. SelectForm(guid);
  652. }
  653. TraceLeaveResult(hres);
  654. }
  655. /*---------------------------------------------------------------------------*/
  656. STDMETHODIMP CQueryFrame::SaveQuery(THIS_ IPersistQuery* pPersistQuery)
  657. {
  658. HRESULT hres;
  659. LPQUERYSCOPE pQueryScope;
  660. TCHAR szBuffer[MAX_PATH];
  661. TraceEnter(TRACE_FRAME, "CQueryFrame::SaveQuery");
  662. if (!pPersistQuery)
  663. ExitGracefully(hres, E_INVALIDARG, "No pPersistQuery object to write into");
  664. pPersistQuery->Clear(); // flush the contents
  665. hres = pPersistQuery->WriteStruct(c_szCommonQuery, c_szHandlerIs,
  666. &_pOpenQueryWnd->clsidHandler,
  667. SIZEOF(_pOpenQueryWnd->clsidHandler));
  668. FailGracefully(hres, "Failed to write handler GUID");
  669. hres = pPersistQuery->WriteStruct(c_szCommonQuery, c_szFormIs,
  670. &_pCurrentForm->clsidForm,
  671. SIZEOF(_pCurrentForm->clsidForm));
  672. FailGracefully(hres, "Failed to write form GUID");
  673. // Allow the handler to persist itself into the the stream, this includes
  674. // giving it the current scope to store.
  675. hres = GetSelectedScope(&pQueryScope);
  676. FailGracefully(hres, "Failed to get the scope from the LookIn control");
  677. hres = _pQueryHandler->SaveQuery(pPersistQuery, pQueryScope->pScope);
  678. FailGracefully(hres, "Failed when calling handler to persist itself");
  679. // Save the query into the stream, coping correctly with the
  680. // UNICODE / ANSI issue. We will be passed an IPersistQuery object which
  681. // we must then thunk accordingly if we are UNICODE for the pages we
  682. // are going to talk to.
  683. hres = CallFormPages(_pCurrentForm, CQPM_PERSIST, FALSE, (LPARAM)pPersistQuery);
  684. FailGracefully(hres, "Failed to load page data (UNICODE)");
  685. hres = S_OK;
  686. exit_gracefully:
  687. TraceLeaveResult(hres);
  688. }
  689. /*---------------------------------------------------------------------------*/
  690. STDMETHODIMP CQueryFrame::CallForm(THIS_ LPCLSID pclsidForm, UINT uMsg, WPARAM wParam, LPARAM lParam)
  691. {
  692. HRESULT hres;
  693. LPQUERYFORM pQueryForm = _pCurrentForm;
  694. TraceEnter(TRACE_FRAME, "CQueryFrame::CallForm");
  695. if (pclsidForm)
  696. {
  697. pQueryForm = FindQueryForm(*pclsidForm);
  698. TraceAssert(pQueryForm);
  699. }
  700. if (!pQueryForm)
  701. ExitGracefully(hres, E_FAIL, "Failed to find query form for given CLSID");
  702. hres = CallFormPages(pQueryForm, uMsg, wParam, lParam);
  703. FailGracefully(hres, "Failed when calling CallFormPages");
  704. // hres = S_OK;
  705. exit_gracefully:
  706. TraceLeaveResult(hres);
  707. }
  708. /*---------------------------------------------------------------------------*/
  709. STDMETHODIMP CQueryFrame::GetScope(THIS_ LPCQSCOPE* ppScope)
  710. {
  711. HRESULT hres;
  712. LPQUERYSCOPE pQueryScope;
  713. TraceEnter(TRACE_FRAME, "CQueryFrame::GetScope");
  714. if (!ppScope)
  715. ExitGracefully(hres, E_INVALIDARG, "ppScope == NULL, thats bad");
  716. hres = GetSelectedScope(&pQueryScope);
  717. FailGracefully(hres, "Failed to get the current scope");
  718. *ppScope = (LPCQSCOPE)CoTaskMemAlloc(pQueryScope->pScope->cbStruct);
  719. TraceAssert(*ppScope);
  720. if (!*ppScope)
  721. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate the scope block");
  722. memcpy(*ppScope, pQueryScope->pScope, pQueryScope->pScope->cbStruct);
  723. hres = S_OK;
  724. exit_gracefully:
  725. TraceLeaveResult(hres);
  726. }
  727. /*---------------------------------------------------------------------------*/
  728. STDMETHODIMP CQueryFrame::GetHandler(THIS_ REFIID riid, void **ppv)
  729. {
  730. HRESULT hres;
  731. TraceEnter(TRACE_FRAME, "CQueryFrame::GetHandler");
  732. if (!_pQueryHandler)
  733. ExitGracefully(hres, E_UNEXPECTED, "_pQueryHandler is NULL");
  734. hres = _pQueryHandler->QueryInterface(riid, ppv);
  735. exit_gracefully:
  736. TraceLeaveResult(hres);
  737. }
  738. /*-----------------------------------------------------------------------------
  739. / Dialog box handler functions (core guts)
  740. /----------------------------------------------------------------------------*/
  741. #define REAL_WINDOW(hwnd) \
  742. (hwnd && \
  743. IsWindowVisible(hwnd) && \
  744. IsWindowEnabled(hwnd) && \
  745. (GetWindowLong(hwnd, GWL_STYLE) & WS_TABSTOP))
  746. HWND _NextTabStop(HWND hwndSearch, BOOL fShift)
  747. {
  748. HWND hwnd;
  749. Trace(TEXT("hwndSearch %08x, fShift %d"), hwndSearch, fShift);
  750. // do we have a window to search into?
  751. while (hwndSearch)
  752. {
  753. // if we have a window then lets check to see if it has any children?
  754. hwnd = GetWindow(hwndSearch, GW_CHILD);
  755. Trace(TEXT("Child of %08x is %08x"), hwndSearch, hwnd);
  756. if (hwnd)
  757. {
  758. // it has a child therefore lets to go its first/last
  759. // and continue the search there for a window that
  760. // matches the criteria we are looking for.
  761. hwnd = GetWindow(hwnd, fShift ? GW_HWNDLAST:GW_HWNDFIRST);
  762. if (!REAL_WINDOW(hwnd))
  763. {
  764. Trace(TEXT("Trying to recurse into %08x"), hwnd);
  765. hwnd = _NextTabStop(hwnd, fShift);
  766. }
  767. Trace(TEXT("Tabstop child of %08x is %08x"), hwndSearch, hwnd);
  768. }
  769. // after all that is hwnd a valid window? if so then pass
  770. // that back out to the caller.
  771. if (REAL_WINDOW(hwnd))
  772. {
  773. Trace(TEXT("Child tab stop was %08x"), hwnd);
  774. return hwnd;
  775. }
  776. // do we have a sibling? if so then lets return that otherwise
  777. // lets just continue to search until we either run out of windows
  778. // or hit something interesting
  779. hwndSearch = GetWindow(hwndSearch, fShift ? GW_HWNDPREV:GW_HWNDNEXT);
  780. if (REAL_WINDOW(hwndSearch))
  781. {
  782. Trace(TEXT("Next tab stop was %08x"), hwndSearch);
  783. return hwndSearch;
  784. }
  785. }
  786. return hwndSearch;
  787. }
  788. INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg)
  789. {
  790. LRESULT lResult = 0;
  791. CQueryFrame* pQueryFrame = NULL;
  792. NMHDR nmhdr;
  793. pQueryFrame = (CQueryFrame*)GetWindowLongPtr(hwnd, DWLP_USER);
  794. if (!pQueryFrame)
  795. return 0;
  796. if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB))
  797. {
  798. BOOL fCtrl = GetAsyncKeyState(VK_CONTROL) < 0;
  799. BOOL fShift = GetAsyncKeyState(VK_SHIFT) < 0;
  800. // ensure that the focus rectangles are shown
  801. #if (_WIN32_WINNT >= 0x0500)
  802. SendMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0);
  803. #endif
  804. if (fCtrl)
  805. {
  806. // if this is a key press within the parent then lets ensure that we
  807. // allow the tab control to change the page correctly. otherwise lets
  808. // just hack around the problem of the result view not handling tabs
  809. // properly.
  810. INT iCur = TabCtrl_GetCurSel(pQueryFrame->_hwndFrame);
  811. INT nPages = TabCtrl_GetItemCount(pQueryFrame->_hwndFrame);
  812. if (fShift)
  813. iCur += (nPages-1);
  814. else
  815. iCur++;
  816. pQueryFrame->SelectFormPage(pQueryFrame->_pCurrentForm, iCur % nPages);
  817. return 1; // we processed it
  818. }
  819. else
  820. {
  821. // is the window that has the focus a child of the result view, if
  822. // so then we must attempt to pass focus to its 1st child and hope
  823. // that is can do the rest.
  824. HWND hwndNext, hwnd = GetFocus();
  825. Trace(TEXT("Current focus window %08x"), hwnd);
  826. while (hwnd && GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD)
  827. {
  828. hwndNext = _NextTabStop(hwnd, fShift);
  829. Trace(TEXT("_NextTabStop yeilds %08x from %08x"), hwndNext, hwnd);
  830. if (hwndNext)
  831. {
  832. Trace(TEXT("SetFocus on child %08x"), hwndNext);
  833. SetFocus(hwndNext);
  834. return 1;
  835. }
  836. while (TRUE)
  837. {
  838. // look up the parent list trying to find a window that we can
  839. // tab back into. We must watch that when we walk out of the
  840. // child list we loop correctly at the top of the list.
  841. hwndNext = GetParent(hwnd);
  842. Trace(TEXT("Parent hwnd %08x"), hwndNext);
  843. if (GetWindowLong(hwndNext, GWL_STYLE) & WS_CHILD)
  844. {
  845. // the parent window is a child, therefore we can check
  846. // to see if has any siblings.
  847. Trace(TEXT("hwndNext is a child, therefore hwndNext of it is %08x"),
  848. GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT));
  849. if (GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT))
  850. {
  851. hwnd = GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT);
  852. Trace(TEXT("Silbing window found %08x"), hwnd);
  853. break;
  854. }
  855. else
  856. {
  857. TraceMsg("There was no sibling, therefore continuing parent loop");
  858. hwnd = hwndNext;
  859. }
  860. }
  861. else
  862. {
  863. // we have hit the parent window of it all (the overlapped one)
  864. // therefore we must attempt to go to its first child. Walk forward
  865. // in the stack looking for a window that matches the
  866. // "REAL_WINDOW" conditions.
  867. hwnd = GetWindow(hwnd, fShift ? GW_HWNDLAST:GW_HWNDFIRST);
  868. Trace(TEXT("First child is %08x"), hwnd);
  869. break; // continue the sibling search etc
  870. }
  871. }
  872. if (REAL_WINDOW(hwnd))
  873. {
  874. SetFocus(hwnd);
  875. return 1;
  876. }
  877. }
  878. }
  879. }
  880. return 0;
  881. }
  882. //
  883. // Main DLGPROC
  884. //
  885. INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  886. {
  887. CQueryFrame* pQueryFrame;
  888. if (uMsg == WM_INITDIALOG)
  889. {
  890. HRESULT hres;
  891. pQueryFrame = (CQueryFrame*)lParam;
  892. SetWindowLongPtr(hwnd, DWLP_USER, (LRESULT)pQueryFrame);
  893. hres = pQueryFrame->OnInitDialog(hwnd);
  894. Trace(TEXT("OnInitDialog returns %08x"), hres);
  895. if (FAILED(hres))
  896. {
  897. TraceMsg("Failed to initialize the dialog, Destroying the window");
  898. pQueryFrame->CloseQueryFrame(hres);
  899. DestroyWindow(hwnd);
  900. }
  901. }
  902. else
  903. {
  904. pQueryFrame = (CQueryFrame*)GetWindowLongPtr(hwnd, DWLP_USER);
  905. if (!pQueryFrame)
  906. goto exit_gracefully;
  907. switch (uMsg)
  908. {
  909. case WM_ERASEBKGND:
  910. {
  911. HDC hdc = (HDC)wParam;
  912. RECT rc;
  913. // if we have a DC then lets fill it, and if we have a
  914. // query form then lets paint the divider between the menu bar and
  915. // this area.
  916. if (hdc)
  917. {
  918. GetClientRect(hwnd, &rc);
  919. FillRect(hdc, &rc, (HBRUSH)(COLOR_3DFACE+1));
  920. if (!(pQueryFrame->_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS))
  921. DrawEdge(hdc, &rc, EDGE_ETCHED, BF_TOP);
  922. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  923. }
  924. return 1;
  925. }
  926. case WM_NOTIFY:
  927. return pQueryFrame->OnNotify((int)wParam, (LPNMHDR)lParam);
  928. case WM_SIZE:
  929. pQueryFrame->OnSize(LOWORD(lParam), HIWORD(lParam));
  930. return(1);
  931. case WM_GETMINMAXINFO:
  932. pQueryFrame->OnGetMinMaxInfo((LPMINMAXINFO)lParam);
  933. return(1);
  934. case WM_COMMAND:
  935. pQueryFrame->OnCommand(wParam, lParam);
  936. return(1);
  937. case WM_ACTIVATE:
  938. pQueryFrame->_pQueryHandler->ActivateView(wParam ? CQRVA_ACTIVATE : CQRVA_DEACTIVATE, 0, 0);
  939. return(1);
  940. case WM_INITMENU:
  941. pQueryFrame->OnInitMenu((HMENU)wParam);
  942. return(1);
  943. case WM_SETCURSOR:
  944. {
  945. // do we have any scopes? if not then let us display the wait
  946. // cursor for the user. if we have a query running then lets
  947. // display the app start cursor.
  948. if (!pQueryFrame->_fAddScopesNYI &&
  949. !ComboBox_GetCount(pQueryFrame->_hwndLookIn))
  950. {
  951. if (LOWORD(lParam) == HTCLIENT)
  952. {
  953. SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT)));
  954. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  955. return 1;
  956. }
  957. }
  958. break;
  959. }
  960. case WM_INITMENUPOPUP:
  961. {
  962. // only send sub-menu activates if the menu bar is being tracked, this is
  963. // handled within OnInitMenu, if we are not tracking the menu then we
  964. // assume that the client has already primed the menu and that they are
  965. // using some kind of popup menu.
  966. if (pQueryFrame->_fTrackingMenuBar)
  967. pQueryFrame->_pQueryHandler->ActivateView(CQRVA_INITMENUBARPOPUP, wParam, lParam);
  968. return(1);
  969. }
  970. case WM_ENTERMENULOOP:
  971. pQueryFrame->OnEnterMenuLoop(TRUE);
  972. return(1);
  973. case WM_EXITMENULOOP:
  974. pQueryFrame->OnEnterMenuLoop(FALSE);
  975. return(1);
  976. case WM_MENUSELECT:
  977. {
  978. UINT uID = LOWORD(wParam);
  979. UINT uFlags = HIWORD(wParam);
  980. HMENU hMenu = (HMENU)lParam;
  981. // the command opens a popup menu the the uID is actually
  982. // the index into the menu, so lets ensure that we pick
  983. // up the correct ID by calling GetMenuItemInfo, note that
  984. // GetMenuItemID returns -1 in this case which is totally
  985. // useless.
  986. if (uFlags & MF_POPUP)
  987. {
  988. MENUITEMINFO mii;
  989. ZeroMemory(&mii, SIZEOF(mii));
  990. mii.cbSize = SIZEOF(mii);
  991. mii.fMask = MIIM_ID;
  992. if (GetMenuItemInfo(hMenu, uID, TRUE, &mii))
  993. uID = mii.wID;
  994. }
  995. pQueryFrame->OnMenuSelect(hMenu, uID);
  996. return(1);
  997. }
  998. case WM_SYSCOMMAND:
  999. if (wParam == SC_CLOSE)
  1000. {
  1001. pQueryFrame->CloseQueryFrame(S_FALSE);
  1002. return(1);
  1003. }
  1004. break;
  1005. case WM_CONTEXTMENU:
  1006. {
  1007. // there are a couple of controls we don't care about for the
  1008. // frame, so lets ignore those when passing the CQRVA_CONTEXTMENU
  1009. // through to the handler.
  1010. POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
  1011. ScreenToClient((HWND)wParam, &pt);
  1012. switch (GetDlgCtrlID(ChildWindowFromPoint((HWND)wParam, pt)))
  1013. {
  1014. case IDC_FORMAREA:
  1015. case IDC_FINDANIMATION:
  1016. case IDC_STATUS:
  1017. return TRUE; // handled
  1018. default:
  1019. pQueryFrame->_pQueryHandler->ActivateView(CQRVA_CONTEXTMENU, wParam, lParam);
  1020. return TRUE;
  1021. }
  1022. return FALSE;
  1023. }
  1024. case WM_HELP:
  1025. {
  1026. LPHELPINFO phi = (LPHELPINFO)lParam;
  1027. // filter out those controls we are not interested in (they make no sense)
  1028. // to bother the user with
  1029. switch (GetDlgCtrlID((HWND)phi->hItemHandle))
  1030. {
  1031. case IDC_FORMAREA:
  1032. case IDC_FINDANIMATION:
  1033. case IDC_STATUS:
  1034. return TRUE;
  1035. default:
  1036. pQueryFrame->OnHelp(phi);
  1037. return TRUE;
  1038. }
  1039. return FALSE;
  1040. }
  1041. case CQFWM_ADDSCOPE:
  1042. {
  1043. LPCQSCOPE pScope = (LPCQSCOPE)wParam;
  1044. BOOL fSelect = LOWORD(lParam);
  1045. INT iIndex = HIWORD(lParam);
  1046. if (SUCCEEDED(pQueryFrame->AddScope(pScope, iIndex, fSelect)))
  1047. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  1048. return 1;
  1049. }
  1050. case CQFWM_GETFRAME:
  1051. {
  1052. IQueryFrame** ppQueryFrame = (IQueryFrame**)lParam;
  1053. if (ppQueryFrame)
  1054. {
  1055. pQueryFrame->AddRef();
  1056. *ppQueryFrame = pQueryFrame;
  1057. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  1058. }
  1059. return 1;
  1060. }
  1061. case CQFWM_ALLSCOPESADDED:
  1062. {
  1063. // there is an async scope collector, it has added all the scopes
  1064. // so we must now attempt to issue the query if the we are in the
  1065. // holding pattern waiting for the scopes to be collected.
  1066. pQueryFrame->_fScopesAddedAsync = FALSE; // all scopes have been added
  1067. if (pQueryFrame->_pOpenQueryWnd->dwFlags & OQWF_ISSUEONOPEN)
  1068. PostMessage(pQueryFrame->_hwnd, CQFWM_STARTQUERY, 0, 0);
  1069. return 1;
  1070. }
  1071. case CQFWM_STARTQUERY:
  1072. pQueryFrame->OnFindNow();
  1073. return 1;
  1074. case CQFWM_SETDEFAULTFOCUS:
  1075. {
  1076. HWND hwndNextTab = _NextTabStop(pQueryFrame->_pCurrentFormPage->hwndPage, FALSE);
  1077. SendMessage(pQueryFrame->_pCurrentFormPage->hwndPage, WM_NEXTDLGCTL, (WPARAM)hwndNextTab, 1);
  1078. break;
  1079. }
  1080. default:
  1081. break;
  1082. }
  1083. }
  1084. exit_gracefully:
  1085. return(0);
  1086. }
  1087. /*-----------------------------------------------------------------------------
  1088. / CQueryFrame::CloseQueryFrame
  1089. / ----------------------------
  1090. / Close the query window passing back the data object if required, and ensuring
  1091. / that our result code indicates what is going on.
  1092. /
  1093. / In:
  1094. / hResult = result code to pass to the caller
  1095. /
  1096. / Out:
  1097. / -
  1098. /----------------------------------------------------------------------------*/
  1099. VOID CQueryFrame::CloseQueryFrame(HRESULT hres)
  1100. {
  1101. TraceEnter(TRACE_FRAME, "CQueryFrame::CloseQueryFrame");
  1102. Trace(TEXT("hResult %08x"), hres);
  1103. // If we succeeded then attempt to collect the IDataObject and pass it
  1104. // back to the caller.
  1105. if (hres == S_OK)
  1106. {
  1107. if (_ppDataObject)
  1108. {
  1109. hres = _pQueryHandler->GetViewObject(CQRVS_SELECTION, IID_IDataObject, (LPVOID*)_ppDataObject);
  1110. FailGracefully(hres, "Failed when collecting the data object");
  1111. }
  1112. if ((_pOpenQueryWnd->dwFlags & OQWF_SAVEQUERYONOK) && _pOpenQueryWnd->pPersistQuery)
  1113. {
  1114. hres = SaveQuery(_pOpenQueryWnd->pPersistQuery);
  1115. FailGracefully(hres, "Failed when persisting query to IPersistQuery blob");
  1116. }
  1117. hres = S_OK; // success
  1118. }
  1119. exit_gracefully:
  1120. _hResult = hres;
  1121. _fExitModalLoop = TRUE; // bomb out of the modal loop
  1122. TraceLeave();
  1123. }
  1124. /*-----------------------------------------------------------------------------
  1125. / CQueryFrame::FrameMessageBox
  1126. / ----------------------------
  1127. / Our message box for putting up prompts that relate to the current
  1128. / query. We handle getting the view information and displaying
  1129. / the prompt, returning the result from MessageBox.
  1130. /
  1131. / In:
  1132. / pPrompt = text displayed as a prompt
  1133. / uType = message box type
  1134. /
  1135. / Out:
  1136. / INT
  1137. /----------------------------------------------------------------------------*/
  1138. INT CQueryFrame::FrameMessageBox(LPCTSTR pPrompt, UINT uType)
  1139. {
  1140. TCHAR szTitle[MAX_PATH];
  1141. CQVIEWINFO vi;
  1142. TraceEnter(TRACE_FRAME, "CQueryFrame::FrameMessageBox");
  1143. ZeroMemory(&vi, SIZEOF(vi));
  1144. //vi. dwFlags = 0; // display attributes
  1145. if (SUCCEEDED(_pQueryHandler->GetViewInfo(&vi)) && vi.hInstance && vi.idTitle)
  1146. LoadString(vi.hInstance, vi.idTitle, szTitle, ARRAYSIZE(szTitle));
  1147. else
  1148. GetWindowText(_hwnd, szTitle, ARRAYSIZE(szTitle));
  1149. TraceLeaveValue(MessageBox(_hwnd, pPrompt, szTitle, uType));
  1150. }
  1151. /*-----------------------------------------------------------------------------
  1152. / CQueryFrame::OnInitDlg
  1153. / ----------------------
  1154. / Handle a WM_INITDAILOG message, this is sent as the first thing the
  1155. / dialog receives, therefore we must handle our initialization that
  1156. / was not handled in the constructor.
  1157. /
  1158. / In:
  1159. / hwnd = handle of dialog we are initializing
  1160. /
  1161. / Out:
  1162. / HRESULT
  1163. /----------------------------------------------------------------------------*/
  1164. HRESULT CQueryFrame::OnInitDialog(HWND hwnd)
  1165. {
  1166. HRESULT hres;
  1167. HICON hIcon = NULL;
  1168. TCHAR szGUID[GUIDSTR_MAX+1];
  1169. TCHAR szBuffer[MAX_PATH];
  1170. CQVIEWINFO vi;
  1171. INT dyControls = 0;
  1172. RECT rect, rect2;
  1173. SIZE size;
  1174. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnInitDialog");
  1175. // get the HKEY for the handler we are using
  1176. hres = GetKeyForCLSID(_pOpenQueryWnd->clsidHandler, NULL, &_hkHandler);
  1177. FailGracefully(hres, "Failed to open handlers HKEY");
  1178. // pick up the control handles and store them, saves picking them up later
  1179. _hwnd = hwnd;
  1180. _hwndFrame = GetDlgItem(hwnd, IDC_FORMAREA);
  1181. _hwndLookForLabel = GetDlgItem(hwnd, CQID_LOOKFORLABEL);
  1182. _hwndLookFor = GetDlgItem(hwnd, CQID_LOOKFOR);
  1183. _hwndLookInLabel = GetDlgItem(hwnd, CQID_LOOKINLABEL);
  1184. _hwndLookIn = GetDlgItem(hwnd, CQID_LOOKIN);
  1185. _hwndBrowse = GetDlgItem(hwnd, CQID_BROWSE);
  1186. _hwndFindNow = GetDlgItem(hwnd, CQID_FINDNOW);
  1187. _hwndStop = GetDlgItem(hwnd, CQID_STOP);
  1188. _hwndNewQuery = GetDlgItem(hwnd, CQID_CLEARALL);
  1189. _hwndFindAnimation = GetDlgItem(hwnd, IDC_FINDANIMATION);
  1190. _hwndOK = GetDlgItem(hwnd, IDOK);
  1191. _hwndCancel = GetDlgItem(hwnd, IDCANCEL);
  1192. // when enable is called this will be the first
  1193. _fFormFirstEnable = TRUE;
  1194. // call the IQueryHandler interface and get its display attributes,
  1195. // then reflect these into the dialog we are about to display to the
  1196. // outside world.
  1197. vi.dwFlags = 0;
  1198. vi.hInstance = NULL;
  1199. vi.idLargeIcon = 0;
  1200. vi.idSmallIcon = 0;
  1201. vi.idTitle = 0;
  1202. vi.idAnimation = 0;
  1203. hres = _pQueryHandler->GetViewInfo(&vi);
  1204. FailGracefully(hres, "Failed when getting the view info from the handler");
  1205. _dwHandlerViewFlags = vi.dwFlags;
  1206. if (vi.hInstance)
  1207. {
  1208. HICON hiTemp = NULL;
  1209. if (vi.idLargeIcon)
  1210. {
  1211. _hiconLarge = (HICON)LoadImage(vi.hInstance,
  1212. MAKEINTRESOURCE(vi.idLargeIcon),
  1213. IMAGE_ICON,
  1214. 0, 0,
  1215. LR_DEFAULTCOLOR|LR_DEFAULTSIZE);
  1216. if (_hiconLarge)
  1217. SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)_hiconLarge);
  1218. }
  1219. if (vi.idSmallIcon)
  1220. {
  1221. _hiconSmall = (HICON)LoadImage(vi.hInstance,
  1222. MAKEINTRESOURCE(vi.idLargeIcon),
  1223. IMAGE_ICON,
  1224. GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
  1225. LR_DEFAULTCOLOR);
  1226. if (_hiconSmall)
  1227. SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)_hiconSmall);
  1228. }
  1229. if (vi.idTitle)
  1230. {
  1231. LoadString(vi.hInstance, vi.idTitle, szBuffer, ARRAYSIZE(szBuffer));
  1232. SetWindowText(hwnd, szBuffer);
  1233. }
  1234. }
  1235. if (vi.hInstance && vi.idAnimation)
  1236. {
  1237. SetWindowLongPtr(_hwndFindAnimation, GWLP_HINSTANCE, (LRESULT)vi.hInstance);
  1238. Animate_Open(_hwndFindAnimation, MAKEINTRESOURCE(vi.idAnimation));
  1239. }
  1240. else
  1241. {
  1242. Animate_Open(_hwndFindAnimation, MAKEINTRESOURCE(IDR_FINDANIMATION));
  1243. }
  1244. // now adjust the positions and hide the controls we are not interested in
  1245. if (_pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS)
  1246. {
  1247. ShowWindow(_hwndLookForLabel, SW_HIDE);
  1248. ShowWindow(_hwndLookFor, SW_HIDE);
  1249. }
  1250. if (_pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES)
  1251. {
  1252. ShowWindow(_hwndLookInLabel, SW_HIDE);
  1253. ShowWindow(_hwndLookIn, SW_HIDE);
  1254. ShowWindow(_hwndBrowse, SW_HIDE);
  1255. }
  1256. // hiding both the scopes and the forms control causes us to
  1257. // move all the controls up by so many units.
  1258. if ((_pOpenQueryWnd->dwFlags & (OQWF_REMOVEFORMS|OQWF_REMOVESCOPES))
  1259. == (OQWF_REMOVEFORMS|OQWF_REMOVESCOPES))
  1260. {
  1261. GetRealWindowInfo(_hwndLookForLabel, &rect, NULL);
  1262. GetRealWindowInfo(_hwndFrame, &rect2, NULL);
  1263. dyControls += rect2.top - rect.top;
  1264. Trace(TEXT("Moving all controls up by %d units"), dyControls);
  1265. OffsetWindow(_hwndFrame, 0, -dyControls);
  1266. OffsetWindow(_hwndFindNow, 0, -dyControls);
  1267. OffsetWindow(_hwndStop, 0, -dyControls);
  1268. OffsetWindow(_hwndNewQuery, 0, -dyControls);
  1269. OffsetWindow(_hwndFindAnimation, 0, -dyControls);
  1270. OffsetWindow(_hwndOK, 0, -dyControls);
  1271. if (_hwndCancel)
  1272. OffsetWindow(_hwndCancel, 0, -dyControls);
  1273. }
  1274. // hiding OK/Cancel so lets adjust the size here to include the
  1275. // OK/Cancel buttons disappearing, note that we update dyControls
  1276. // to include this delta
  1277. if (!(_pOpenQueryWnd->dwFlags & OQWF_OKCANCEL))
  1278. {
  1279. ShowWindow(_hwndOK, SW_HIDE);
  1280. if (_hwndCancel)
  1281. ShowWindow(_hwndCancel, SW_HIDE);
  1282. // if this is the filter dialog then lets ensure that
  1283. // we trim the OK/Cancel buttons from the size by adjusting the
  1284. // dyControls further.
  1285. GetRealWindowInfo(_hwndOK, &rect, NULL);
  1286. GetRealWindowInfo(_hwndFrame, &rect2, NULL);
  1287. dyControls += rect.bottom - rect2.bottom;
  1288. }
  1289. // having performed that extra bit of initialization lets cache the
  1290. // positions of the various controls, to make sizing more fun...
  1291. GetClientRect(hwnd, &rect2);
  1292. rect2.bottom -= dyControls;
  1293. _dyResultsTop = rect2.bottom;
  1294. GetRealWindowInfo(hwnd, NULL, &size);
  1295. GetRealWindowInfo(_hwndFrame, &rect, &_szForm);
  1296. Trace(TEXT("dyControls %d"), dyControls);
  1297. size.cy -= dyControls;
  1298. _dxFormAreaLeft = rect.left;
  1299. _dxFormAreaRight = rect2.right - rect.right;
  1300. _szMinTrack.cx = size.cx - _szForm.cx;
  1301. _szMinTrack.cy = size.cy - _szForm.cy;
  1302. if (!(_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS))
  1303. {
  1304. TraceMsg("Adjusting _szMinTrack.cy to account for menu bar");
  1305. _szMinTrack.cy += GetSystemMetrics(SM_CYMENU);
  1306. }
  1307. GetRealWindowInfo(_hwndBrowse, &rect, NULL);
  1308. _dxButtonsLeft = rect2.right - rect.left;
  1309. GetRealWindowInfo(_hwndLookIn, &rect, NULL);
  1310. _dxGap = (rect2.right - rect.right) - _dxButtonsLeft;
  1311. GetRealWindowInfo(_hwndFindAnimation, &rect, NULL);
  1312. _dxAnimationLeft = rect2.right - rect.left;
  1313. GetRealWindowInfo(_hwndOK, &rect, NULL);
  1314. _dyOKTop = rect2.bottom - rect.top;
  1315. _dyGap = size.cy - rect.bottom;
  1316. // Now collect the forms and pages, then walk them building the size
  1317. // information that we need.
  1318. hres = GatherForms();
  1319. FailGracefully(hres, "Failed to init form list");
  1320. _szMinTrack.cx += _szForm.cx;
  1321. _szMinTrack.cy += _szForm.cy;
  1322. // Populate the scope control by querying the handler for them,
  1323. // if there are none then we display a suitable message box and
  1324. // let the user know that something went wrong.
  1325. hres = PopulateScopeControl();
  1326. FailGracefully(hres, "Failed to init scope list");
  1327. _fScopesPopulated = TRUE; // scope control now populated
  1328. // perform final fix up of the window, ensure that we size it so that
  1329. // the entire form and buttons are visible. Then set ourselves into the
  1330. // no query state and reset the animation.
  1331. SetWindowPos(hwnd,
  1332. NULL,
  1333. 0, 0,
  1334. _szMinTrack.cx, _szMinTrack.cy,
  1335. SWP_NOMOVE|SWP_NOZORDER);
  1336. if (_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS)
  1337. ::SetMenu(hwnd, NULL);
  1338. hres = PopulateFormControl(_pOpenQueryWnd->dwFlags & OQWF_SHOWOPTIONAL);
  1339. FailGracefully(hres, "Failed to populate form control");
  1340. // Now load the query which inturn selects the form that we should be using,
  1341. // if there is no query to load then either use the default form or
  1342. // the first in the list.
  1343. if ((_pOpenQueryWnd->dwFlags & OQWF_LOADQUERY) && _pOpenQueryWnd->pPersistQuery)
  1344. {
  1345. hres = LoadQuery(_pOpenQueryWnd->pPersistQuery);
  1346. FailGracefully(hres, "Failed when to load query from supplied IPersistQuery");
  1347. }
  1348. else
  1349. {
  1350. if (_pOpenQueryWnd->dwFlags & OQWF_DEFAULTFORM)
  1351. {
  1352. SelectForm(_pOpenQueryWnd->clsidDefaultForm);
  1353. if (!_pCurrentForm)
  1354. ExitGracefully(hres, E_FAIL, "Failed to select the query form");
  1355. }
  1356. else
  1357. {
  1358. INT iForm = (int)ComboBox_GetItemData(_hwndLookFor, 0);
  1359. LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  1360. TraceAssert(pQueryForm);
  1361. SelectForm(pQueryForm->clsidForm);
  1362. }
  1363. }
  1364. StartQuery(FALSE);
  1365. // issue on open, therefore lets get the query going, if there is async
  1366. // scope collection then the query will be issued by the bg thread.
  1367. if (_pOpenQueryWnd->dwFlags & OQWF_ISSUEONOPEN)
  1368. PostMessage(_hwnd, CQFWM_STARTQUERY, 0, 0);
  1369. SetForegroundWindow(hwnd);
  1370. hres = S_OK; // success
  1371. exit_gracefully:
  1372. TraceLeaveResult(hres);
  1373. }
  1374. /*-----------------------------------------------------------------------------
  1375. / CQueryFrame::EnableControls
  1376. / ---------------------------
  1377. / Set the controls into their enabled/disabled state based on the
  1378. / state of the dialog.
  1379. /
  1380. / In:
  1381. / -
  1382. /
  1383. / Out:
  1384. / HRESULT
  1385. /----------------------------------------------------------------------------*/
  1386. VOID CQueryFrame::DoEnableControls(VOID)
  1387. {
  1388. BOOL fScopes = (_fAddScopesNYI || ComboBox_GetCount(_hwndLookIn));
  1389. BOOL fEnable = fScopes;
  1390. UINT uEnable = fScopes ? MF_ENABLED:MF_GRAYED;
  1391. HMENU hMenu = GetMenu(_hwnd);
  1392. INT i;
  1393. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::DoEnableControls");
  1394. EnableWindow(_hwndFindNow, !_fQueryRunning && fEnable);
  1395. EnableWindow(_hwndStop, _fQueryRunning && fEnable);
  1396. EnableWindow(_hwndNewQuery, fEnable);
  1397. EnableWindow(_hwndLookFor, !_fQueryRunning && fEnable);
  1398. EnableWindow(_hwndLookIn, !_fQueryRunning && fEnable);
  1399. EnableWindow(_hwndBrowse, !_fQueryRunning && fEnable);
  1400. if (_pCurrentForm)
  1401. {
  1402. CallFormPages(_pCurrentForm, CQPM_ENABLE, (BOOL)(!_fQueryRunning && fEnable), 0);
  1403. if (_fFormFirstEnable)
  1404. {
  1405. PostMessage(_hwnd, CQFWM_SETDEFAULTFOCUS, 0, 0);
  1406. _fFormFirstEnable = FALSE;
  1407. }
  1408. }
  1409. if (_hwndOK)
  1410. EnableWindow(_hwndOK, !_fQueryRunning && fEnable);
  1411. if (_hwndCancel)
  1412. EnableWindow(_hwndCancel, !_fQueryRunning && fEnable);
  1413. for (i = 0 ; i < GetMenuItemCount(hMenu) ; i++)
  1414. EnableMenuItem(hMenu, i, MF_BYPOSITION|uEnable);
  1415. DrawMenuBar(_hwnd);
  1416. TraceLeave();
  1417. }
  1418. /*-----------------------------------------------------------------------------
  1419. / CQueryFrame::OnNotify
  1420. / ---------------------
  1421. / Notify event received, decode it and handle accordingly
  1422. /
  1423. / In:
  1424. / idCtrl = ID of control issuing notify
  1425. / pNotify -> LPNMHDR structure
  1426. /
  1427. / Out:
  1428. / LRESULT
  1429. /----------------------------------------------------------------------------*/
  1430. LRESULT CQueryFrame::OnNotify(INT idCtrl, LPNMHDR pNotify)
  1431. {
  1432. LRESULT lr = 0;
  1433. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnNotify");
  1434. // TCN_SELCHANGE used to indicate that the currently active
  1435. // tab has been changed
  1436. if (pNotify->code == TCN_SELCHANGE)
  1437. {
  1438. INT iPage = TabCtrl_GetCurSel(_hwndFrame);
  1439. TraceAssert(iPage >= 0);
  1440. if (iPage >= 0)
  1441. {
  1442. SelectFormPage(_pCurrentForm, iPage);
  1443. lr = 0;
  1444. }
  1445. }
  1446. TraceLeaveResult((HRESULT)lr);
  1447. }
  1448. /*-----------------------------------------------------------------------------
  1449. / CQueryFrame::OnSize
  1450. / -------------------
  1451. / The window is being sized and we received a WM_SIZE, therefore move
  1452. / the content of the window about.
  1453. /
  1454. / In:
  1455. / cx = new width
  1456. / cy = new height
  1457. /
  1458. / Out:
  1459. / -
  1460. /----------------------------------------------------------------------------*/
  1461. VOID CQueryFrame::OnSize(INT cx, INT cy)
  1462. {
  1463. HDWP hdwp;
  1464. RECT rect, rect2;
  1465. SIZE sz, sz2;
  1466. INT x, cxForm, cyForm;
  1467. INT dyResultsTop = 0;
  1468. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnSize");
  1469. // do as much as we can within a DefWindowPos to aVOID too
  1470. // much flicker.
  1471. hdwp = BeginDeferWindowPos(16);
  1472. if (hdwp)
  1473. {
  1474. {
  1475. // adjust the look for controls, if there is no scope then
  1476. // stretch the look for control over the entire client area
  1477. // of the window.
  1478. if (!(_pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS))
  1479. {
  1480. if (_pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES)
  1481. {
  1482. GetRealWindowInfo(_hwndLookFor, &rect, &sz);
  1483. hdwp = DeferWindowPos(hdwp, _hwndLookFor, NULL,
  1484. 0, 0,
  1485. (cx - _dxFormAreaRight) - rect.left, sz.cy,
  1486. SWP_NOZORDER|SWP_NOMOVE);
  1487. }
  1488. }
  1489. // adjust the "look in" controls, if there is a form control
  1490. // then stretch across the remaining space, otherwise move the
  1491. // label and stretch the scope over the remaining space.
  1492. if (!(_pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES))
  1493. {
  1494. INT xScopeRight;
  1495. GetRealWindowInfo(_hwndLookIn, &rect, &sz);
  1496. xScopeRight = cx - _dxFormAreaRight - _dxGap;
  1497. if (_pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHUI)
  1498. {
  1499. //
  1500. // when hiding the search UI, then adjust the button position to account for the
  1501. // right edge of the dialog not having buttons.
  1502. //
  1503. xScopeRight -= (_dxButtonsLeft - _dxFormAreaRight) + _dxGap;
  1504. }
  1505. if (_pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS)
  1506. {
  1507. GetRealWindowInfo(_hwndLookInLabel, &rect2, &sz2);
  1508. hdwp = DeferWindowPos(hdwp, _hwndLookInLabel, NULL,
  1509. _dxFormAreaLeft, rect2.top,
  1510. 0, 0,
  1511. SWP_NOSIZE|SWP_NOZORDER);
  1512. hdwp = DeferWindowPos(hdwp, _hwndLookIn, NULL,
  1513. _dxFormAreaLeft+sz2.cx, rect.top,
  1514. xScopeRight - (_dxFormAreaLeft + sz2.cx), sz.cy,
  1515. SWP_NOZORDER);
  1516. }
  1517. else
  1518. {
  1519. hdwp = DeferWindowPos(hdwp, _hwndLookIn, NULL,
  1520. 0, 0,
  1521. xScopeRight - rect.left, sz.cy,
  1522. SWP_NOZORDER|SWP_NOMOVE);
  1523. }
  1524. // browse control is displayed always if we are showing the
  1525. // scopes.
  1526. GetRealWindowInfo(_hwndBrowse, &rect, NULL);
  1527. hdwp = DeferWindowPos(hdwp, _hwndBrowse, NULL,
  1528. xScopeRight+_dxGap, rect.top,
  1529. 0, 0,
  1530. SWP_NOZORDER|SWP_NOSIZE);
  1531. }
  1532. // all the buttons have a fixed offset from the right edege
  1533. // of the dialog, so just handle that as we can.
  1534. if (!(_pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHUI))
  1535. {
  1536. GetRealWindowInfo(_hwndFindNow, &rect, NULL);
  1537. hdwp = DeferWindowPos(hdwp, _hwndFindNow, NULL,
  1538. (cx - _dxButtonsLeft), rect.top,
  1539. 0, 0,
  1540. SWP_NOZORDER|SWP_NOSIZE);
  1541. GetRealWindowInfo(_hwndStop, &rect, &sz);
  1542. hdwp = DeferWindowPos(hdwp, _hwndStop, NULL,
  1543. (cx - _dxButtonsLeft), rect.top,
  1544. 0, 0,
  1545. SWP_NOZORDER|SWP_NOSIZE);
  1546. GetRealWindowInfo(_hwndNewQuery, &rect, NULL);
  1547. hdwp = DeferWindowPos(hdwp, _hwndNewQuery, NULL,
  1548. (cx - _dxButtonsLeft), rect.top,
  1549. 0, 0,
  1550. SWP_NOZORDER|SWP_NOSIZE);
  1551. GetRealWindowInfo(_hwndFindAnimation, &rect2, &sz2);
  1552. hdwp = DeferWindowPos(hdwp, _hwndFindAnimation, NULL,
  1553. (cx - _dxAnimationLeft), rect2.top,
  1554. 0, 0,
  1555. SWP_NOZORDER|SWP_NOSIZE);
  1556. }
  1557. // position the form "frame" control
  1558. GetRealWindowInfo(_hwndFrame, &rect, &sz);
  1559. cxForm = (cx - _dxFormAreaRight) - rect.left;
  1560. hdwp = DeferWindowPos(hdwp, _hwndFrame, NULL,
  1561. 0, 0,
  1562. cxForm, _szForm.cy,
  1563. SWP_NOZORDER|SWP_NOMOVE);
  1564. dyResultsTop = _dyResultsTop;
  1565. // when we have a cancel button then ensure that it is to the right
  1566. // of the OK button.
  1567. if (_hwndCancel)
  1568. {
  1569. GetRealWindowInfo(_hwndCancel, &rect, &sz);
  1570. hdwp = DeferWindowPos(hdwp, _hwndCancel, NULL,
  1571. (cx - _dxButtonsLeft), dyResultsTop - _dyOKTop,
  1572. 0, 0,
  1573. SWP_NOZORDER|SWP_NOSIZE);
  1574. GetRealWindowInfo(_hwndOK, &rect, &sz);
  1575. hdwp = DeferWindowPos(hdwp, _hwndOK, NULL,
  1576. (cx - _dxButtonsLeft - _dxGap - sz.cx), dyResultsTop - _dyOKTop,
  1577. 0, 0,
  1578. SWP_NOZORDER|SWP_NOSIZE);
  1579. }
  1580. else
  1581. {
  1582. GetRealWindowInfo(_hwndOK, &rect, &sz);
  1583. hdwp = DeferWindowPos(hdwp, _hwndOK, NULL,
  1584. (cx - _dxButtonsLeft), dyResultsTop - _dyOKTop,
  1585. 0, 0,
  1586. SWP_NOZORDER|SWP_NOSIZE);
  1587. }
  1588. }
  1589. // move the results and status bar as required
  1590. if (_hwndResults)
  1591. {
  1592. hdwp = DeferWindowPos(hdwp, _hwndStatus, NULL,
  1593. 0, cy - _cyStatus,
  1594. cx, _cyStatus,
  1595. SWP_SHOWWINDOW|SWP_NOZORDER);
  1596. hdwp = DeferWindowPos(hdwp, _hwndResults, NULL,
  1597. 0, dyResultsTop,
  1598. cx, max(0, cy - (dyResultsTop + _cyStatus)),
  1599. SWP_SHOWWINDOW|SWP_NOZORDER);
  1600. }
  1601. EndDeferWindowPos(hdwp);
  1602. // here is the strange bit, by this point we have moved & sized all the
  1603. // controls on the dialog except the current page, as this is a child window
  1604. // and not a control which in turn has controls doing this would break
  1605. // the DefWindowPos path, therefore having updated everybody, lets update
  1606. // the page.
  1607. if (_pCurrentFormPage && _pCurrentFormPage->hwndPage)
  1608. {
  1609. GetRealWindowInfo(_hwndFrame, &rect, NULL);
  1610. TabCtrl_AdjustRect(_hwndFrame, FALSE, &rect);
  1611. cxForm = rect.right - rect.left;
  1612. cyForm = rect.bottom - rect.top;
  1613. SetWindowPos(_pCurrentFormPage->hwndPage, NULL,
  1614. rect.left, rect.top, cxForm, cyForm,
  1615. SWP_NOZORDER);
  1616. }
  1617. }
  1618. TraceLeave();
  1619. }
  1620. /*-----------------------------------------------------------------------------
  1621. / CQueryFrame::OnGetMinMaxInfo
  1622. / ----------------------------
  1623. / The window is being sized and we received a WM_SIZE, therefore move
  1624. / the content of the window about.
  1625. /
  1626. / In:
  1627. / lpmmin -> MINMAXINFO structure
  1628. /
  1629. / Out:
  1630. / -
  1631. /----------------------------------------------------------------------------*/
  1632. VOID CQueryFrame::OnGetMinMaxInfo(LPMINMAXINFO lpmmi)
  1633. {
  1634. RECT rect = {0, 0, 0, 0};
  1635. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnGetMinMaxInfo");
  1636. #if 0
  1637. if (!_fHideSearchPane)
  1638. #endif
  1639. {
  1640. lpmmi->ptMinTrackSize.x = _szMinTrack.cx;
  1641. lpmmi->ptMinTrackSize.y = _szMinTrack.cy;
  1642. if (!_hwndResults)
  1643. {
  1644. lpmmi->ptMaxSize.y = lpmmi->ptMinTrackSize.y;
  1645. lpmmi->ptMaxTrackSize.y = lpmmi->ptMinTrackSize.y;
  1646. }
  1647. }
  1648. #if 0
  1649. else
  1650. {
  1651. AdjustWindowRect(&rect, GetWindowLong(_hwnd, GWL_STYLE), (NULL != GetMenu(_hwnd)));
  1652. lpmmi->ptMinTrackSize.y = rect.bottom - rect.top;
  1653. }
  1654. #endif
  1655. if (_hwndResults && _hwndStatus)
  1656. lpmmi->ptMinTrackSize.y += _cyStatus;
  1657. TraceLeave();
  1658. }
  1659. /*-----------------------------------------------------------------------------
  1660. / CQueryFrame::OnCommand
  1661. / ----------------------
  1662. / We have recieved a WM_COMMAND so process it accordingly.
  1663. /
  1664. / In:
  1665. / wParam, lParam = parameters from the message
  1666. /
  1667. / Out:
  1668. / -
  1669. /----------------------------------------------------------------------------*/
  1670. VOID CQueryFrame::OnCommand(WPARAM wParam, LPARAM lParam)
  1671. {
  1672. HRESULT hres;
  1673. UINT uID = LOWORD(wParam);
  1674. UINT uNotify = HIWORD(wParam);
  1675. HWND hwndControl = (HWND)lParam;
  1676. INT i;
  1677. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnCommand");
  1678. Trace(TEXT("uID %08x, uNotify %d, hwndControl %08x"), uID, uNotify, hwndControl);
  1679. switch (uID)
  1680. {
  1681. case IDOK:
  1682. TraceMsg("IDOK received");
  1683. CloseQueryFrame(S_OK);
  1684. break;
  1685. case IDCANCEL:
  1686. TraceMsg("IDCANCEL received");
  1687. CloseQueryFrame(S_FALSE);
  1688. break;
  1689. case CQID_LOOKFOR:
  1690. {
  1691. if (uNotify == CBN_SELCHANGE)
  1692. {
  1693. INT iSel = ComboBox_GetCurSel(_hwndLookFor);
  1694. INT iForm = (int)ComboBox_GetItemData(_hwndLookFor, iSel);
  1695. LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  1696. TraceAssert(pQueryForm);
  1697. if (S_FALSE == SelectForm(pQueryForm->clsidForm))
  1698. {
  1699. TraceMsg("SelectForm return S_FALSE, so the user doesn't want the new form");
  1700. PostMessage(_hwndLookFor, CB_SETCURSEL, (WPARAM)_pCurrentForm->iForm, 0);
  1701. }
  1702. }
  1703. break;
  1704. }
  1705. case CQID_BROWSE:
  1706. OnBrowse();
  1707. break;
  1708. case CQID_FINDNOW:
  1709. OnFindNow();
  1710. break;
  1711. case CQID_STOP:
  1712. {
  1713. LONG style;
  1714. _pQueryHandler->StopQuery();
  1715. // For some reason, the standard method of getting the old
  1716. // def button used in SetDefButton() below isn't working,
  1717. // so we have to forcibly remove the BS_DEFPUSHBUTTON style
  1718. // from the CQID_STOP button.
  1719. style = GetWindowLong(_hwndStop, GWL_STYLE) & ~BS_DEFPUSHBUTTON;
  1720. SendMessage(_hwndStop,
  1721. BM_SETSTYLE,
  1722. MAKEWPARAM(style, 0),
  1723. MAKELPARAM(TRUE, 0));
  1724. SetDefButton(_hwnd, CQID_FINDNOW);
  1725. SetFocus(_hwndFindNow);
  1726. break;
  1727. }
  1728. case CQID_CLEARALL:
  1729. OnNewQuery(TRUE); // discard the current query
  1730. break;
  1731. case CQID_FILE_CLOSE:
  1732. TraceMsg("CQID_FILE_CLOSE received");
  1733. CloseQueryFrame(S_FALSE);
  1734. break;
  1735. default:
  1736. _pQueryHandler->InvokeCommand(_hwnd, uID);
  1737. break;
  1738. }
  1739. TraceLeave();
  1740. }
  1741. /*-----------------------------------------------------------------------------
  1742. / CQueryFrame::OnInitMenu
  1743. / -----------------------
  1744. / Handle telling the handler that the menu is being initialised, however
  1745. / this should only happen if the menu being activated is the
  1746. / menu bar, otherwise we assume that the caller is tracking a popup
  1747. / menu and has performed the required initalization.
  1748. /
  1749. / In:
  1750. / wParam, lParam = parameters from the WM_INITMENU
  1751. /
  1752. / Out:
  1753. / -
  1754. /----------------------------------------------------------------------------*/
  1755. VOID CQueryFrame::OnInitMenu(HMENU hMenu)
  1756. {
  1757. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnInitMenu");
  1758. _fTrackingMenuBar = (GetMenu(_hwnd) == hMenu);
  1759. if (_fTrackingMenuBar)
  1760. {
  1761. TraceMsg("Tracking the menu bar, sending activate");
  1762. _pQueryHandler->ActivateView(CQRVA_INITMENUBAR, (WPARAM)hMenu, 0L);
  1763. EnableMenuItem(hMenu, CQID_VIEW_SEARCHPANE,
  1764. MF_BYCOMMAND|(_hwndResults != NULL) ? MF_ENABLED:MF_GRAYED);
  1765. }
  1766. TraceLeave();
  1767. }
  1768. /*-----------------------------------------------------------------------------
  1769. / CQueryFrame::OnEnterMenuLoop
  1770. / ----------------------------
  1771. / When the user displays a menu we must reflect this into the status bar
  1772. / so that we can give the user help text relating to the commands they
  1773. / select.
  1774. /
  1775. / In:
  1776. / fEntering = entering the menu loop, or leaving.
  1777. /
  1778. / Out:
  1779. / -
  1780. /----------------------------------------------------------------------------*/
  1781. VOID CQueryFrame::OnEnterMenuLoop(BOOL fEntering)
  1782. {
  1783. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnEnterMenuLoop");
  1784. if (_hwndStatus)
  1785. {
  1786. if (fEntering)
  1787. {
  1788. SendMessage(_hwndStatus, SB_SIMPLE, (WPARAM)TRUE, 0L);
  1789. SendMessage(_hwndStatus, SB_SETTEXT, (WPARAM)SBT_NOBORDERS|255, 0L);
  1790. }
  1791. else
  1792. {
  1793. SendMessage(_hwndStatus, SB_SIMPLE, (WPARAM)FALSE, 0L);
  1794. }
  1795. }
  1796. TraceLeave();
  1797. }
  1798. /*-----------------------------------------------------------------------------
  1799. / CQueryFrame::OnMenuSelect
  1800. / -------------------------
  1801. / Get the status text for this menu item and display it to the user,
  1802. / if this doesn't map to any particular command then NULL out
  1803. / the string. At this point we also trap our commands.
  1804. /
  1805. / In:
  1806. / hMenu = menu the user is on
  1807. / uID = command ID for that item
  1808. /
  1809. / Out:
  1810. / -
  1811. /----------------------------------------------------------------------------*/
  1812. VOID CQueryFrame::OnMenuSelect(HMENU hMenu, UINT uID)
  1813. {
  1814. TCHAR szBuffer[MAX_PATH] = { TEXT('\0') };
  1815. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnMenuSelect");
  1816. Trace(TEXT("hMenu %08x, uID %08x"), hMenu, uID);
  1817. if (_hwndStatus)
  1818. {
  1819. switch (uID)
  1820. {
  1821. case CQID_FILE_CLOSE:
  1822. case CQID_VIEW_SEARCHPANE:
  1823. LoadString(GLOBAL_HINSTANCE, uID, szBuffer, ARRAYSIZE(szBuffer));
  1824. break;
  1825. default:
  1826. _pQueryHandler->GetCommandString(uID, 0x0, szBuffer, ARRAYSIZE(szBuffer));
  1827. break;
  1828. }
  1829. Trace(TEXT("Setting status bar to: %s"), szBuffer);
  1830. SendMessage(_hwndStatus, SB_SETTEXT, (WPARAM)SBT_NOBORDERS|255, (LPARAM)szBuffer);
  1831. }
  1832. TraceLeave();
  1833. }
  1834. /*-----------------------------------------------------------------------------
  1835. / CQueryFrame::OnFindNow
  1836. / ----------------------
  1837. // Issue the query, resulting in a view window being created and then issuing
  1838. // the parameter block to the query client.
  1839. /
  1840. / In:
  1841. / Out:
  1842. / HRESULT
  1843. /----------------------------------------------------------------------------*/
  1844. HRESULT CQueryFrame::OnFindNow(VOID)
  1845. {
  1846. HRESULT hres;
  1847. CQPARAMS qp = { 0 };
  1848. LPQUERYSCOPE pQueryScope = NULL;
  1849. TCHAR szBuffer[MAX_PATH];
  1850. BOOL fFixSize = TRUE;
  1851. RECT rc;
  1852. DECLAREWAITCURSOR;
  1853. BOOL fSetCursor = FALSE;
  1854. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnFindNow");
  1855. TraceAssert(_pCurrentForm != NULL);
  1856. if (_fQueryRunning)
  1857. ExitGracefully(hres, E_FAIL, "Quyery is already running");
  1858. SetWaitCursor();
  1859. fSetCursor = TRUE;
  1860. // If we have not created the viewer before now lets do so, also at the
  1861. // same time we attempt to fix the window size to ensure that enough
  1862. // of the view is visible.
  1863. if (!_hwndResults)
  1864. {
  1865. if (!_hwndStatus)
  1866. {
  1867. _hwndStatus = CreateStatusWindow(WS_CHILD, NULL, _hwnd, IDC_STATUS);
  1868. GetClientRect(_hwndStatus, &rc);
  1869. _cyStatus = rc.bottom - rc.top;
  1870. }
  1871. // Now construct the result viewer for us to use
  1872. hres = _pQueryHandler->CreateResultView(_hwnd, &_hwndResults);
  1873. FailGracefully(hres, "Failed when creating the view object");
  1874. GetWindowRect(_hwnd, &rc);
  1875. SetWindowPos(_hwnd, NULL,
  1876. 0, 0,
  1877. rc.right - rc.left,
  1878. _szMinTrack.cy + VIEWER_DEFAULT_CY,
  1879. SWP_NOZORDER|SWP_NOMOVE);
  1880. }
  1881. // are we still collecting the scopes async? If so then lets wait until
  1882. // they have all arrived before we set the UI running.
  1883. if (_hdsaScopes && DSA_GetItemCount(_hdsaScopes))
  1884. {
  1885. // Collect the parameters ready for starting the query, if this fails then
  1886. // there is no point us continuing.
  1887. ZeroMemory(&qp, SIZEOF(qp));
  1888. qp.cbStruct = SIZEOF(qp);
  1889. //qp.dwFlags = 0x0;
  1890. qp.clsidForm = _pCurrentForm->clsidForm; // new NT5 beta 2
  1891. hres = GetSelectedScope(&pQueryScope);
  1892. FailGracefully(hres, "Failed to get the scope from the LookIn control");
  1893. if (pQueryScope)
  1894. {
  1895. Trace(TEXT("pQueryScope %08x"), pQueryScope);
  1896. qp.pQueryScope = pQueryScope->pScope;
  1897. }
  1898. hres = CallFormPages(_pCurrentForm, CQPM_GETPARAMETERS, 0, (LPARAM)&qp.pQueryParameters);
  1899. FailGracefully(hres, "Failed when collecting parameters from form");
  1900. if (!qp.pQueryParameters)
  1901. {
  1902. LoadString(GLOBAL_HINSTANCE, IDS_ERR_NOPARAMS, szBuffer, ARRAYSIZE(szBuffer));
  1903. FrameMessageBox(szBuffer, MB_ICONERROR|MB_OK);
  1904. ExitGracefully(hres, E_FAIL, "Failed to issue the query, no parameters");
  1905. }
  1906. // We either already had a view, or have just created one. Either way
  1907. // we must now prepare the query for sending.
  1908. Trace(TEXT("qp.cbStruct %08x"), qp.cbStruct);
  1909. Trace(TEXT("qp.dwFlags %08x"), qp.dwFlags);
  1910. Trace(TEXT("qp.pQueryScope %08x"), qp.pQueryScope);
  1911. Trace(TEXT("qp.pQueryParameters %08x"), qp.pQueryParameters);
  1912. TraceGUID("qp.clsidForm: ", qp.clsidForm);
  1913. hres = _pQueryHandler->IssueQuery(&qp);
  1914. FailGracefully(hres, "Failed in IssueQuery");
  1915. }
  1916. else
  1917. {
  1918. // set the status text to reflect that we are initializng, otherwise it is
  1919. // left empty and looks like we have crashed.
  1920. if (LoadString(GLOBAL_HINSTANCE, IDS_INITIALIZING, szBuffer, ARRAYSIZE(szBuffer)))
  1921. {
  1922. SetStatusText(szBuffer);
  1923. }
  1924. }
  1925. hres = S_OK; // success
  1926. exit_gracefully:
  1927. if (qp.pQueryParameters)
  1928. CoTaskMemFree(qp.pQueryParameters);
  1929. if (fSetCursor)
  1930. ResetWaitCursor();
  1931. TraceLeaveResult(hres);
  1932. }
  1933. /*-----------------------------------------------------------------------------
  1934. / CQueryFrame::OnNewQuery
  1935. / -----------------------
  1936. / Discard the current query, prompting the user as requierd.
  1937. /
  1938. / In:
  1939. / fAlwaysPrompt = TRUE if we force prompting of the user
  1940. /
  1941. / Out:
  1942. / BOOL
  1943. /----------------------------------------------------------------------------*/
  1944. BOOL CQueryFrame::OnNewQuery(BOOL fAlwaysPrompt)
  1945. {
  1946. BOOL fQueryCleared = TRUE;
  1947. TCHAR szBuffer[MAX_PATH];
  1948. RECT rc;
  1949. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnNewQuery");
  1950. if (_hwndResults || fAlwaysPrompt)
  1951. {
  1952. LoadString(GLOBAL_HINSTANCE, IDS_CLEARCURRENT, szBuffer, ARRAYSIZE(szBuffer));
  1953. if (IDOK != FrameMessageBox(szBuffer, MB_ICONINFORMATION|MB_OKCANCEL))
  1954. ExitGracefully(fQueryCleared, FALSE, "Used cancled new query");
  1955. if (_pQueryHandler)
  1956. _pQueryHandler->StopQuery();
  1957. CallFormPages(_pCurrentForm, CQPM_CLEARFORM, 0, 0);
  1958. if (_hwndResults)
  1959. {
  1960. DestroyWindow(_hwndResults); // no result view now
  1961. _hwndResults = NULL;
  1962. DestroyWindow(_hwndStatus); // no status bar
  1963. _hwndStatus = NULL;
  1964. GetWindowRect(_hwnd, &rc); // shrink the window
  1965. SetWindowPos(_hwnd, NULL,
  1966. 0, 0, rc.right - rc.left, _szMinTrack.cy,
  1967. SWP_NOZORDER|SWP_NOMOVE);
  1968. }
  1969. }
  1970. exit_gracefully:
  1971. TraceLeaveValue(fQueryCleared);
  1972. }
  1973. /*-----------------------------------------------------------------------------
  1974. / CQueryFrame::OnBrowse
  1975. / ---------------------
  1976. / Browse for a new scope, adding it to the list if not already present,
  1977. / or selecting the previous scope.
  1978. /
  1979. / In:
  1980. / Out:
  1981. / HRESULT
  1982. /----------------------------------------------------------------------------*/
  1983. HRESULT CQueryFrame::OnBrowse(VOID)
  1984. {
  1985. HRESULT hres;
  1986. LPQUERYSCOPE pQueryScope = NULL;
  1987. LPCQSCOPE pScope = NULL;
  1988. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnBrowse");
  1989. // Call the handler and get a scope allocation back, then add it to the list
  1990. // of scopes to be displayed.
  1991. hres = GetSelectedScope(&pQueryScope);
  1992. FailGracefully(hres, "Failed to get the scope from the LookIn control");
  1993. Trace(TEXT("Calling BrowseForScope _hwnd %08x, pQueryScope %08x (%08x)"),
  1994. _hwnd, pQueryScope, pQueryScope->pScope);
  1995. hres = _pQueryHandler->BrowseForScope(_hwnd, pQueryScope ? pQueryScope->pScope:NULL, &pScope);
  1996. FailGracefully(hres, "Failed when calling BrowseForScope");
  1997. if ((hres != S_FALSE) && pScope)
  1998. {
  1999. hres = InsertScopeIntoList(pScope, DA_LAST, TRUE);
  2000. FailGracefully(hres, "Failed when adding the scope to the control");
  2001. ComboBox_SetCurSel(_hwndLookIn, ShortFromResult(hres));
  2002. }
  2003. hres = S_OK;
  2004. exit_gracefully:
  2005. if (pScope)
  2006. CoTaskMemFree(pScope);
  2007. TraceLeaveResult(hres);
  2008. }
  2009. /*-----------------------------------------------------------------------------
  2010. / CQueryFrame::OnHelp
  2011. / -------------------
  2012. / Invoke the context sensitive help for the window, catch the
  2013. / handler specific and page specific stuff and pass those help
  2014. / requests down to the relevant objects.
  2015. /
  2016. / In:
  2017. / pHelpInfo -> help info structure
  2018. /
  2019. / Out:
  2020. / HRESULT
  2021. /----------------------------------------------------------------------------*/
  2022. HRESULT CQueryFrame::OnHelp(LPHELPINFO pHelpInfo)
  2023. {
  2024. HRESULT hres;
  2025. RECT rc;
  2026. HWND hwnd = (HWND)pHelpInfo->hItemHandle;
  2027. TraceEnter(TRACE_FRAME, "CQueryFrame::OnHelp");
  2028. // We are invoking help, theroefore we need ot check to see where element
  2029. // of the window we are being invoked for. If it is the
  2030. // result view then route the message to that, if its the form then
  2031. // likewise.
  2032. //
  2033. // If we don't hit any of the extension controls then lets pass the
  2034. // help onto WinHelp and get it to display the topics we have.
  2035. if (pHelpInfo->iContextType != HELPINFO_WINDOW)
  2036. ExitGracefully(hres, E_FAIL, "WM_HELP handler only copes with WINDOW objects");
  2037. if (_pCurrentFormPage->hwndPage && IsChild(_pCurrentFormPage->hwndPage, hwnd))
  2038. {
  2039. // it was on the query form page, therefore let it go there, that way
  2040. // they can provide topics specific to them
  2041. TraceMsg("Invoking help on the form pane");
  2042. hres = _CallPageProc(_pCurrentFormPage, CQPM_HELP, 0, (LPARAM)pHelpInfo);
  2043. FailGracefully(hres, "Failed when calling page proc to get help");
  2044. }
  2045. else
  2046. {
  2047. // pass the help information through to the handler as an activation,
  2048. // this should really just be a new method, but this works.
  2049. TraceMsg("Invoking help on the results pane");
  2050. TraceAssert(_pQueryHandler);
  2051. hres = _pQueryHandler->ActivateView(CQRVA_HELP, 0, (LPARAM)pHelpInfo);
  2052. FailGracefully(hres, "Handler WndProc returned FALSE");
  2053. }
  2054. hres = S_OK;
  2055. exit_gracefully:
  2056. TraceLeaveResult(hres);
  2057. }
  2058. /*-----------------------------------------------------------------------------
  2059. / Scope helper functions
  2060. /----------------------------------------------------------------------------*/
  2061. /*-----------------------------------------------------------------------------
  2062. / _CallScopeProc
  2063. / --------------
  2064. / Releae the given scope object, freeing the object that is referenced
  2065. / and passing a CQSM_RELEASE message to it.
  2066. /
  2067. / In:
  2068. / pQueryScope -> scope object to be called
  2069. / uMsg, pVoid -> parameters for the scope
  2070. /
  2071. / Out:
  2072. / HRESULT
  2073. /----------------------------------------------------------------------------*/
  2074. HRESULT _CallScopeProc(LPQUERYSCOPE pQueryScope, UINT uMsg, LPVOID pVoid)
  2075. {
  2076. HRESULT hres;
  2077. TraceEnter(TRACE_SCOPES, "_CallScopeProc");
  2078. Trace(TEXT("pQueryScope %08x, uMsg %d, pVoid %08x"), pQueryScope, uMsg, pVoid);
  2079. Trace(TEXT("(cbStruct %d, pScopeProc %08x, lParam %08x)"),
  2080. pQueryScope->pScope->cbStruct,
  2081. pQueryScope->pScope->pScopeProc,
  2082. pQueryScope->pScope->lParam);
  2083. if (!pQueryScope)
  2084. ExitGracefully(hres, S_OK, "pQueryScope == NULL");
  2085. hres = (pQueryScope->pScope->pScopeProc)(pQueryScope->pScope, uMsg, pVoid);
  2086. FailGracefully(hres, "Failed calling ScopeProc");
  2087. exit_gracefully:
  2088. TraceLeaveResult(hres);
  2089. }
  2090. /*-----------------------------------------------------------------------------
  2091. / _FreeScope
  2092. / ----------
  2093. / Releae the given scope object, freeing the object that is referenced
  2094. / and passing a CQSM_RELEASE message to it.
  2095. /
  2096. / In:
  2097. / pQueryScope -> scope object to be released
  2098. /
  2099. / Out:
  2100. / INT == 1 always
  2101. /----------------------------------------------------------------------------*/
  2102. INT _FreeScopeCB(LPVOID pItem, LPVOID pData)
  2103. {
  2104. return _FreeScope((LPQUERYSCOPE)pItem);
  2105. }
  2106. INT _FreeScope(LPQUERYSCOPE pQueryScope)
  2107. {
  2108. TraceEnter(TRACE_SCOPES, "_FreeScope");
  2109. Trace(TEXT("pQueryScope %08x, pQueryScope->pScope %08x"), pQueryScope, pQueryScope->pScope);
  2110. if (pQueryScope)
  2111. {
  2112. _CallScopeProc(pQueryScope, CQSM_RELEASE, NULL);
  2113. if (pQueryScope->pScope)
  2114. {
  2115. LocalFree((HLOCAL)pQueryScope->pScope);
  2116. pQueryScope->pScope = NULL;
  2117. }
  2118. }
  2119. TraceLeaveValue(TRUE);
  2120. }
  2121. /*-----------------------------------------------------------------------------
  2122. / CQueryFrame::InsertScopeIntoList
  2123. / --------------------------------
  2124. / Adds the given scope to the scope picker.
  2125. /
  2126. / In:
  2127. / pQueryScope -> zcope object to be added to the view
  2128. / i = index to insert the scope at
  2129. / fAddToControl = add the scope the picker control
  2130. / ppQueryScope -> recieves the new query scope object / = NULL
  2131. /
  2132. / Out:
  2133. / HRESULT
  2134. /----------------------------------------------------------------------------*/
  2135. HRESULT CQueryFrame::InsertScopeIntoList(LPCQSCOPE pScope, INT i, BOOL fAddToControl)
  2136. {
  2137. HRESULT hres;
  2138. QUERYSCOPE qs;
  2139. INT iScope;
  2140. TraceEnter(TRACE_SCOPES, "CQueryFrame::InsertScopeIntoList");
  2141. Trace(TEXT("pScope %08x, i %d, fAddToControl %d"), pScope, i, fAddToControl);
  2142. if (!pScope)
  2143. ExitGracefully(hres, E_INVALIDARG, "pScope == NULL, not allowed");
  2144. // if we don't have any scopes then allocate the DSA
  2145. if (!_hdsaScopes)
  2146. {
  2147. _hdsaScopes = DSA_Create(SIZEOF(QUERYSCOPE), 4);
  2148. TraceAssert(_hdsaScopes);
  2149. if (!_hdsaScopes)
  2150. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate the scope DPA");
  2151. }
  2152. // Walk the list of scopes checking to see if this one is already in
  2153. // there, if not then we can add it.
  2154. for (iScope = 0 ; iScope < DSA_GetItemCount(_hdsaScopes) ; iScope++)
  2155. {
  2156. LPQUERYSCOPE pQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, iScope);
  2157. TraceAssert(pQueryScope);
  2158. if (S_OK == _CallScopeProc(pQueryScope, CQSM_SCOPEEQUAL, pScope))
  2159. {
  2160. hres = ResultFromShort(iScope);
  2161. goto exit_gracefully;
  2162. }
  2163. }
  2164. // Take a copy of the scope blob passed by the caller. We copy the entire
  2165. // structure who's size is defined by cbStruct into a LocalAlloc block,
  2166. // once we have this we can then build the QUERYSCOPE structure that references
  2167. // it.
  2168. Trace(TEXT("pScope->cbStruct == %d"), pScope->cbStruct);
  2169. qs.pScope = (LPCQSCOPE)LocalAlloc(LPTR, pScope->cbStruct);
  2170. if (!qs.pScope)
  2171. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate query scope");
  2172. Trace(TEXT("Copying structure qs.pScope %08x, pScope %08x"), qs.pScope, pScope);
  2173. CopyMemory(qs.pScope, pScope, pScope->cbStruct);
  2174. //qs.pScope = NULL;
  2175. qs.iImage = -1; // no image
  2176. // We have a QUERYSCOPE, so initialize it, if that works then append it to the
  2177. // DSA before either setting the return value or appending it to the control.
  2178. _CallScopeProc(&qs, CQSM_INITIALIZE, NULL);
  2179. iScope = DSA_InsertItem(_hdsaScopes, i, &qs);
  2180. Trace(TEXT("iScope = %d"), iScope);
  2181. if (iScope == -1)
  2182. {
  2183. _FreeScope(&qs);
  2184. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to add scope to DSA");
  2185. }
  2186. if (fAddToControl)
  2187. {
  2188. LPQUERYSCOPE pQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, iScope);
  2189. TraceAssert(pQueryScope);
  2190. Trace(TEXT("Calling AddScopeToControl with %08x (%d)"), pQueryScope, iScope);
  2191. hres = AddScopeToControl(pQueryScope, iScope);
  2192. }
  2193. else
  2194. {
  2195. hres = ResultFromShort(iScope);
  2196. }
  2197. exit_gracefully:
  2198. TraceLeaveResult(hres);
  2199. }
  2200. /*-----------------------------------------------------------------------------
  2201. / CQueryFrame::AddScopeToControl
  2202. / ------------------------------
  2203. / Adds the given scope to the scope picker.
  2204. /
  2205. / In:
  2206. / pQueryScope -> zcope object to be added to the view
  2207. / i = index into view where to insert the scope
  2208. /
  2209. / Out:
  2210. / HRESULT (== index of item added)
  2211. /----------------------------------------------------------------------------*/
  2212. HRESULT CQueryFrame::AddScopeToControl(LPQUERYSCOPE pQueryScope, INT i)
  2213. {
  2214. HRESULT hres;
  2215. CQSCOPEDISPLAYINFO cqsdi;
  2216. COMBOBOXEXITEM cbi;
  2217. TCHAR szBuffer[MAX_PATH];
  2218. TCHAR szIconLocation[MAX_PATH] = { 0 };
  2219. INT item;
  2220. TraceEnter(TRACE_SCOPES, "CQueryFrame::AddScopeToControl");
  2221. if (!pQueryScope)
  2222. ExitGracefully(hres, E_INVALIDARG, "No scope specified");
  2223. // Call the scope to get the display information about this
  2224. // scope before we attempt to add it.
  2225. cqsdi.cbStruct = SIZEOF(cqsdi);
  2226. cqsdi.dwFlags = 0;
  2227. cqsdi.pDisplayName = szBuffer;
  2228. cqsdi.cchDisplayName = ARRAYSIZE(szBuffer);
  2229. cqsdi.pIconLocation = szIconLocation;
  2230. cqsdi.cchIconLocation = ARRAYSIZE(szIconLocation);
  2231. cqsdi.iIconResID = 0;
  2232. cqsdi.iIndent = 0;
  2233. hres = _CallScopeProc(pQueryScope, CQSM_GETDISPLAYINFO, &cqsdi);
  2234. FailGracefully(hres, "Failed to get display info for the scope");
  2235. // Now add the item to the control, if they gave as an image then
  2236. // add that to the image list (and tweak the INSERTITEM structure
  2237. // accordingly).
  2238. cbi.mask = CBEIF_TEXT|CBEIF_INDENT;
  2239. cbi.iItem = i;
  2240. cbi.pszText = cqsdi.pDisplayName;
  2241. cbi.iIndent = cqsdi.iIndent;
  2242. Trace(TEXT("Indent is %d"), cqsdi.iIndent);
  2243. if (szIconLocation[0] && cqsdi.iIconResID)
  2244. {
  2245. INT iImage;
  2246. if (!_fScopeImageListSet)
  2247. {
  2248. HIMAGELIST himlSmall;
  2249. Shell_GetImageLists(NULL, &himlSmall);
  2250. SendMessage(_hwndLookIn, CBEM_SETIMAGELIST, 0, (LPARAM)himlSmall);
  2251. _fScopeImageListSet = TRUE;
  2252. }
  2253. cbi.mask |= CBEIF_IMAGE|CBEIF_SELECTEDIMAGE;
  2254. cbi.iImage = Shell_GetCachedImageIndex(szIconLocation, cqsdi.iIconResID, 0x0);;
  2255. cbi.iSelectedImage = cbi.iImage;
  2256. Trace(TEXT("Image index set to: %d"), cbi.iImage);
  2257. }
  2258. item = (INT)SendMessage(_hwndLookIn, CBEM_INSERTITEM, 0, (LPARAM)&cbi);
  2259. if (item == -1)
  2260. ExitGracefully(hres, E_FAIL, "Failed when inserting the scope to the list");
  2261. DoEnableControls(); // reflect button changes into UI
  2262. hres = ResultFromShort(item);
  2263. exit_gracefully:
  2264. TraceLeaveResult(hres);
  2265. }
  2266. /*-----------------------------------------------------------------------------
  2267. / CQueryFrame::PopulateScopeControl
  2268. / ---------------------------------
  2269. / Collect the scopes that we want to display in the scope control and
  2270. / then populate it. If the handler doesn't return any scopes then
  2271. / we remove the control and assume that know what to do when they
  2272. / don't receive a scope pointer.
  2273. /
  2274. / In:
  2275. / -
  2276. /
  2277. / Out:
  2278. / HRESULT
  2279. /----------------------------------------------------------------------------*/
  2280. HRESULT CQueryFrame::PopulateScopeControl(VOID)
  2281. {
  2282. HRESULT hres;
  2283. LPQUERYSCOPE pQueryScope;
  2284. INT i;
  2285. TraceEnter(TRACE_SCOPES, "CQueryFrame::PopulateScopeControl");
  2286. // Collect the scopes that we should be showing in the view, if we don't
  2287. // get any back then we disable the scope control, if we do get some then
  2288. // populate the scope control with them.
  2289. hres = _pQueryHandler->AddScopes();
  2290. _fAddScopesNYI = (hres == E_NOTIMPL);
  2291. if (hres != E_NOTIMPL)
  2292. FailGracefully(hres, "Failed when calling handler to add scopes");
  2293. if (_hdsaScopes)
  2294. {
  2295. // We have some scopes, so now we create the image list that we can use
  2296. // for icons with scopes. Then walk through the DPA getting the scope
  2297. // to give us some display information about itself that we can
  2298. // add to the combo box.
  2299. ComboBox_SetExtendedUI(_hwndLookIn, TRUE);
  2300. for (i = 0 ; i < DSA_GetItemCount(_hdsaScopes); i++)
  2301. {
  2302. pQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, i);
  2303. TraceAssert(pQueryScope);
  2304. AddScopeToControl(pQueryScope, i);
  2305. }
  2306. }
  2307. else
  2308. {
  2309. // we don't have any scopes after calling AddScopes, this is either
  2310. // because the ::AddScopes method is not implemented, or the
  2311. // scopes are being added async. If IssueQuery returned a success
  2312. // we assume they are coming in async and flag as such in our
  2313. // state.
  2314. if (!_fAddScopesNYI)
  2315. {
  2316. TraceMsg("Handler adding scopes async, so marking so");
  2317. _fScopesAddedAsync = TRUE;
  2318. }
  2319. }
  2320. hres = S_OK; // success
  2321. exit_gracefully:
  2322. Trace(TEXT("Default scope is index %d"), _iDefaultScope);
  2323. ComboBox_SetCurSel(_hwndLookIn, _iDefaultScope);
  2324. TraceLeaveResult(hres);
  2325. }
  2326. /*-----------------------------------------------------------------------------
  2327. / CQueryFrame::GetSelectedScope
  2328. / -----------------------------
  2329. / Get the selected from the the scope ComboBox, this is a reference into the
  2330. / scope DSA.
  2331. /
  2332. / In:
  2333. / ppQueryScope = receives a pointer to the new scope
  2334. /
  2335. / Out:
  2336. / HRESULT
  2337. /----------------------------------------------------------------------------*/
  2338. HRESULT CQueryFrame::GetSelectedScope(LPQUERYSCOPE* ppQueryScope)
  2339. {
  2340. HRESULT hres;
  2341. COMBOBOXEXITEM cbi;
  2342. INT iScope;
  2343. TraceEnter(TRACE_SCOPES, "CQueryFrame::GetSelectedScope");
  2344. *ppQueryScope = NULL;
  2345. if (_hdsaScopes)
  2346. {
  2347. // Get the index for the current scope, if it doesn't give a real
  2348. // index to a item in our view then barf! Otherwise look up the
  2349. // associated scope.
  2350. iScope = ComboBox_GetCurSel(_hwndLookIn);
  2351. Trace(TEXT("iScope %d"), iScope);
  2352. if (iScope == -1)
  2353. ExitGracefully(hres, E_FAIL, "User entered scopes not supported yet");
  2354. *ppQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, iScope);
  2355. TraceAssert(*ppQueryScope);
  2356. }
  2357. hres = *ppQueryScope ? S_OK : E_FAIL;
  2358. exit_gracefully:
  2359. Trace(TEXT("Returning LPQUERYSCOPE %08x"), *ppQueryScope);
  2360. TraceLeaveResult(hres);
  2361. }
  2362. /*-----------------------------------------------------------------------------
  2363. / Form handling functions
  2364. /----------------------------------------------------------------------------*/
  2365. /*-----------------------------------------------------------------------------
  2366. / _FreeQueryForm
  2367. / ---------------
  2368. / Destroy the QUERYFORM allocation being used to describe the form in
  2369. / our DPA. We ensure that we issue a CQPM_RELEASE before doing anything
  2370. /
  2371. / In:
  2372. / pQueryForm -> query form to be destroyed
  2373. /
  2374. / Out:
  2375. / INT == 1 always
  2376. /----------------------------------------------------------------------------*/
  2377. INT _FreeQueryFormCB(LPVOID pItem, LPVOID pData)
  2378. {
  2379. return _FreeQueryForm((LPQUERYFORM)pItem);
  2380. }
  2381. INT _FreeQueryForm(LPQUERYFORM pQueryForm)
  2382. {
  2383. TraceEnter(TRACE_FORMS, "_FreeQueryForm");
  2384. if (pQueryForm)
  2385. {
  2386. if (pQueryForm->hdsaPages)
  2387. {
  2388. DSA_DestroyCallback(pQueryForm->hdsaPages, _FreeQueryFormPageCB, NULL);
  2389. pQueryForm->hdsaPages = NULL;
  2390. }
  2391. Str_SetPtr(&pQueryForm->pTitle, NULL);
  2392. if (pQueryForm->hIcon)
  2393. {
  2394. DestroyIcon(pQueryForm->hIcon);
  2395. }
  2396. }
  2397. TraceLeaveValue(TRUE);
  2398. }
  2399. /*-----------------------------------------------------------------------------
  2400. / _FreeQueryFormPage
  2401. / ------------------
  2402. / Given a pointer to a query form page structure release the members that
  2403. // are of interest, including calling the PAGEPROC to releasee the underlying
  2404. / object.
  2405. /
  2406. / In:
  2407. / pQueryFormPage -> page to be removed
  2408. /
  2409. / Out:
  2410. / INT == 1 always
  2411. /----------------------------------------------------------------------------*/
  2412. INT _FreeQueryFormPageCB(LPVOID pItem, LPVOID pData)
  2413. {
  2414. return _FreeQueryFormPage((LPQUERYFORMPAGE)pItem);
  2415. }
  2416. INT _FreeQueryFormPage(LPQUERYFORMPAGE pQueryFormPage)
  2417. {
  2418. TraceEnter(TRACE_FORMS, "_FreeQueryFormPage");
  2419. if (pQueryFormPage)
  2420. {
  2421. _CallPageProc(pQueryFormPage, CQPM_RELEASE, 0, 0); // NB: ignore return code
  2422. if (pQueryFormPage->hwndPage)
  2423. {
  2424. EnableThemeDialogTexture(pQueryFormPage->hwndPage, ETDT_DISABLE);
  2425. DestroyWindow(pQueryFormPage->hwndPage);
  2426. pQueryFormPage->hwndPage = NULL;
  2427. }
  2428. if (pQueryFormPage->pPage)
  2429. {
  2430. LocalFree(pQueryFormPage->pPage);
  2431. pQueryFormPage->pPage = NULL;
  2432. }
  2433. }
  2434. TraceLeaveValue(TRUE);
  2435. }
  2436. /*-----------------------------------------------------------------------------
  2437. / _CallPageProc
  2438. / -------------
  2439. / Call the given page object thunking the arguments as required if the
  2440. / page object is non-UNICODE (only if building UNICODE).
  2441. /
  2442. / In:
  2443. / pQueryFormPage -> page object to be called
  2444. / uMsg, wParam, lParam = parameters for message
  2445. /
  2446. / Out:
  2447. / HRESULT
  2448. /----------------------------------------------------------------------------*/
  2449. HRESULT _CallPageProc(LPQUERYFORMPAGE pQueryFormPage, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2450. {
  2451. HRESULT hres;
  2452. TraceEnter(TRACE_FORMS, "_CallPageProc");
  2453. Trace(TEXT("pQueryFormPage %08x, pPage %08x, uMsg %d, wParam %08x, lParam %08x"),
  2454. pQueryFormPage, pQueryFormPage->pPage, uMsg, wParam, lParam);
  2455. if (!pQueryFormPage)
  2456. ExitGracefully(hres, S_OK, "pQueryFormPage == NULL");
  2457. hres = (pQueryFormPage->pPage->pPageProc)(pQueryFormPage->pPage, pQueryFormPage->hwndPage, uMsg, wParam, lParam);
  2458. FailGracefully(hres, "Failed calling PageProc");
  2459. // hres = S_OK;
  2460. exit_gracefully:
  2461. TraceLeaveResult(hres);
  2462. }
  2463. /*-----------------------------------------------------------------------------
  2464. / Functions for adding query forms/pages
  2465. /----------------------------------------------------------------------------*/
  2466. // CB to add forms to the form DSA.
  2467. HRESULT _AddFormsProc(LPARAM lParam, LPCQFORM pForm)
  2468. {
  2469. HRESULT hres;
  2470. QUERYFORM qf = {0};
  2471. HDSA hdsaForms = (HDSA)lParam;
  2472. TraceEnter(TRACE_FORMS, "_AddFormsProc");
  2473. if (!pForm || !hdsaForms)
  2474. ExitGracefully(hres, E_INVALIDARG, "Failed to add page pForm == NULL");
  2475. // Allocate and thunk as required
  2476. qf.hdsaPages = NULL; // DSA of pages
  2477. qf.dwFlags = pForm->dwFlags; // flags
  2478. qf.clsidForm = pForm->clsid; // CLSID identifier for this form
  2479. qf.pTitle = NULL; // title used for drop down / title bar
  2480. qf.hIcon = pForm->hIcon; // hIcon passed by caller
  2481. qf.iImage = -1; // image list index of icon
  2482. qf.iForm = 0; // visible index of form in control
  2483. qf.iPage = 0; // currently selected page on form
  2484. if (!Str_SetPtr(&qf.pTitle, pForm->pszTitle))
  2485. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to copy form title string");
  2486. // Allocate the DSA if one doesn't exist yet, then add in the form
  2487. // structure as required.
  2488. if (-1 == DSA_AppendItem(hdsaForms, &qf))
  2489. ExitGracefully(hres, E_FAIL, "Failed to add form to the form DSA");
  2490. hres = S_OK; // success
  2491. exit_gracefully:
  2492. if (FAILED(hres))
  2493. _FreeQueryForm(&qf);
  2494. TraceLeaveResult(hres);
  2495. }
  2496. // CB to add pages to the page DSA.
  2497. HRESULT _AddPagesProc(LPARAM lParam, REFCLSID clsidForm, LPCQPAGE pPage)
  2498. {
  2499. HRESULT hres;
  2500. QUERYFORMPAGE qfp = {0};
  2501. HDSA hdsaPages = (HDSA)lParam;
  2502. TraceEnter(TRACE_FORMS, "_AddPagesProc");
  2503. if (!pPage || !hdsaPages)
  2504. ExitGracefully(hres, E_INVALIDARG, "Failed to add page pPage == NULL");
  2505. // copy the pPage structure for us to pass to the PAGEPROC later, nb: we
  2506. // use the cbStruct field to indicate the size of blob we must copy.
  2507. Trace(TEXT("pPage->cbStruct == %d"), pPage->cbStruct);
  2508. qfp.pPage = (LPCQPAGE)LocalAlloc(LPTR, pPage->cbStruct);
  2509. if (!qfp.pPage)
  2510. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate copy of page structure");
  2511. Trace(TEXT("Copying structure qfp.pPage %08x, pPage %08x"), qfp.pPage, pPage);
  2512. CopyMemory(qfp.pPage, pPage, pPage->cbStruct); // copy the page structure
  2513. //qfp.pPage = NULL;
  2514. qfp.clsidForm = clsidForm;
  2515. qfp.pPageProc = pPage->pPageProc;
  2516. qfp.lParam = pPage->lParam;
  2517. qfp.hwndPage = NULL;
  2518. _CallPageProc(&qfp, CQPM_INITIALIZE, 0, 0);
  2519. if (-1 == DSA_AppendItem(hdsaPages, &qfp))
  2520. ExitGracefully(hres, E_FAIL, "Failed to add the form to the DSA");
  2521. hres = S_OK; // succcess
  2522. exit_gracefully:
  2523. if (FAILED(hres))
  2524. _FreeQueryFormPage(&qfp);
  2525. TraceLeaveResult(hres);
  2526. }
  2527. // Add forms/pages from a UNICODE IQueryForm iface
  2528. HRESULT CQueryFrame::AddFromIQueryForm(IQueryForm* pQueryForm, HKEY hKeyForm)
  2529. {
  2530. HRESULT hres;
  2531. TraceEnter(TRACE_FORMS, "CQueryFrame::AddFromIQueryForm");
  2532. if (!pQueryForm)
  2533. ExitGracefully(hres, E_FAIL, "pQueryForm == NULL, failing");
  2534. hres = pQueryForm->Initialize(hKeyForm);
  2535. FailGracefully(hres, "Failed in IQueryFormW::Initialize");
  2536. // Call the form object to add its form and then its pages
  2537. hres = pQueryForm->AddForms(_AddFormsProc, (LPARAM)_hdsaForms);
  2538. if (SUCCEEDED(hres) || (hres == E_NOTIMPL))
  2539. {
  2540. hres = pQueryForm->AddPages(_AddPagesProc, (LPARAM)_hdsaPages);
  2541. FailGracefully(hres, "Failed in IQueryForm::AddPages");
  2542. }
  2543. else
  2544. {
  2545. FailGracefully(hres, "Failed when calling IQueryForm::AddForms");
  2546. }
  2547. hres = S_OK; // success
  2548. exit_gracefully:
  2549. TraceLeaveResult(hres);
  2550. }
  2551. #ifdef UNICODE
  2552. #define ADD_FROM_IQUERYFORM AddFromIQueryFormW
  2553. #else
  2554. #define ADD_FROM_IQUERYFORM AddFromIQueryFormA
  2555. #endif
  2556. /*-----------------------------------------------------------------------------
  2557. / CQueryFrame::GatherForms
  2558. / ------------------------
  2559. / Enumerate all the query forms for the given query handler and build
  2560. / the DPA containing the list of them. Once we have done this we
  2561. / can then populate the control at some more convientent moment.
  2562. /
  2563. / When gathering we first hit the "handler", then the "Forms" sub-key
  2564. / trying to load all the InProc servers that provide forms. We build
  2565. / list of hidden, never shown etc.
  2566. /
  2567. / In:
  2568. / -
  2569. / Out:
  2570. / HRESULT
  2571. /----------------------------------------------------------------------------*/
  2572. HRESULT _AddPageToForm(LPQUERYFORM pQueryForm, LPQUERYFORMPAGE pQueryFormPage, BOOL fClone)
  2573. {
  2574. HRESULT hres;
  2575. QUERYFORMPAGE qfp;
  2576. LPCQPAGE pPage;
  2577. TraceEnter(TRACE_FORMS, "_AddPageToForm");
  2578. TraceAssert(pQueryForm);
  2579. TraceAssert(pQueryFormPage);
  2580. // ensure that we have a page DSA for this form object
  2581. if (!pQueryForm->hdsaPages)
  2582. {
  2583. TraceMsg("Creating a new page DSA for form");
  2584. pQueryForm->hdsaPages = DSA_Create(SIZEOF(QUERYFORMPAGE), 4);
  2585. if (!pQueryForm->hdsaPages)
  2586. ExitGracefully(hres, E_OUTOFMEMORY, "*** No page DSA on form object ***");
  2587. }
  2588. if (!fClone)
  2589. {
  2590. // Moving this page structure to the one associated with the query form,
  2591. // therefore just ensure that the form has a DSA for pages and just
  2592. // insert an item at the header (yes, we add the pages in reverse).
  2593. Trace(TEXT("Adding page %08x to form %s"), pQueryFormPage, pQueryForm->pTitle);
  2594. if (-1 == DSA_InsertItem(pQueryForm->hdsaPages, 0, pQueryFormPage))
  2595. ExitGracefully(hres, E_FAIL, "Failed to copy page to form page DSA");
  2596. }
  2597. else
  2598. {
  2599. LPCQPAGE pPage = pQueryFormPage->pPage;
  2600. // Copying the page structure (it must be global), therefore clone
  2601. // the QUERYFORMPAGE strucutre and the CQPAGE into a new allocation
  2602. // and insert that into the page DSA.
  2603. Trace(TEXT("Cloning page %08x to form %s"), pQueryFormPage, pQueryForm->pTitle);
  2604. CopyMemory(&qfp, pQueryFormPage, SIZEOF(QUERYFORMPAGE));
  2605. qfp.pPage = (LPCQPAGE)LocalAlloc(LPTR, pPage->cbStruct);
  2606. if (!qfp.pPage)
  2607. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate copy of page structure");
  2608. Trace(TEXT("Copying structure qfp.pPage %08x, pPage %08x"), qfp.pPage, pPage);
  2609. CopyMemory(qfp.pPage, pPage, pPage->cbStruct); // copy the page structure
  2610. _CallPageProc(&qfp, CQPM_INITIALIZE, 0, 0);
  2611. if (-1 == DSA_AppendItem(pQueryForm->hdsaPages, &qfp))
  2612. {
  2613. _FreeQueryFormPage(&qfp);
  2614. ExitGracefully(hres, E_FAIL, "Failed to copy page to form DSA");
  2615. }
  2616. }
  2617. hres = S_OK; // success
  2618. exit_gracefully:
  2619. TraceLeaveResult(hres);
  2620. }
  2621. HRESULT CQueryFrame::GatherForms(VOID)
  2622. {
  2623. HRESULT hres;
  2624. IQueryForm* pQueryForm = NULL;
  2625. HKEY hKeyForms = NULL;
  2626. TCHAR szBuffer[MAX_PATH];
  2627. INT i, iPage, iForm;
  2628. RECT rect;
  2629. TC_ITEM tci;
  2630. TraceEnter(TRACE_FORMS, "CQueryFrame::GatherForms");
  2631. // Construct DSA's so we can store the forms and pages as required.
  2632. _hdsaForms = DSA_Create(SIZEOF(QUERYFORM), 4);
  2633. _hdsaPages = DSA_Create(SIZEOF(QUERYFORMPAGE), 4);
  2634. if (!_hdsaForms || !_hdsaPages)
  2635. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to create DSA's for storing pages/forms");
  2636. // First check the IQueryHandler to see if it supports IQueryForm, if it does
  2637. // then call it to add its objects. Note that we don't bother with ANSI/UNICODE
  2638. // at this point as the handler is assumed to be built the same the
  2639. // the query framework.
  2640. if (SUCCEEDED(_pQueryHandler->QueryInterface(IID_IQueryForm, (LPVOID*)&pQueryForm)))
  2641. {
  2642. hres = AddFromIQueryForm(pQueryForm, NULL);
  2643. FailGracefully(hres, "Failed when calling AddFromIQueryForm on handlers IQueryForm iface)");
  2644. }
  2645. // now attempt to build the list of forms and pages from the registered form
  2646. // extensions. These are declared under the handlers CLSID in the registry,
  2647. // under the sub-key "Forms".
  2648. if (ERROR_SUCCESS != RegOpenKeyEx(_hkHandler, c_szForms, NULL, KEY_READ, &hKeyForms))
  2649. {
  2650. TraceMsg("No 'Forms' sub-key found, therefore skipping");
  2651. }
  2652. else
  2653. {
  2654. // Enumerate all the keys in the "Forms" key, these are assumed to be a list of
  2655. // the form handlers.
  2656. for (i = 0 ; TRUE ; i++)
  2657. {
  2658. DWORD cchStruct = ARRAYSIZE(szBuffer);
  2659. if (ERROR_SUCCESS != RegEnumKeyEx(hKeyForms, i, szBuffer, &cchStruct, NULL, NULL, NULL, NULL))
  2660. {
  2661. TraceMsg("RegEnumKeyEx return's false, therefore stopping eunmeration");
  2662. break;
  2663. }
  2664. GetForms(hKeyForms, szBuffer);
  2665. }
  2666. }
  2667. // Now tally the form/page information together and remove duplicates and attach the pages
  2668. // to forms, take special note of the global pages. As all forms will now be in the
  2669. // DSA we can check for a zero count and we don't have to worry about the order
  2670. // in which the the forms and pages were added.
  2671. if (!DSA_GetItemCount(_hdsaForms) || !DSA_GetItemCount(_hdsaPages))
  2672. ExitGracefully(hres, E_FAIL, "Either the forms or pages DSA is empty");
  2673. for (iPage = DSA_GetItemCount(_hdsaPages) ; --iPage >= 0 ;)
  2674. {
  2675. LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(_hdsaPages, iPage);
  2676. TraceAssert(pQueryFormPage);
  2677. Trace(TEXT("iPage %d (of %d)"), iPage, DSA_GetItemCount(_hdsaPages));
  2678. if (!(pQueryFormPage->pPage->dwFlags & CQPF_ISGLOBAL))
  2679. {
  2680. LPQUERYFORM pQueryForm = FindQueryForm(pQueryFormPage->clsidForm);
  2681. TraceAssert(pQueryForm);
  2682. TraceGUID("Adding page to form:", pQueryFormPage->clsidForm);
  2683. if (pQueryForm)
  2684. {
  2685. hres = _AddPageToForm(pQueryForm, pQueryFormPage, FALSE);
  2686. FailGracefully(hres, "Failed when adding page to form");
  2687. if (!DSA_DeleteItem(_hdsaPages, iPage))
  2688. TraceMsg("**** Failed to remove page from global DSA ****");
  2689. }
  2690. }
  2691. }
  2692. for (iPage = DSA_GetItemCount(_hdsaPages) ; --iPage >= 0 ;)
  2693. {
  2694. LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(_hdsaPages, iPage);
  2695. TraceAssert(pQueryFormPage);
  2696. if ((pQueryFormPage->pPage->dwFlags & CQPF_ISGLOBAL))
  2697. {
  2698. Trace(TEXT("Adding global page to %d forms"), DSA_GetItemCount(_hdsaForms));
  2699. for (iForm = 0 ; iForm < DSA_GetItemCount(_hdsaForms); iForm++)
  2700. {
  2701. LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  2702. TraceAssert(pQueryForm);
  2703. if (!(pQueryForm->dwFlags & CQFF_NOGLOBALPAGES))
  2704. {
  2705. hres = _AddPageToForm(pQueryForm, pQueryFormPage, TRUE);
  2706. FailGracefully(hres, "Failed when adding global page to form");
  2707. }
  2708. }
  2709. _FreeQueryFormPage(pQueryFormPage);
  2710. if (!DSA_DeleteItem(_hdsaPages, iPage))
  2711. TraceMsg("**** Failed to remove page from global DSA ****");
  2712. }
  2713. }
  2714. // Walk the list of forms, rmeoving the ones which have no pages assocaited with
  2715. // them, we don't need these around confusing the world around us. Note that
  2716. // we walk backwards through the list removing.
  2717. //
  2718. // Also remove the optional forms we don't want to ehw orld to see
  2719. for (iForm = DSA_GetItemCount(_hdsaForms) ; --iForm >= 0 ;)
  2720. {
  2721. LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  2722. TraceAssert(pQueryForm);
  2723. Trace(TEXT("pQueryForm %08x (%s), pQueryForm->hdsaPages %08x (%d)"),
  2724. pQueryForm,
  2725. pQueryForm->pTitle,
  2726. pQueryForm->hdsaPages,
  2727. pQueryForm->hdsaPages ? DSA_GetItemCount(pQueryForm->hdsaPages):0);
  2728. if (!pQueryForm->hdsaPages
  2729. || !DSA_GetItemCount(pQueryForm->hdsaPages)
  2730. || ((pQueryForm->dwFlags & CQFF_ISOPTIONAL) && !(_pOpenQueryWnd->dwFlags & OQWF_SHOWOPTIONAL)))
  2731. {
  2732. TraceGUID("Removing form: ", pQueryForm->clsidForm);
  2733. _FreeQueryForm(pQueryForm);
  2734. DSA_DeleteItem(_hdsaForms, iForm);
  2735. }
  2736. }
  2737. if (!DSA_GetItemCount(_hdsaForms))
  2738. ExitGracefully(hres, E_FAIL, "!!!!! No forms registered after page/form fix ups !!!!!");
  2739. // The pages have been attached to the forms so we can now attempt to create the
  2740. // form/page objects.
  2741. _szForm.cx = 0;
  2742. _szForm.cy = 0;
  2743. tci.mask = TCIF_TEXT;
  2744. tci.pszText = TEXT("");
  2745. tci.cchTextMax = 0;
  2746. TabCtrl_InsertItem(_hwndFrame, 0, &tci); // tabctrl needs at least one item so we can compute sizes
  2747. for (iForm = 0 ; iForm < DSA_GetItemCount(_hdsaForms); iForm++)
  2748. {
  2749. LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  2750. TraceAssert(pQueryForm);
  2751. // Create each of the modeless page dialoges that we show to allow the user
  2752. // to edit the search criteria. We also grab the size and modify the
  2753. // form informaiton we have so that the default size of the dialog can be
  2754. // correctly computed.
  2755. for (iPage = 0 ; iPage < DSA_GetItemCount(pQueryForm->hdsaPages); iPage++)
  2756. {
  2757. LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryForm->hdsaPages, iPage);
  2758. TraceAssert(pQueryFormPage);
  2759. pQueryFormPage->hwndPage = CreateDialogParam(pQueryFormPage->pPage->hInstance,
  2760. MAKEINTRESOURCE(pQueryFormPage->pPage->idPageTemplate),
  2761. _hwnd,
  2762. pQueryFormPage->pPage->pDlgProc,
  2763. (LPARAM)pQueryFormPage->pPage);
  2764. if (!pQueryFormPage->hwndPage)
  2765. ExitGracefully(hres, E_FAIL, "Failed to create query form page");
  2766. EnableThemeDialogTexture(pQueryFormPage->hwndPage, ETDT_ENABLETAB);
  2767. GetRealWindowInfo(pQueryFormPage->hwndPage, &rect, NULL);
  2768. TabCtrl_AdjustRect(_hwndFrame, TRUE, &rect);
  2769. _szForm.cx = max(rect.right-rect.left, _szForm.cx);
  2770. _szForm.cy = max(rect.bottom-rect.top, _szForm.cy);
  2771. // flush the form parameters
  2772. _CallPageProc(pQueryFormPage, CQPM_CLEARFORM, 0, 0);
  2773. // Call the page with CQPM_SETDEFAULTPARAMETERS with the
  2774. // OPENQUERYWINDOW structure. wParam is TRUE/FALSE indiciating if
  2775. // the form is the default one, and therefore if the pFormParam is
  2776. // valid.
  2777. _CallPageProc(pQueryFormPage, CQPM_SETDEFAULTPARAMETERS,
  2778. (WPARAM)((_pOpenQueryWnd->dwFlags & OQWF_DEFAULTFORM) &&
  2779. IsEqualCLSID(_pOpenQueryWnd->clsidDefaultForm, pQueryFormPage->clsidForm)),
  2780. (LPARAM)_pOpenQueryWnd);
  2781. }
  2782. // If the form has an hIcon then lets ensure that we add that to the form image
  2783. // list, any failure here is non-fatal, in that we will just skip that forms
  2784. // icon in the list (rather than barfing)
  2785. if (pQueryForm->hIcon)
  2786. {
  2787. if (!_himlForms)
  2788. _himlForms = ImageList_Create(COMBOEX_IMAGE_CX, COMBOEX_IMAGE_CY, 0, 4, 1);
  2789. if (_himlForms)
  2790. {
  2791. pQueryForm->iImage = ImageList_AddIcon(_himlForms, pQueryForm->hIcon);
  2792. TraceAssert(pQueryForm->iImage >= 0);
  2793. }
  2794. DestroyIcon(pQueryForm->hIcon);
  2795. pQueryForm->hIcon = NULL;
  2796. }
  2797. }
  2798. hres = S_OK; // success
  2799. exit_gracefully:
  2800. DoRelease(pQueryForm);
  2801. if (hKeyForms)
  2802. RegCloseKey(hKeyForms);
  2803. TraceLeaveResult(hres);
  2804. }
  2805. /*-----------------------------------------------------------------------------
  2806. / CQueryFrame::GetForms
  2807. / ---------------------
  2808. / Given a HKEY to the forms list and the value name for the form we want
  2809. / to add, query for the form information add add the form objects
  2810. / to the master list.
  2811. /
  2812. / In:
  2813. / hKeyForms = HKEY for the {CLSID provider}\Forms key
  2814. / pName -> key value to query for
  2815. /
  2816. / Out:
  2817. / VOID
  2818. /----------------------------------------------------------------------------*/
  2819. HRESULT CQueryFrame::GetForms(HKEY hKeyForms, LPTSTR pName)
  2820. {
  2821. HRESULT hres;
  2822. HKEY hKeyForm = NULL;
  2823. TCHAR szQueryFormCLSID[GUIDSTR_MAX+1];
  2824. DWORD dwFlags;
  2825. DWORD dwSize;
  2826. IUnknown* pUnknown = NULL;
  2827. IQueryForm* pQueryForm = NULL;
  2828. CLSID clsidForm;
  2829. BOOL fIncludeForms = FALSE;
  2830. TraceEnter(TRACE_FORMS, "CQueryFrame::_GetForms");
  2831. Trace(TEXT("pName %s"), pName);
  2832. if (ERROR_SUCCESS != RegOpenKeyEx(hKeyForms, pName, NULL, KEY_READ, &hKeyForm))
  2833. ExitGracefully(hres, E_UNEXPECTED, "Failed to open the form key");
  2834. // Read the flags and try to determine if we should invoke this form object.
  2835. dwSize = SIZEOF(dwFlags);
  2836. if (ERROR_SUCCESS != RegQueryValueEx(hKeyForm, c_szFlags, NULL, NULL, (LPBYTE)&dwFlags, &dwSize))
  2837. {
  2838. TraceMsg("No flags, defaulting to something sensible");
  2839. dwFlags = QUERYFORM_CHANGESFORMLIST;
  2840. }
  2841. Trace(TEXT("Forms flag is %08x"), dwFlags);
  2842. // should be invoke this form object?
  2843. //
  2844. // - if dwFlags has QUERYFORM_CHANGESFORMSLIST, or
  2845. // - if dwFlags has QUERYFORM_CHANGESOPTFORMLIST and we are showing optional forms, or
  2846. // - neither set and the form object supports the requested form
  2847. if (!(dwFlags & QUERYFORM_CHANGESFORMLIST))
  2848. {
  2849. if ((dwFlags & QUERYFORM_CHANGESOPTFORMLIST) &&
  2850. (_pOpenQueryWnd->dwFlags & OQWF_SHOWOPTIONAL))
  2851. {
  2852. TraceMsg("Form is optional, are we are showing optional forms");
  2853. fIncludeForms = TRUE;
  2854. }
  2855. else
  2856. {
  2857. // OK, so it either didn't update the form list, or wasn't marked as optional,
  2858. // so lets check to see if it supports the form the user has requested, if not
  2859. // then don't bother loading this guy.
  2860. if (_pOpenQueryWnd->dwFlags & OQWF_DEFAULTFORM)
  2861. {
  2862. TCHAR szBuffer[GUIDSTR_MAX+32];
  2863. HKEY hkFormsSupported;
  2864. TraceMsg("Checking for supported form");
  2865. if (ERROR_SUCCESS == RegOpenKeyEx(hKeyForm, TEXT("Forms Supported"), NULL, KEY_READ, &hkFormsSupported))
  2866. {
  2867. TraceMsg("Form has a 'Supported Forms' sub-key");
  2868. GetStringFromGUID(_pOpenQueryWnd->clsidDefaultForm, szQueryFormCLSID, ARRAYSIZE(szQueryFormCLSID));
  2869. Trace(TEXT("Checking for: %s"), szQueryFormCLSID);
  2870. if (ERROR_SUCCESS == RegQueryValueEx(hkFormsSupported, szQueryFormCLSID, NULL, NULL, NULL, NULL))
  2871. {
  2872. TraceMsg("Query form is in supported list");
  2873. fIncludeForms = TRUE;
  2874. }
  2875. RegCloseKey(hkFormsSupported);
  2876. }
  2877. else
  2878. {
  2879. TraceMsg("No forms supported sub-key, so loading form object anyway");
  2880. fIncludeForms = TRUE;
  2881. }
  2882. }
  2883. }
  2884. }
  2885. else
  2886. {
  2887. TraceMsg("Form updates form list");
  2888. fIncludeForms = TRUE;
  2889. }
  2890. // if fIncludeForms is TRUE, then the checks above succeeded and we are including forms
  2891. // from this object (identified by pName), so we must now get the CLSID of the object
  2892. // we are invoking and use its IQueryForm interface to add the forms that we want.
  2893. if (fIncludeForms)
  2894. {
  2895. // get the form object CLSID, having parse it, then CoCreate it adding the forms.
  2896. dwSize = SIZEOF(szQueryFormCLSID);
  2897. if (ERROR_SUCCESS != RegQueryValueEx(hKeyForm, c_szCLSID, NULL, NULL, (LPBYTE)szQueryFormCLSID, &dwSize))
  2898. ExitGracefully(hres, E_UNEXPECTED, "Failed to read the CLSID of the form");
  2899. Trace(TEXT("szQueryFormCLSID: %s"), szQueryFormCLSID);
  2900. if (!GetGUIDFromString(szQueryFormCLSID, &clsidForm))
  2901. ExitGracefully(hres, E_UNEXPECTED, "Fialed to parse the string as a GUID");
  2902. // we now have the CLISD of the form object, so we must attempt to CoCreate it, we try for
  2903. // the current build type (eg UNICODE) and then fall back to ANSI if thats not supported,
  2904. // so we can support ANSI query form objects on a UNICODE platform.
  2905. hres = CoCreateInstance(clsidForm, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
  2906. FailGracefully(hres, "Failed to CoCreate the form object");
  2907. if (SUCCEEDED(pUnknown->QueryInterface(IID_IQueryForm, (LPVOID*)&pQueryForm)))
  2908. {
  2909. hres = AddFromIQueryForm(pQueryForm, hKeyForm);
  2910. FailGracefully(hres, "Failed when adding forms from specified IQueryForm iface");
  2911. }
  2912. else
  2913. {
  2914. ExitGracefully(hres, E_UNEXPECTED, "Form object doesn't support IQueryForm(A/W)");
  2915. }
  2916. }
  2917. hres = S_OK;
  2918. exit_gracefully:
  2919. if (hKeyForm)
  2920. RegCloseKey(hKeyForm);
  2921. DoRelease(pUnknown);
  2922. DoRelease(pQueryForm);
  2923. TraceLeaveResult(hres);
  2924. }
  2925. /*-----------------------------------------------------------------------------
  2926. / CQueryFrame::PopulateFormControl
  2927. / ---------------------------------
  2928. / Enumerate all the query forms for the given query handler and build
  2929. / the DPA containing the list of them. Once we have done this we
  2930. / can then populate the control at some more convientent moment.
  2931. /
  2932. / When gathering we first hit the "handler", then the "Forms" sub-key
  2933. / trying to load all the InProc servers that provide forms. We build
  2934. / list of hidden, never shown etc.
  2935. /
  2936. / In:
  2937. / fIncludeHidden = list forms marked as hidden in control
  2938. /
  2939. / Out:
  2940. / VOID
  2941. /----------------------------------------------------------------------------*/
  2942. HRESULT CQueryFrame::PopulateFormControl(BOOL fIncludeHidden)
  2943. {
  2944. HRESULT hres;
  2945. COMBOBOXEXITEM cbi;
  2946. LPQUERYFORM pQueryForm;
  2947. INT i, iForm;
  2948. TraceEnter(TRACE_FORMS, "CQueryFrame::PopulateFormControl");
  2949. Trace(TEXT("fIncludeHidden: %d"), fIncludeHidden);
  2950. // list which forms within the control
  2951. if (!_hdsaForms)
  2952. ExitGracefully(hres, E_FAIL, "No forms to list");
  2953. ComboBox_ResetContent(_hwndLookFor); // remove all items from that control
  2954. for (i = 0, iForm = 0 ; iForm < DSA_GetItemCount(_hdsaForms); iForm++)
  2955. {
  2956. LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  2957. TraceAssert(pQueryForm);
  2958. // filter out those forms that are not of interest to this instance of the
  2959. // dialog.
  2960. if (((pQueryForm->dwFlags & CQFF_ISOPTIONAL) && !fIncludeHidden) ||
  2961. (pQueryForm->dwFlags & CQFF_ISNEVERLISTED))
  2962. {
  2963. Trace(TEXT("Hiding form: %s"), pQueryForm->pTitle);
  2964. continue;
  2965. }
  2966. // now add the form to the control, including the image if there is an image
  2967. // specified.
  2968. cbi.mask = CBEIF_TEXT|CBEIF_LPARAM;
  2969. cbi.iItem = i++;
  2970. cbi.pszText = pQueryForm->pTitle;
  2971. cbi.cchTextMax = lstrlen(pQueryForm->pTitle);
  2972. cbi.lParam = iForm;
  2973. if (pQueryForm->iImage >= 0)
  2974. {
  2975. Trace(TEXT("Form has an image %d"), pQueryForm->iImage);
  2976. cbi.mask |= CBEIF_IMAGE|CBEIF_SELECTEDIMAGE;
  2977. cbi.iImage = pQueryForm->iImage;
  2978. cbi.iSelectedImage = pQueryForm->iImage;
  2979. }
  2980. pQueryForm->iForm = (int)SendMessage(_hwndLookFor, CBEM_INSERTITEM, 0, (LPARAM)&cbi);
  2981. if (pQueryForm->iForm < 0)
  2982. {
  2983. Trace(TEXT("Form name: %s"), pQueryForm->pTitle);
  2984. ExitGracefully(hres, E_FAIL, "Failed to add the entry to the combo box");
  2985. }
  2986. }
  2987. hres = S_OK;
  2988. exit_gracefully:
  2989. TraceLeaveValue(hres);
  2990. }
  2991. /*-----------------------------------------------------------------------------
  2992. / CQueryFrame::SelectForm
  2993. / -----------------------
  2994. / Changes the current form to the one specified as an into the DPA.
  2995. /
  2996. / In:
  2997. / iForm = form to be selected
  2998. /
  2999. / Out:
  3000. / -
  3001. /----------------------------------------------------------------------------*/
  3002. HRESULT CQueryFrame::SelectForm(REFCLSID clsidForm)
  3003. {
  3004. HRESULT hres;
  3005. LPQUERYFORM pQueryForm, pOldQueryForm;
  3006. LPQUERYFORMPAGE pQueryFormPage;
  3007. LPCQPAGE pPage;
  3008. INT nCmdShow = SW_SHOW;
  3009. TCHAR szBuffer[64], szTitle[MAX_PATH];;
  3010. TC_ITEM tci;
  3011. INT i;
  3012. TraceEnter(TRACE_FORMS, "CQueryFrame::SelectForm");
  3013. pQueryForm = FindQueryForm(clsidForm);
  3014. TraceAssert(pQueryForm);
  3015. if (!pQueryForm)
  3016. ExitGracefully(hres, S_FALSE, "Failed to find the requested form");
  3017. // Change the currently displayed form and change the displayed
  3018. // tabs to correctly indicate this
  3019. if ((pQueryForm != _pCurrentForm))
  3020. {
  3021. if (!OnNewQuery(FALSE)) // prompt the user
  3022. ExitGracefully(hres, S_FALSE, "Failed to select the new form");
  3023. TabCtrl_DeleteAllItems(_hwndFrame);
  3024. for (i = 0 ; i < DSA_GetItemCount(pQueryForm->hdsaPages) ; i++)
  3025. {
  3026. pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryForm->hdsaPages, i);
  3027. pPage = pQueryFormPage->pPage;
  3028. tci.mask = TCIF_TEXT;
  3029. tci.pszText = pQueryForm->pTitle;
  3030. tci.cchTextMax = MAX_PATH;
  3031. if (pPage->idPageName &&
  3032. LoadString(pPage->hInstance, pPage->idPageName, szBuffer, ARRAYSIZE(szBuffer)))
  3033. {
  3034. Trace(TEXT("Loaded page title string %s"), szBuffer);
  3035. tci.pszText = szBuffer;
  3036. }
  3037. TabCtrl_InsertItem(_hwndFrame, i, &tci);
  3038. }
  3039. ComboBox_SetCurSel(_hwndLookFor, pQueryForm->iForm);
  3040. _pCurrentForm = pQueryForm;
  3041. SelectFormPage(pQueryForm, pQueryForm->iPage);
  3042. // Change the dialog title to reflect the new form
  3043. if (LoadString(GLOBAL_HINSTANCE, IDS_FRAMETITLE, szBuffer, ARRAYSIZE(szBuffer)))
  3044. {
  3045. wsprintf(szTitle, szBuffer, pQueryForm->pTitle);
  3046. SetWindowText(_hwnd, szTitle);
  3047. }
  3048. // Tell the handler that we have changed the form, they can then use this
  3049. // new form name to modify their UI.
  3050. _pQueryHandler->ActivateView(CQRVA_FORMCHANGED, (WPARAM)lstrlen(pQueryForm->pTitle), (LPARAM)pQueryForm->pTitle);
  3051. }
  3052. hres = S_OK;
  3053. exit_gracefully:
  3054. TraceLeaveResult(hres);
  3055. }
  3056. /*-----------------------------------------------------------------------------
  3057. / CQueryFrame::SelectFormPage
  3058. / ---------------------------
  3059. / Change the currently active page of a query form to the one specified
  3060. / by the index.
  3061. /
  3062. / In:
  3063. / pQueryForm = query form to be changed
  3064. / iForm = form to be selected
  3065. /
  3066. / Out:
  3067. / -
  3068. /----------------------------------------------------------------------------*/
  3069. VOID CQueryFrame::SelectFormPage(LPQUERYFORM pQueryForm, INT iPage)
  3070. {
  3071. LPQUERYFORMPAGE pQueryFormPage;
  3072. RECT rect;
  3073. TraceEnter(TRACE_FORMS, "CQueryFrame::SelectFormPage");
  3074. pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryForm->hdsaPages, iPage);
  3075. // Have we changed the query form page? If so then display the now dialog
  3076. // hiding the previous one. We call the TabCtrl to find out where we should
  3077. // be placing this new control.
  3078. if (pQueryFormPage != _pCurrentFormPage)
  3079. {
  3080. // Reflect the change into the tab control
  3081. TabCtrl_SetCurSel(_hwndFrame, iPage);
  3082. pQueryForm->iPage = iPage;
  3083. // Fix the size and visability of the new form
  3084. if (_pCurrentFormPage)
  3085. ShowWindow(_pCurrentFormPage->hwndPage, SW_HIDE);
  3086. GetRealWindowInfo(_hwndFrame, &rect, NULL);
  3087. TabCtrl_AdjustRect(_hwndFrame, FALSE, &rect);
  3088. SetWindowPos(pQueryFormPage->hwndPage,
  3089. HWND_TOP,
  3090. rect.left, rect.top,
  3091. rect.right - rect.left,
  3092. rect.bottom - rect.top,
  3093. SWP_SHOWWINDOW);
  3094. _pCurrentFormPage = pQueryFormPage;
  3095. }
  3096. TraceLeave();
  3097. }
  3098. /*-----------------------------------------------------------------------------
  3099. / CQueryFrame::CallFormPages
  3100. / --------------------------
  3101. / Given a query form traverse the array of pages calling each of them
  3102. / with the given message information. If any of the pages return
  3103. / an error code (other than E_NOTIMPL) we bail.
  3104. /
  3105. / In:
  3106. / pQueryForm = query form to call
  3107. / uMsg, wParam, lParam = parameters for the page
  3108. /
  3109. / Out:
  3110. / HRESULT
  3111. /----------------------------------------------------------------------------*/
  3112. HRESULT CQueryFrame::CallFormPages(LPQUERYFORM pQueryForm, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3113. {
  3114. HRESULT hres = S_OK;
  3115. INT iPage;
  3116. TraceEnter(TRACE_FORMS, "CQueryFrame::CallFormPages");
  3117. if (!pQueryForm || !pQueryForm->hdsaPages)
  3118. ExitGracefully(hres, E_FAIL, "No pQueryForm || pQueryForm->hdsaPages == NULL");
  3119. Trace(TEXT("pQueryForm %08x"), pQueryForm);
  3120. Trace(TEXT("uMsg %08x, wParam %08x, lParam %08x"), uMsg, wParam, lParam);
  3121. Trace(TEXT("%d pages to call"), DSA_GetItemCount(pQueryForm->hdsaPages));
  3122. // Call each page in turn if it matches the filter we have been given for calling
  3123. // down. If a page returns S_FALSE or a FAILURE then we exit the loop. If the
  3124. // failure however is E_NOTIMPL then we ignore.
  3125. for (iPage = 0 ; iPage < DSA_GetItemCount(pQueryForm->hdsaPages); iPage++)
  3126. {
  3127. LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryForm->hdsaPages, iPage);
  3128. TraceAssert(pQueryFormPage);
  3129. hres = _CallPageProc(pQueryFormPage, uMsg, wParam, lParam);
  3130. if (FAILED(hres) && (hres != E_NOTIMPL))
  3131. {
  3132. TraceMsg("PageProc returned a FAILURE");
  3133. break;
  3134. }
  3135. else if (hres == S_FALSE)
  3136. {
  3137. TraceMsg("PageProc returned S_FALSE, exiting loop");
  3138. break;
  3139. }
  3140. }
  3141. exit_gracefully:
  3142. TraceLeaveResult(hres);
  3143. }
  3144. /*-----------------------------------------------------------------------------
  3145. / CQueryFrame::FindQueryForm
  3146. / --------------------------
  3147. / Given the CLSID for the form return a pointer to its LPQUERYFORM structure,
  3148. / or NULL if not found.
  3149. /
  3150. / In:
  3151. / clsidForm = ID of the form
  3152. /
  3153. / Out:
  3154. / LPQUERYFORM
  3155. /----------------------------------------------------------------------------*/
  3156. LPQUERYFORM CQueryFrame::FindQueryForm(REFCLSID clsidForm)
  3157. {
  3158. LPQUERYFORM pQueryForm = NULL;
  3159. INT i;
  3160. TraceEnter(TRACE_FORMS, "CQueryFrame::FindQueryForm");
  3161. TraceGUID("Form ID", clsidForm);
  3162. for (i = 0 ; _hdsaForms && (i < DSA_GetItemCount(_hdsaForms)) ; i++)
  3163. {
  3164. pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, i);
  3165. TraceAssert(pQueryForm);
  3166. if (IsEqualCLSID(clsidForm, pQueryForm->clsidForm))
  3167. {
  3168. Trace(TEXT("Form is index %d (%08x)"), i, pQueryForm);
  3169. break;
  3170. }
  3171. }
  3172. if (!_hdsaForms || (i >= DSA_GetItemCount(_hdsaForms)))
  3173. pQueryForm = NULL;
  3174. TraceLeaveValue(pQueryForm);
  3175. }