4101 lines
130 KiB
C++
4101 lines
130 KiB
C++
|
#include "pch.h"
|
||
|
#include "uxtheme.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ Private data and helper functions
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
//
|
||
|
// ICommonQuery stuff
|
||
|
//
|
||
|
|
||
|
class CCommonQuery : public ICommonQuery, IObjectWithSite
|
||
|
{
|
||
|
private:
|
||
|
LONG _cRef;
|
||
|
IUnknown* _punkSite;
|
||
|
|
||
|
public:
|
||
|
CCommonQuery();
|
||
|
~CCommonQuery();
|
||
|
|
||
|
// IUnknown
|
||
|
STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObject);
|
||
|
STDMETHOD_(ULONG, AddRef)();
|
||
|
STDMETHOD_(ULONG, Release)();
|
||
|
|
||
|
// ICommonQuery
|
||
|
STDMETHOD(OpenQueryWindow)(THIS_ HWND hwndParent, LPOPENQUERYWINDOW pOpenQueryWnd, IDataObject** ppDataObject);
|
||
|
|
||
|
// IObjectWithSite
|
||
|
STDMETHODIMP SetSite(IUnknown* punk);
|
||
|
STDMETHODIMP GetSite(REFIID riid, void **ppv);
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// View layout constants used by our dialogs
|
||
|
//
|
||
|
|
||
|
#define VIEWER_DEFAULT_CY 200
|
||
|
|
||
|
#define COMBOEX_IMAGE_CX 16
|
||
|
#define COMBOEX_IMAGE_CY 16
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
HDSA hdsaPages; // DSA containing page entries
|
||
|
DWORD dwFlags; // flags
|
||
|
CLSID clsidForm; // CLSID identifier for this form
|
||
|
LPTSTR pTitle; // title used for drop down / title bar
|
||
|
HICON hIcon; // hIcon passed by caller
|
||
|
INT iImage; // image list index of icon
|
||
|
INT iForm; // visible index of form in control
|
||
|
INT iPage; // currently selected page on form
|
||
|
} QUERYFORM, * LPQUERYFORM;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
CLSID clsidForm; // CLSID to associate this form with
|
||
|
LPCQPAGE pPage; // CQPAGE structures
|
||
|
LPCQPAGEPROC pPageProc; // PageProc's used by thunking layer
|
||
|
LPARAM lParam; // PAGEPROC lParam
|
||
|
HWND hwndPage; // hWnd of page dialog // = NULL if none
|
||
|
} QUERYFORMPAGE, * LPQUERYFORMPAGE;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
LPCQSCOPE pScope;
|
||
|
INT iImage;
|
||
|
} QUERYSCOPE, * LPQUERYSCOPE;
|
||
|
|
||
|
class CQueryFrame : public IQueryFrame
|
||
|
{
|
||
|
friend INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg);
|
||
|
friend INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
public:
|
||
|
CQueryFrame(IUnknown* punkSite, LPOPENQUERYWINDOW pOpenQueryWindow, IDataObject** ppDataObject);
|
||
|
~CQueryFrame();
|
||
|
|
||
|
// IUnknown
|
||
|
STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObject);
|
||
|
STDMETHOD_(ULONG, AddRef)();
|
||
|
STDMETHOD_(ULONG, Release)();
|
||
|
|
||
|
// Internal helper functions
|
||
|
STDMETHOD(DoModal)(HWND hwndParent);
|
||
|
|
||
|
// IQueryFrame
|
||
|
STDMETHOD(AddScope)(THIS_ LPCQSCOPE pScope, INT i, BOOL fSelect);
|
||
|
STDMETHOD(GetWindow)(THIS_ HWND* phWnd);
|
||
|
STDMETHOD(InsertMenus)(THIS_ HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidth);
|
||
|
STDMETHOD(RemoveMenus)(THIS_ HMENU hmenuShared);
|
||
|
STDMETHOD(SetMenu)(THIS_ HMENU hmenuShared, HOLEMENU holereservedMenu);
|
||
|
STDMETHOD(SetStatusText)(THIS_ LPCTSTR pszStatusText);
|
||
|
STDMETHOD(StartQuery)(THIS_ BOOL fStarting);
|
||
|
STDMETHOD(LoadQuery)(THIS_ IPersistQuery* pPersistQuery);
|
||
|
STDMETHOD(SaveQuery)(THIS_ IPersistQuery* pPersistQuery);
|
||
|
STDMETHOD(CallForm)(THIS_ LPCLSID pclsidForm, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
STDMETHOD(GetScope)(THIS_ LPCQSCOPE* ppScope);
|
||
|
STDMETHOD(GetHandler)(THIS_ REFIID riid, void **ppv);
|
||
|
|
||
|
protected:
|
||
|
// Helper functions
|
||
|
VOID CloseQueryFrame(HRESULT hres);
|
||
|
INT FrameMessageBox(LPCTSTR pPrompt, UINT uType);
|
||
|
|
||
|
// Message handlers
|
||
|
HRESULT OnInitDialog(HWND hwnd);
|
||
|
VOID DoEnableControls(VOID);
|
||
|
LRESULT OnNotify(INT idCtrl, LPNMHDR pNotify);
|
||
|
VOID OnSize(INT cx, INT cy);
|
||
|
VOID OnGetMinMaxInfo(LPMINMAXINFO lpmmi);
|
||
|
VOID OnCommand(WPARAM wParam, LPARAM lParam);
|
||
|
VOID OnInitMenu(HMENU hMenu);
|
||
|
VOID OnEnterMenuLoop(BOOL fEntering);
|
||
|
VOID OnMenuSelect(HMENU hMenu, UINT uID);
|
||
|
HRESULT OnFindNow(VOID);
|
||
|
BOOL OnNewQuery(BOOL fAlwaysPrompt);
|
||
|
HRESULT OnBrowse(VOID);
|
||
|
HRESULT OnHelp(LPHELPINFO pHelpInfo);
|
||
|
|
||
|
// Form/Scope helper fucntions
|
||
|
HRESULT InsertScopeIntoList(LPCQSCOPE pScope, INT i, BOOL fAddToControl);
|
||
|
HRESULT AddScopeToControl(LPQUERYSCOPE pQueryScope, INT i);
|
||
|
HRESULT PopulateScopeControl(VOID);
|
||
|
HRESULT GetSelectedScope(LPQUERYSCOPE* ppQueryScope);
|
||
|
HRESULT AddFromIQueryForm(IQueryForm* pQueryForm, HKEY hkeyForm);
|
||
|
HRESULT GatherForms(VOID);
|
||
|
HRESULT GetForms(HKEY hKeyForms, LPTSTR pName);
|
||
|
HRESULT PopulateFormControl(BOOL fIncludeHidden);
|
||
|
HRESULT SelectForm(REFCLSID clsidForm);
|
||
|
VOID SelectFormPage(LPQUERYFORM pQueryForm, INT iPage);
|
||
|
HRESULT CallFormPages(LPQUERYFORM pQueryForm, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
LPQUERYFORM FindQueryForm(REFCLSID clsidForm);
|
||
|
|
||
|
private:
|
||
|
LONG _cRef; // reference count for the object
|
||
|
|
||
|
IUnknown* _punkSite; // site object we need to pass through
|
||
|
IQueryHandler* _pQueryHandler; // IQueryHandler object we need to interact with
|
||
|
LPOPENQUERYWINDOW _pOpenQueryWnd; // copy of initial parameters provided by caller
|
||
|
IDataObject** _ppDataObject; // receives the resulting data object from handler
|
||
|
|
||
|
DWORD _dwHandlerViewFlags; // flags from the handler
|
||
|
|
||
|
BOOL _fQueryRunning:1; // = 1 => query has been started, via IQueryFrame::StartQuery(TRUE)
|
||
|
BOOL _fExitModalLoop:1; // = 1 => must leave modal loop
|
||
|
BOOL _fScopesPopulated:1; // = 1 => scope control has been populated
|
||
|
BOOL _fTrackingMenuBar:1; // = 1 => then we are tracking the menu bar, therefore send activates etc
|
||
|
BOOL _fAddScopesNYI:1; // = 1 => did AddScopes return E_NOTIMPL
|
||
|
BOOL _fScopesAddedAsync:1; // = 1 => scopes added async by the handler
|
||
|
BOOL _fScopeImageListSet:1; // = 1 => scope image list has been set
|
||
|
BOOL _fFormFirstEnable:1; // = 1 => enabling controls for first item, so ensure we set focus
|
||
|
|
||
|
HRESULT _hResult; // result value stored by CloseQueryFrame
|
||
|
HKEY _hkHandler; // registry key for the handler
|
||
|
|
||
|
HWND _hwnd; // main window handle
|
||
|
HWND _hwndResults; // result viewer
|
||
|
HWND _hwndStatus; // status bar
|
||
|
|
||
|
HWND _hwndFrame; // Query Pages tab control
|
||
|
HWND _hwndLookForLabel; // "Find:"
|
||
|
HWND _hwndLookFor; // Form combo
|
||
|
HWND _hwndLookInLabel; // "In:"
|
||
|
HWND _hwndLookIn; // Scope combo
|
||
|
HWND _hwndBrowse; // "Browse"
|
||
|
HWND _hwndFindNow; // "Find now"
|
||
|
HWND _hwndStop; // "Stop"
|
||
|
HWND _hwndNewQuery; // "New Query"
|
||
|
HWND _hwndOK; // "OK"
|
||
|
HWND _hwndCancel; // "Cancel"
|
||
|
HWND _hwndFindAnimation; // Query issued animation
|
||
|
|
||
|
HICON _hiconSmall; // large/small app icons
|
||
|
HICON _hiconLarge;
|
||
|
|
||
|
HMENU _hmenuFile; // handle of the frames menu bar
|
||
|
|
||
|
HIMAGELIST _himlForms; // image list for query form objects
|
||
|
|
||
|
SIZE _szMinTrack; // minimum track size of the window
|
||
|
|
||
|
INT _dxFormAreaLeft; // offset to left edge of form area (from window left)
|
||
|
INT _dxFormAreaRight; // offset to right edge of form area (from window right)
|
||
|
INT _dxButtonsLeft; // offset to left edge of buttons (from window right)
|
||
|
INT _dxAnimationLeft; // offset to left edge of aniimation (from window right)
|
||
|
INT _dyResultsTop; // offset to top of results (from top of window)
|
||
|
INT _dyOKTop; // offset to top of "OK" buttom (from results top)
|
||
|
INT _dxGap; // gap between OK + Cancel / LookIn + Browse
|
||
|
INT _dyGap; // gap between bottom of OK,Cancel and the frame.
|
||
|
|
||
|
INT _cyStatus; // height of the status bar
|
||
|
|
||
|
HDSA _hdsaForms; // forms DSA
|
||
|
HDSA _hdsaPages; // pages DSA
|
||
|
SIZE _szForm; // size of the (current form we are displaying)
|
||
|
|
||
|
HDSA _hdsaScopes; // scopes DSA
|
||
|
INT _iDefaultScope; // index of the defualt scope to select (into DSA)
|
||
|
|
||
|
LPQUERYFORM _pCurrentForm; // == NULL if none / else -> form structure
|
||
|
LPQUERYFORMPAGE _pCurrentFormPage; // == NULL if none / else -> page structure
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Helper functions
|
||
|
//
|
||
|
|
||
|
INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg);
|
||
|
|
||
|
HRESULT _CallScopeProc(LPQUERYSCOPE pQueryScope, UINT uMsg, LPVOID pVoid);
|
||
|
INT _FreeScope(LPQUERYSCOPE pQueryScope);
|
||
|
INT _FreeScopeCB(LPVOID pItem, LPVOID pData);
|
||
|
|
||
|
HRESULT _CallPageProc(LPQUERYFORMPAGE pQueryFormPage, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||
|
INT _FreeQueryFormCB(LPVOID pItem, LPVOID pData);
|
||
|
INT _FreeQueryForm(LPQUERYFORM pQueryForm);
|
||
|
INT _FreeQueryFormPageCB(LPVOID pItem, LPVOID pData);
|
||
|
INT _FreeQueryFormPage(LPQUERYFORMPAGE pQueryFormPage);
|
||
|
|
||
|
HRESULT _AddFormsProc(LPARAM lParam, LPCQFORM pForm);
|
||
|
HRESULT _AddPagesProc(LPARAM lParam, REFCLSID clsidForm, LPCQPAGE pPage);
|
||
|
|
||
|
//
|
||
|
// Help stuff
|
||
|
//
|
||
|
|
||
|
#define HELP_FILE (NULL)
|
||
|
|
||
|
static DWORD const aHelpIDs[] =
|
||
|
{
|
||
|
0, 0
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// constant strings
|
||
|
//
|
||
|
|
||
|
TCHAR const c_szCLSID[] = TEXT("CLSID");
|
||
|
TCHAR const c_szForms[] = TEXT("Forms");
|
||
|
TCHAR const c_szFlags[] = TEXT("Flags");
|
||
|
|
||
|
TCHAR const c_szCommonQuery[] = TEXT("CommonQuery");
|
||
|
TCHAR const c_szHandlerIs[] = TEXT("Handler");
|
||
|
TCHAR const c_szFormIs[] = TEXT("Form");
|
||
|
TCHAR const c_szSearchPaneHidden[] = TEXT("SearchPaneHidden");
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CCommonQuery
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
CCommonQuery::CCommonQuery() :
|
||
|
_punkSite(NULL), _cRef(1)
|
||
|
{
|
||
|
DllAddRef();
|
||
|
}
|
||
|
|
||
|
CCommonQuery::~CCommonQuery()
|
||
|
{
|
||
|
DoRelease(_punkSite);
|
||
|
DllRelease();
|
||
|
}
|
||
|
|
||
|
|
||
|
// QI handling
|
||
|
|
||
|
ULONG CCommonQuery::AddRef()
|
||
|
{
|
||
|
return InterlockedIncrement(&_cRef);
|
||
|
}
|
||
|
|
||
|
ULONG CCommonQuery::Release()
|
||
|
{
|
||
|
if (InterlockedDecrement(&_cRef))
|
||
|
return _cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
HRESULT CCommonQuery::QueryInterface(REFIID riid, void **ppv)
|
||
|
{
|
||
|
static const QITAB qit[] =
|
||
|
{
|
||
|
QITABENT(CCommonQuery, ICommonQuery), // IID_ICommonQuery
|
||
|
QITABENT(CCommonQuery, IObjectWithSite), // IID_IObjectWithSite
|
||
|
{0, 0 },
|
||
|
};
|
||
|
return QISearch(this, qit, riid, ppv);
|
||
|
}
|
||
|
|
||
|
STDAPI CCommonQuery_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
|
||
|
{
|
||
|
CCommonQuery *pcq = new CCommonQuery;
|
||
|
if (!pcq)
|
||
|
return E_OUTOFMEMORY;
|
||
|
|
||
|
HRESULT hres = pcq->QueryInterface(IID_IUnknown, (void **)ppunk);
|
||
|
pcq->Release();
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
// ICommonQuery methods
|
||
|
|
||
|
STDMETHODIMP CCommonQuery::OpenQueryWindow(THIS_ HWND hwndParent, LPOPENQUERYWINDOW pOpenQueryWnd, IDataObject** ppDataObject)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
CQueryFrame* pQueryFrame = NULL;
|
||
|
|
||
|
TraceEnter(TRACE_QUERY, "CCommonQuery::OpenQueryWindow");
|
||
|
|
||
|
if (!pOpenQueryWnd || (hwndParent && !IsWindow(hwndParent)))
|
||
|
ExitGracefully(hres, E_INVALIDARG, "Bad parameters");
|
||
|
|
||
|
if (ppDataObject)
|
||
|
*(ppDataObject) = NULL;
|
||
|
|
||
|
pQueryFrame = new CQueryFrame(_punkSite, pOpenQueryWnd, ppDataObject);
|
||
|
TraceAssert(pQueryFrame);
|
||
|
|
||
|
if (!pQueryFrame)
|
||
|
ExitGracefully(hres, E_OUTOFMEMORY, "Failed to construct the query window object");
|
||
|
|
||
|
hres = pQueryFrame->DoModal(hwndParent); // don't bother fail gracefully etc
|
||
|
FailGracefully(hres, "Failed on calling DoModal");
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
DoRelease(pQueryFrame);
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
// IObjectWithSite
|
||
|
|
||
|
STDMETHODIMP CCommonQuery::SetSite(IUnknown* punk)
|
||
|
{
|
||
|
HRESULT hres = S_OK;
|
||
|
|
||
|
TraceEnter(TRACE_QUERY, "CCommonQuery::SetSite");
|
||
|
|
||
|
DoRelease(_punkSite);
|
||
|
|
||
|
if (punk)
|
||
|
{
|
||
|
TraceMsg("QIing for IUnknown from the site object");
|
||
|
|
||
|
hres = punk->QueryInterface(IID_IUnknown, (void **)&_punkSite);
|
||
|
FailGracefully(hres, "Failed to get IUnknown from the site object");
|
||
|
}
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CCommonQuery::GetSite(REFIID riid, void **ppv)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
TraceEnter(TRACE_QUERY, "CCommonQuery::GetSite");
|
||
|
|
||
|
if (!_punkSite)
|
||
|
ExitGracefully(hres, E_NOINTERFACE, "No site to QI from");
|
||
|
|
||
|
hres = _punkSite->QueryInterface(riid, ppv);
|
||
|
FailGracefully(hres, "QI failed on the site unknown object");
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// IQueryFrame stuff
|
||
|
|
||
|
CQueryFrame::CQueryFrame(IUnknown *punkSite, LPOPENQUERYWINDOW pOpenQueryWindow, IDataObject** ppDataObject) :
|
||
|
_cRef(1), _punkSite(punkSite), _pOpenQueryWnd(pOpenQueryWindow),
|
||
|
_ppDataObject(ppDataObject), _hiconLarge(NULL), _hiconSmall(NULL)
|
||
|
{
|
||
|
if (_punkSite)
|
||
|
_punkSite->AddRef();
|
||
|
|
||
|
DllAddRef();
|
||
|
}
|
||
|
|
||
|
CQueryFrame::~CQueryFrame()
|
||
|
{
|
||
|
DoRelease(_punkSite);
|
||
|
|
||
|
if (_hiconLarge)
|
||
|
DestroyIcon(_hiconLarge);
|
||
|
|
||
|
if (_hiconSmall)
|
||
|
DestroyIcon(_hiconSmall);
|
||
|
|
||
|
if (_hkHandler)
|
||
|
RegCloseKey(_hkHandler);
|
||
|
|
||
|
if (_hmenuFile)
|
||
|
DestroyMenu(_hmenuFile);
|
||
|
|
||
|
if (_himlForms)
|
||
|
ImageList_Destroy(_himlForms);
|
||
|
|
||
|
if (_hdsaForms)
|
||
|
{
|
||
|
Trace(TEXT("Destroying QUERYFORM DSA (%d)"), DSA_GetItemCount(_hdsaForms));
|
||
|
DSA_DestroyCallback(_hdsaForms, _FreeQueryFormCB, NULL);
|
||
|
_hdsaForms = NULL;
|
||
|
}
|
||
|
|
||
|
if (_hdsaPages)
|
||
|
{
|
||
|
Trace(TEXT("Destroying QUERYFORMPAGE DSA (%d)"), DSA_GetItemCount(_hdsaPages));
|
||
|
DSA_DestroyCallback(_hdsaPages, _FreeQueryFormPageCB, NULL);
|
||
|
_hdsaPages = NULL;
|
||
|
}
|
||
|
|
||
|
if (_hdsaScopes)
|
||
|
{
|
||
|
Trace(TEXT("Destroying QUERYSCOPE DSA (%d)"), DSA_GetItemCount(_hdsaScopes));
|
||
|
DSA_DestroyCallback(_hdsaScopes, _FreeScopeCB, NULL);
|
||
|
_hdsaScopes = NULL;
|
||
|
}
|
||
|
|
||
|
_pCurrentForm = NULL;
|
||
|
_pCurrentFormPage = NULL;
|
||
|
|
||
|
// Now discard the handler and its window (if we have one), if
|
||
|
// we don't do this they will never kill their objects
|
||
|
|
||
|
if (_hwndResults)
|
||
|
{
|
||
|
DestroyWindow(_hwndResults);
|
||
|
_hwndResults = NULL;
|
||
|
}
|
||
|
|
||
|
DllRelease();
|
||
|
}
|
||
|
|
||
|
// QI handling
|
||
|
|
||
|
ULONG CQueryFrame::AddRef()
|
||
|
{
|
||
|
return InterlockedIncrement(&_cRef);
|
||
|
}
|
||
|
|
||
|
ULONG CQueryFrame::Release()
|
||
|
{
|
||
|
if (InterlockedDecrement(&_cRef))
|
||
|
return _cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
HRESULT CQueryFrame::QueryInterface(REFIID riid, void **ppv)
|
||
|
{
|
||
|
static const QITAB qit[] =
|
||
|
{
|
||
|
QITABENT(CQueryFrame, IQueryFrame), // IID_IQueryFrame
|
||
|
{0, 0 },
|
||
|
};
|
||
|
return QISearch(this, qit, riid, ppv);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ IQueryFrame
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::DoModal(HWND hwndParent)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
HWND hwndFrame = NULL;
|
||
|
HWND hwndFocus = NULL;
|
||
|
HWND hwndTopOwner = hwndParent;
|
||
|
MSG msg;
|
||
|
INITCOMMONCONTROLSEX iccex;
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::DoModal");
|
||
|
|
||
|
// initialize with the query handler we need
|
||
|
|
||
|
hres = CoCreateInstance(_pOpenQueryWnd->clsidHandler, NULL, CLSCTX_INPROC_SERVER, IID_IQueryHandler, (LPVOID*)&_pQueryHandler);
|
||
|
FailGracefully(hres, "Failed to get IQueryHandler for the given CLSID");
|
||
|
|
||
|
hres = _pQueryHandler->Initialize(this, _pOpenQueryWnd->dwFlags, _pOpenQueryWnd->pHandlerParameters);
|
||
|
FailGracefully(hres, "Failed to initialize the handler");
|
||
|
|
||
|
// mimic the behaviour of DialogBox by working out which control previously
|
||
|
// had focus, which window to disable and then running a message
|
||
|
// pump for our dialog. Having done this we can then restore the state
|
||
|
// back to something sensible.
|
||
|
|
||
|
_fExitModalLoop = FALSE; // can be changed from hear down
|
||
|
|
||
|
iccex.dwSize = SIZEOF(iccex);
|
||
|
iccex.dwICC = ICC_USEREX_CLASSES;
|
||
|
InitCommonControlsEx(&iccex);
|
||
|
|
||
|
if (_pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHUI)
|
||
|
{
|
||
|
hwndFrame = CreateDialogParam(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDD_FILTER),
|
||
|
hwndParent,
|
||
|
QueryWnd_DlgProc, (LPARAM)this);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hwndFrame = CreateDialogParam(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDD_FIND),
|
||
|
hwndParent,
|
||
|
QueryWnd_DlgProc, (LPARAM)this);
|
||
|
}
|
||
|
|
||
|
if (!hwndFrame)
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to create the dialog");
|
||
|
|
||
|
hwndFocus = GetFocus();
|
||
|
|
||
|
if (hwndTopOwner)
|
||
|
{
|
||
|
// walk up the window stack looking for the window to be disabled, this must
|
||
|
// be the top-most non-child window. If the resulting window is either
|
||
|
// the desktop or is already disabled then don't bother.
|
||
|
|
||
|
while (GetWindowLong(hwndTopOwner, GWL_STYLE) & WS_CHILD)
|
||
|
hwndTopOwner = GetParent(hwndTopOwner);
|
||
|
|
||
|
TraceAssert(hwndTopOwner);
|
||
|
|
||
|
if ((hwndTopOwner == GetDesktopWindow())
|
||
|
|| EnableWindow(hwndTopOwner, FALSE))
|
||
|
{
|
||
|
TraceMsg("Parent is disabled or the desktop window, therefore setting to NULL");
|
||
|
hwndTopOwner = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ShowWindow(hwndFrame, SW_SHOW); // show the query window
|
||
|
|
||
|
while (!_fExitModalLoop && GetMessage(&msg, NULL, 0, 0) > 0)
|
||
|
{
|
||
|
if (!QueryWnd_MessageProc(hwndFrame, &msg) && !IsDialogMessage(hwndFrame, &msg))
|
||
|
{
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now tidy up, make the parent the active window, enable the top most
|
||
|
// window if there is one and restore focus as required.
|
||
|
|
||
|
if (hwndTopOwner)
|
||
|
EnableWindow(hwndTopOwner, TRUE);
|
||
|
|
||
|
if (hwndParent && (GetActiveWindow() == hwndFrame))
|
||
|
{
|
||
|
TraceMsg("Passing activation to parent");
|
||
|
SetActiveWindow(hwndParent);
|
||
|
}
|
||
|
|
||
|
if (IsWindow(hwndFocus))
|
||
|
SetFocus(hwndFocus);
|
||
|
|
||
|
DestroyWindow(hwndFrame); // discard the current frame window
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
DoRelease(_pQueryHandler);
|
||
|
|
||
|
TraceLeaveResult(_hResult);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::AddScope(THIS_ LPCQSCOPE pScope, INT i, BOOL fSelect)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::AddScope");
|
||
|
|
||
|
if (!pScope)
|
||
|
ExitGracefully(hres, E_INVALIDARG, "No scope to add to the list");
|
||
|
|
||
|
// Add the scope to the control and then ensure that we either have
|
||
|
// its index stored (for default selection) or we select the
|
||
|
// item.
|
||
|
|
||
|
if (!_hdsaScopes || !DSA_GetItemCount(_hdsaScopes))
|
||
|
{
|
||
|
TraceMsg("First scope being added, thefore selecting");
|
||
|
fSelect = TRUE;
|
||
|
}
|
||
|
|
||
|
hres = InsertScopeIntoList(pScope, i, _fScopesPopulated);
|
||
|
FailGracefully(hres, "Failed to add scope to control");
|
||
|
|
||
|
if (fSelect)
|
||
|
{
|
||
|
if (!_fScopesPopulated)
|
||
|
{
|
||
|
Trace(TEXT("Storing default scope index %d"), ShortFromResult(hres));
|
||
|
_iDefaultScope = ShortFromResult(hres);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Trace(TEXT("Selecting scope index %d"), ShortFromResult(hres));
|
||
|
ComboBox_SetCurSel(_hwndLookIn, ShortFromResult(hres));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::GetWindow(THIS_ HWND* phWnd)
|
||
|
{
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::GetWindow");
|
||
|
|
||
|
TraceAssert(phWnd);
|
||
|
*phWnd = _hwnd;
|
||
|
|
||
|
TraceLeaveResult(S_OK);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
// Add a menu group to the given menu bar, updating the width index accordingly
|
||
|
// so that other people can merge in accordingly
|
||
|
|
||
|
VOID _DoInsertMenu(HMENU hMenu, INT iIndexTo, HMENU hMenuToInsert, INT iIndexFrom)
|
||
|
{
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
HMENU hPopupMenu = NULL;
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "_DoInsertMenu");
|
||
|
|
||
|
hPopupMenu = CreatePopupMenu();
|
||
|
|
||
|
if (hPopupMenu)
|
||
|
{
|
||
|
Shell_MergeMenus(hPopupMenu, GetSubMenu(hMenuToInsert, iIndexFrom), 0x0, 0x0, 0x7fff, 0);
|
||
|
|
||
|
GetMenuString(hMenuToInsert, iIndexFrom, szBuffer, ARRAYSIZE(szBuffer), MF_BYPOSITION);
|
||
|
InsertMenu(hMenu, iIndexTo, MF_BYPOSITION|MF_POPUP, (UINT_PTR)hPopupMenu, szBuffer);
|
||
|
}
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
VOID _AddMenuGroup(HMENU hMenuShared, HMENU hMenuGroup, LONG iInsertAt, LPLONG pWidth)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
HMENU hMenu;
|
||
|
INT i;
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "_AddMenuGroup");
|
||
|
|
||
|
TraceAssert(hMenuShared);
|
||
|
TraceAssert(hMenuGroup);
|
||
|
TraceAssert(pWidth);
|
||
|
|
||
|
for (i = 0 ; i < GetMenuItemCount(hMenuGroup) ; i++)
|
||
|
{
|
||
|
_DoInsertMenu(hMenuShared, iInsertAt+i, hMenuGroup, i);
|
||
|
*pWidth += 1;
|
||
|
}
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::InsertMenus(THIS_ HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidth)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::InsertMenus");
|
||
|
|
||
|
if (!hmenuShared || !lpMenuWidth)
|
||
|
ExitGracefully(hres, E_INVALIDARG, "Unable to insert menus");
|
||
|
|
||
|
// if we don't have the menu bar already loaded then lets load it,
|
||
|
// having done that we can then add our menu to the bar (we only
|
||
|
// provide entries for the file menu).
|
||
|
|
||
|
if (!_hmenuFile)
|
||
|
{
|
||
|
_hmenuFile = LoadMenu(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDR_FILEMENUGROUP));
|
||
|
|
||
|
if (!_hmenuFile)
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to load base menu defn");
|
||
|
}
|
||
|
|
||
|
_AddMenuGroup(hmenuShared, _hmenuFile, 0, &lpMenuWidth->width[0]);
|
||
|
|
||
|
hres = S_OK; // success
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::RemoveMenus(THIS_ HMENU hmenuShared)
|
||
|
{
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::RemoveMenus");
|
||
|
|
||
|
// We don't need to implement this as we copy or menus into the
|
||
|
// menu that the handler supplies - fix DSQUERY if this ever
|
||
|
// changes.
|
||
|
|
||
|
TraceLeaveResult(S_OK);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::SetMenu(THIS_ HMENU hmenuShared, HOLEMENU holereservedMenu)
|
||
|
{
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::SetMenu");
|
||
|
|
||
|
if (!(_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS))
|
||
|
{
|
||
|
HMENU hmenuOld = ::GetMenu(_hwnd);
|
||
|
|
||
|
if (!hmenuShared)
|
||
|
hmenuShared = _hmenuFile;
|
||
|
|
||
|
::SetMenu(_hwnd, hmenuShared);
|
||
|
DoEnableControls(); // ensure the menu state is valid
|
||
|
::DrawMenuBar(_hwnd);
|
||
|
|
||
|
if (hmenuOld && (hmenuOld != _hmenuFile) && (hmenuOld != hmenuShared))
|
||
|
{
|
||
|
TraceMsg("Destroying old menu");
|
||
|
DestroyMenu(hmenuOld);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TraceLeaveResult(S_OK);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::SetStatusText(THIS_ LPCTSTR pszStatusText)
|
||
|
{
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::SetStatusText");
|
||
|
Trace(TEXT("Setting status text to: %s"), pszStatusText);
|
||
|
|
||
|
if (_hwndStatus)
|
||
|
SendMessage(_hwndStatus, SB_SETTEXT, 0, (LPARAM)pszStatusText);
|
||
|
|
||
|
TraceLeaveResult(S_OK);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::StartQuery(THIS_ BOOL fStarting)
|
||
|
{
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::StartQuery");
|
||
|
|
||
|
if (fStarting)
|
||
|
{
|
||
|
Animate_Play(_hwndFindAnimation, 0, -1, -1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Animate_Stop(_hwndFindAnimation);
|
||
|
Animate_Seek(_hwndFindAnimation, 0); // go to start
|
||
|
}
|
||
|
|
||
|
if (_pQueryHandler)
|
||
|
_pQueryHandler->ActivateView(CQRVA_STARTQUERY, (WPARAM)fStarting, 0);
|
||
|
|
||
|
// now set the controls into a sensble state
|
||
|
|
||
|
_fQueryRunning = fStarting;
|
||
|
DoEnableControls();
|
||
|
|
||
|
TraceLeaveResult(S_OK);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::LoadQuery(THIS_ IPersistQuery* pPersistQuery)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
TCHAR szGUID[GUIDSTR_MAX+1];
|
||
|
LPQUERYFORM pQueryForm = NULL;
|
||
|
GUID guid;
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::LoadQuery");
|
||
|
|
||
|
_pQueryHandler->StopQuery(); // ensure that the handler stops its processing
|
||
|
|
||
|
// Attempt to read the handler GUID from the query stream, first try reading it as
|
||
|
// as string then parsing it into something that we can use, if that fails then
|
||
|
// try again, but this time read it as a structure.
|
||
|
//
|
||
|
// having aquired the GUID for the handler make sure that we have the correct handler
|
||
|
// selected.
|
||
|
|
||
|
if (FAILED(pPersistQuery->ReadString(c_szCommonQuery, c_szHandlerIs, szGUID, ARRAYSIZE(szGUID))) ||
|
||
|
!GetGUIDFromString(szGUID, &guid))
|
||
|
{
|
||
|
TraceMsg("Trying new style handler GUID as struct");
|
||
|
|
||
|
hres = pPersistQuery->ReadStruct(c_szCommonQuery, c_szHandlerIs, &guid, SIZEOF(guid));
|
||
|
FailGracefully(hres, "Failed to read handler GUID as struct");
|
||
|
}
|
||
|
|
||
|
if (guid != _pOpenQueryWnd->clsidHandler)
|
||
|
ExitGracefully(hres, E_FAIL, "Persisted handler GUID and specified handler GUID don't match");
|
||
|
|
||
|
hres = _pQueryHandler->LoadQuery(pPersistQuery);
|
||
|
FailGracefully(hres, "Handler failed to load its query data");
|
||
|
|
||
|
// Get the form ID, then look up the form to see if we have one that matches,
|
||
|
// if not then we cannot load any thing else. If we do haved that form then
|
||
|
// ensure that we clear it and then load away.
|
||
|
|
||
|
if (FAILED(pPersistQuery->ReadString(c_szCommonQuery, c_szFormIs, szGUID, ARRAYSIZE(szGUID))) ||
|
||
|
!GetGUIDFromString(szGUID, &guid))
|
||
|
{
|
||
|
TraceMsg("Trying new style form GUID as struct");
|
||
|
|
||
|
hres = pPersistQuery->ReadStruct(c_szCommonQuery, c_szFormIs, &guid, SIZEOF(guid));
|
||
|
FailGracefully(hres, "Failed to read handler GUID as struct");
|
||
|
}
|
||
|
|
||
|
hres = SelectForm(guid);
|
||
|
FailGracefully(hres, "Failed to select the query form");
|
||
|
|
||
|
if (hres == S_FALSE)
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to select the query form to read the query info");
|
||
|
|
||
|
hres = CallFormPages(_pCurrentForm, CQPM_CLEARFORM, 0, 0);
|
||
|
FailGracefully(hres, "Failed to clear form before loading");
|
||
|
|
||
|
// Load the persisted query from the stream, coping correctly with the
|
||
|
// UNICODE / ANSI issue. We will be passed an IPersistQuery object which
|
||
|
// we must then thunk accordingly if we are UNICODE for the pages we
|
||
|
// are going to talk to.
|
||
|
|
||
|
hres = CallFormPages(_pCurrentForm, CQPM_PERSIST, TRUE, (LPARAM)pPersistQuery);
|
||
|
FailGracefully(hres, "Failed to load page data (UNICODE)");
|
||
|
|
||
|
hres = S_OK; // success
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
TraceMsg("Query loaded successfully, select form query");
|
||
|
SelectForm(guid);
|
||
|
}
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::SaveQuery(THIS_ IPersistQuery* pPersistQuery)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
LPQUERYSCOPE pQueryScope;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::SaveQuery");
|
||
|
|
||
|
if (!pPersistQuery)
|
||
|
ExitGracefully(hres, E_INVALIDARG, "No pPersistQuery object to write into");
|
||
|
|
||
|
pPersistQuery->Clear(); // flush the contents
|
||
|
|
||
|
hres = pPersistQuery->WriteStruct(c_szCommonQuery, c_szHandlerIs,
|
||
|
&_pOpenQueryWnd->clsidHandler,
|
||
|
SIZEOF(_pOpenQueryWnd->clsidHandler));
|
||
|
FailGracefully(hres, "Failed to write handler GUID");
|
||
|
|
||
|
hres = pPersistQuery->WriteStruct(c_szCommonQuery, c_szFormIs,
|
||
|
&_pCurrentForm->clsidForm,
|
||
|
SIZEOF(_pCurrentForm->clsidForm));
|
||
|
FailGracefully(hres, "Failed to write form GUID");
|
||
|
|
||
|
// Allow the handler to persist itself into the the stream, this includes
|
||
|
// giving it the current scope to store.
|
||
|
|
||
|
hres = GetSelectedScope(&pQueryScope);
|
||
|
FailGracefully(hres, "Failed to get the scope from the LookIn control");
|
||
|
|
||
|
hres = _pQueryHandler->SaveQuery(pPersistQuery, pQueryScope->pScope);
|
||
|
FailGracefully(hres, "Failed when calling handler to persist itself");
|
||
|
|
||
|
// Save the query into the stream, coping correctly with the
|
||
|
// UNICODE / ANSI issue. We will be passed an IPersistQuery object which
|
||
|
// we must then thunk accordingly if we are UNICODE for the pages we
|
||
|
// are going to talk to.
|
||
|
|
||
|
hres = CallFormPages(_pCurrentForm, CQPM_PERSIST, FALSE, (LPARAM)pPersistQuery);
|
||
|
FailGracefully(hres, "Failed to load page data (UNICODE)");
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::CallForm(THIS_ LPCLSID pclsidForm, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
LPQUERYFORM pQueryForm = _pCurrentForm;
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::CallForm");
|
||
|
|
||
|
if (pclsidForm)
|
||
|
{
|
||
|
pQueryForm = FindQueryForm(*pclsidForm);
|
||
|
TraceAssert(pQueryForm);
|
||
|
}
|
||
|
|
||
|
if (!pQueryForm)
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to find query form for given CLSID");
|
||
|
|
||
|
hres = CallFormPages(pQueryForm, uMsg, wParam, lParam);
|
||
|
FailGracefully(hres, "Failed when calling CallFormPages");
|
||
|
|
||
|
// hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::GetScope(THIS_ LPCQSCOPE* ppScope)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
LPQUERYSCOPE pQueryScope;
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::GetScope");
|
||
|
|
||
|
if (!ppScope)
|
||
|
ExitGracefully(hres, E_INVALIDARG, "ppScope == NULL, thats bad");
|
||
|
|
||
|
hres = GetSelectedScope(&pQueryScope);
|
||
|
FailGracefully(hres, "Failed to get the current scope");
|
||
|
|
||
|
*ppScope = (LPCQSCOPE)CoTaskMemAlloc(pQueryScope->pScope->cbStruct);
|
||
|
TraceAssert(*ppScope);
|
||
|
|
||
|
if (!*ppScope)
|
||
|
ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate the scope block");
|
||
|
|
||
|
memcpy(*ppScope, pQueryScope->pScope, pQueryScope->pScope->cbStruct);
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
STDMETHODIMP CQueryFrame::GetHandler(THIS_ REFIID riid, void **ppv)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::GetHandler");
|
||
|
|
||
|
if (!_pQueryHandler)
|
||
|
ExitGracefully(hres, E_UNEXPECTED, "_pQueryHandler is NULL");
|
||
|
|
||
|
hres = _pQueryHandler->QueryInterface(riid, ppv);
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ Dialog box handler functions (core guts)
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
#define REAL_WINDOW(hwnd) \
|
||
|
(hwnd && \
|
||
|
IsWindowVisible(hwnd) && \
|
||
|
IsWindowEnabled(hwnd) && \
|
||
|
(GetWindowLong(hwnd, GWL_STYLE) & WS_TABSTOP))
|
||
|
|
||
|
HWND _NextTabStop(HWND hwndSearch, BOOL fShift)
|
||
|
{
|
||
|
HWND hwnd;
|
||
|
|
||
|
Trace(TEXT("hwndSearch %08x, fShift %d"), hwndSearch, fShift);
|
||
|
|
||
|
// do we have a window to search into?
|
||
|
|
||
|
while (hwndSearch)
|
||
|
{
|
||
|
// if we have a window then lets check to see if it has any children?
|
||
|
|
||
|
hwnd = GetWindow(hwndSearch, GW_CHILD);
|
||
|
Trace(TEXT("Child of %08x is %08x"), hwndSearch, hwnd);
|
||
|
|
||
|
if (hwnd)
|
||
|
{
|
||
|
// it has a child therefore lets to go its first/last
|
||
|
// and continue the search there for a window that
|
||
|
// matches the criteria we are looking for.
|
||
|
|
||
|
hwnd = GetWindow(hwnd, fShift ? GW_HWNDLAST:GW_HWNDFIRST);
|
||
|
|
||
|
if (!REAL_WINDOW(hwnd))
|
||
|
{
|
||
|
Trace(TEXT("Trying to recurse into %08x"), hwnd);
|
||
|
hwnd = _NextTabStop(hwnd, fShift);
|
||
|
}
|
||
|
|
||
|
Trace(TEXT("Tabstop child of %08x is %08x"), hwndSearch, hwnd);
|
||
|
}
|
||
|
|
||
|
// after all that is hwnd a valid window? if so then pass
|
||
|
// that back out to the caller.
|
||
|
|
||
|
if (REAL_WINDOW(hwnd))
|
||
|
{
|
||
|
Trace(TEXT("Child tab stop was %08x"), hwnd);
|
||
|
return hwnd;
|
||
|
}
|
||
|
|
||
|
// do we have a sibling? if so then lets return that otherwise
|
||
|
// lets just continue to search until we either run out of windows
|
||
|
// or hit something interesting
|
||
|
|
||
|
hwndSearch = GetWindow(hwndSearch, fShift ? GW_HWNDPREV:GW_HWNDNEXT);
|
||
|
|
||
|
if (REAL_WINDOW(hwndSearch))
|
||
|
{
|
||
|
Trace(TEXT("Next tab stop was %08x"), hwndSearch);
|
||
|
return hwndSearch;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hwndSearch;
|
||
|
}
|
||
|
|
||
|
INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg)
|
||
|
{
|
||
|
LRESULT lResult = 0;
|
||
|
CQueryFrame* pQueryFrame = NULL;
|
||
|
NMHDR nmhdr;
|
||
|
|
||
|
pQueryFrame = (CQueryFrame*)GetWindowLongPtr(hwnd, DWLP_USER);
|
||
|
|
||
|
if (!pQueryFrame)
|
||
|
return 0;
|
||
|
|
||
|
if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB))
|
||
|
{
|
||
|
BOOL fCtrl = GetAsyncKeyState(VK_CONTROL) < 0;
|
||
|
BOOL fShift = GetAsyncKeyState(VK_SHIFT) < 0;
|
||
|
|
||
|
// ensure that the focus rectangles are shown
|
||
|
|
||
|
#if (_WIN32_WINNT >= 0x0500)
|
||
|
SendMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0);
|
||
|
#endif
|
||
|
|
||
|
if (fCtrl)
|
||
|
{
|
||
|
// if this is a key press within the parent then lets ensure that we
|
||
|
// allow the tab control to change the page correctly. otherwise lets
|
||
|
// just hack around the problem of the result view not handling tabs
|
||
|
// properly.
|
||
|
|
||
|
INT iCur = TabCtrl_GetCurSel(pQueryFrame->_hwndFrame);
|
||
|
INT nPages = TabCtrl_GetItemCount(pQueryFrame->_hwndFrame);
|
||
|
|
||
|
if (fShift)
|
||
|
iCur += (nPages-1);
|
||
|
else
|
||
|
iCur++;
|
||
|
|
||
|
pQueryFrame->SelectFormPage(pQueryFrame->_pCurrentForm, iCur % nPages);
|
||
|
|
||
|
return 1; // we processed it
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// is the window that has the focus a child of the result view, if
|
||
|
// so then we must attempt to pass focus to its 1st child and hope
|
||
|
// that is can do the rest.
|
||
|
|
||
|
HWND hwndNext, hwnd = GetFocus();
|
||
|
Trace(TEXT("Current focus window %08x"), hwnd);
|
||
|
|
||
|
while (hwnd && GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD)
|
||
|
{
|
||
|
hwndNext = _NextTabStop(hwnd, fShift);
|
||
|
Trace(TEXT("_NextTabStop yeilds %08x from %08x"), hwndNext, hwnd);
|
||
|
|
||
|
if (hwndNext)
|
||
|
{
|
||
|
Trace(TEXT("SetFocus on child %08x"), hwndNext);
|
||
|
SetFocus(hwndNext);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
// look up the parent list trying to find a window that we can
|
||
|
// tab back into. We must watch that when we walk out of the
|
||
|
// child list we loop correctly at the top of the list.
|
||
|
|
||
|
hwndNext = GetParent(hwnd);
|
||
|
Trace(TEXT("Parent hwnd %08x"), hwndNext);
|
||
|
|
||
|
if (GetWindowLong(hwndNext, GWL_STYLE) & WS_CHILD)
|
||
|
{
|
||
|
// the parent window is a child, therefore we can check
|
||
|
// to see if has any siblings.
|
||
|
|
||
|
Trace(TEXT("hwndNext is a child, therefore hwndNext of it is %08x"),
|
||
|
GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT));
|
||
|
|
||
|
if (GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT))
|
||
|
{
|
||
|
hwnd = GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT);
|
||
|
Trace(TEXT("Silbing window found %08x"), hwnd);
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceMsg("There was no sibling, therefore continuing parent loop");
|
||
|
hwnd = hwndNext;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// we have hit the parent window of it all (the overlapped one)
|
||
|
// therefore we must attempt to go to its first child. Walk forward
|
||
|
// in the stack looking for a window that matches the
|
||
|
// "REAL_WINDOW" conditions.
|
||
|
|
||
|
hwnd = GetWindow(hwnd, fShift ? GW_HWNDLAST:GW_HWNDFIRST);
|
||
|
Trace(TEXT("First child is %08x"), hwnd);
|
||
|
break; // continue the sibling search etc
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (REAL_WINDOW(hwnd))
|
||
|
{
|
||
|
SetFocus(hwnd);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Main DLGPROC
|
||
|
//
|
||
|
|
||
|
INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
CQueryFrame* pQueryFrame;
|
||
|
|
||
|
if (uMsg == WM_INITDIALOG)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
pQueryFrame = (CQueryFrame*)lParam;
|
||
|
SetWindowLongPtr(hwnd, DWLP_USER, (LRESULT)pQueryFrame);
|
||
|
|
||
|
hres = pQueryFrame->OnInitDialog(hwnd);
|
||
|
Trace(TEXT("OnInitDialog returns %08x"), hres);
|
||
|
|
||
|
if (FAILED(hres))
|
||
|
{
|
||
|
TraceMsg("Failed to initialize the dialog, Destroying the window");
|
||
|
pQueryFrame->CloseQueryFrame(hres);
|
||
|
DestroyWindow(hwnd);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pQueryFrame = (CQueryFrame*)GetWindowLongPtr(hwnd, DWLP_USER);
|
||
|
|
||
|
if (!pQueryFrame)
|
||
|
goto exit_gracefully;
|
||
|
|
||
|
switch (uMsg)
|
||
|
{
|
||
|
case WM_ERASEBKGND:
|
||
|
{
|
||
|
HDC hdc = (HDC)wParam;
|
||
|
RECT rc;
|
||
|
|
||
|
// if we have a DC then lets fill it, and if we have a
|
||
|
// query form then lets paint the divider between the menu bar and
|
||
|
// this area.
|
||
|
|
||
|
if (hdc)
|
||
|
{
|
||
|
GetClientRect(hwnd, &rc);
|
||
|
FillRect(hdc, &rc, (HBRUSH)(COLOR_3DFACE+1));
|
||
|
|
||
|
if (!(pQueryFrame->_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS))
|
||
|
DrawEdge(hdc, &rc, EDGE_ETCHED, BF_TOP);
|
||
|
|
||
|
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
case WM_NOTIFY:
|
||
|
return pQueryFrame->OnNotify((int)wParam, (LPNMHDR)lParam);
|
||
|
|
||
|
case WM_SIZE:
|
||
|
pQueryFrame->OnSize(LOWORD(lParam), HIWORD(lParam));
|
||
|
return(1);
|
||
|
|
||
|
case WM_GETMINMAXINFO:
|
||
|
pQueryFrame->OnGetMinMaxInfo((LPMINMAXINFO)lParam);
|
||
|
return(1);
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
pQueryFrame->OnCommand(wParam, lParam);
|
||
|
return(1);
|
||
|
|
||
|
case WM_ACTIVATE:
|
||
|
pQueryFrame->_pQueryHandler->ActivateView(wParam ? CQRVA_ACTIVATE : CQRVA_DEACTIVATE, 0, 0);
|
||
|
return(1);
|
||
|
|
||
|
case WM_INITMENU:
|
||
|
pQueryFrame->OnInitMenu((HMENU)wParam);
|
||
|
return(1);
|
||
|
|
||
|
case WM_SETCURSOR:
|
||
|
{
|
||
|
// do we have any scopes? if not then let us display the wait
|
||
|
// cursor for the user. if we have a query running then lets
|
||
|
// display the app start cursor.
|
||
|
|
||
|
if (!pQueryFrame->_fAddScopesNYI &&
|
||
|
!ComboBox_GetCount(pQueryFrame->_hwndLookIn))
|
||
|
{
|
||
|
if (LOWORD(lParam) == HTCLIENT)
|
||
|
{
|
||
|
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT)));
|
||
|
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case WM_INITMENUPOPUP:
|
||
|
{
|
||
|
// only send sub-menu activates if the menu bar is being tracked, this is
|
||
|
// handled within OnInitMenu, if we are not tracking the menu then we
|
||
|
// assume that the client has already primed the menu and that they are
|
||
|
// using some kind of popup menu.
|
||
|
|
||
|
if (pQueryFrame->_fTrackingMenuBar)
|
||
|
pQueryFrame->_pQueryHandler->ActivateView(CQRVA_INITMENUBARPOPUP, wParam, lParam);
|
||
|
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
case WM_ENTERMENULOOP:
|
||
|
pQueryFrame->OnEnterMenuLoop(TRUE);
|
||
|
return(1);
|
||
|
|
||
|
case WM_EXITMENULOOP:
|
||
|
pQueryFrame->OnEnterMenuLoop(FALSE);
|
||
|
return(1);
|
||
|
|
||
|
case WM_MENUSELECT:
|
||
|
{
|
||
|
UINT uID = LOWORD(wParam);
|
||
|
UINT uFlags = HIWORD(wParam);
|
||
|
HMENU hMenu = (HMENU)lParam;
|
||
|
|
||
|
// the command opens a popup menu the the uID is actually
|
||
|
// the index into the menu, so lets ensure that we pick
|
||
|
// up the correct ID by calling GetMenuItemInfo, note that
|
||
|
// GetMenuItemID returns -1 in this case which is totally
|
||
|
// useless.
|
||
|
|
||
|
if (uFlags & MF_POPUP)
|
||
|
{
|
||
|
MENUITEMINFO mii;
|
||
|
|
||
|
ZeroMemory(&mii, SIZEOF(mii));
|
||
|
mii.cbSize = SIZEOF(mii);
|
||
|
mii.fMask = MIIM_ID;
|
||
|
|
||
|
if (GetMenuItemInfo(hMenu, uID, TRUE, &mii))
|
||
|
uID = mii.wID;
|
||
|
}
|
||
|
|
||
|
pQueryFrame->OnMenuSelect(hMenu, uID);
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
case WM_SYSCOMMAND:
|
||
|
if (wParam == SC_CLOSE)
|
||
|
{
|
||
|
pQueryFrame->CloseQueryFrame(S_FALSE);
|
||
|
return(1);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_CONTEXTMENU:
|
||
|
{
|
||
|
// there are a couple of controls we don't care about for the
|
||
|
// frame, so lets ignore those when passing the CQRVA_CONTEXTMENU
|
||
|
// through to the handler.
|
||
|
|
||
|
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
|
||
|
ScreenToClient((HWND)wParam, &pt);
|
||
|
|
||
|
switch (GetDlgCtrlID(ChildWindowFromPoint((HWND)wParam, pt)))
|
||
|
{
|
||
|
case IDC_FORMAREA:
|
||
|
case IDC_FINDANIMATION:
|
||
|
case IDC_STATUS:
|
||
|
return TRUE; // handled
|
||
|
|
||
|
default:
|
||
|
pQueryFrame->_pQueryHandler->ActivateView(CQRVA_CONTEXTMENU, wParam, lParam);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
case WM_HELP:
|
||
|
{
|
||
|
LPHELPINFO phi = (LPHELPINFO)lParam;
|
||
|
|
||
|
// filter out those controls we are not interested in (they make no sense)
|
||
|
// to bother the user with
|
||
|
|
||
|
switch (GetDlgCtrlID((HWND)phi->hItemHandle))
|
||
|
{
|
||
|
case IDC_FORMAREA:
|
||
|
case IDC_FINDANIMATION:
|
||
|
case IDC_STATUS:
|
||
|
return TRUE;
|
||
|
|
||
|
default:
|
||
|
pQueryFrame->OnHelp(phi);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
case CQFWM_ADDSCOPE:
|
||
|
{
|
||
|
LPCQSCOPE pScope = (LPCQSCOPE)wParam;
|
||
|
BOOL fSelect = LOWORD(lParam);
|
||
|
INT iIndex = HIWORD(lParam);
|
||
|
|
||
|
if (SUCCEEDED(pQueryFrame->AddScope(pScope, iIndex, fSelect)))
|
||
|
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
case CQFWM_GETFRAME:
|
||
|
{
|
||
|
IQueryFrame** ppQueryFrame = (IQueryFrame**)lParam;
|
||
|
|
||
|
if (ppQueryFrame)
|
||
|
{
|
||
|
pQueryFrame->AddRef();
|
||
|
*ppQueryFrame = pQueryFrame;
|
||
|
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
case CQFWM_ALLSCOPESADDED:
|
||
|
{
|
||
|
// there is an async scope collector, it has added all the scopes
|
||
|
// so we must now attempt to issue the query if the we are in the
|
||
|
// holding pattern waiting for the scopes to be collected.
|
||
|
|
||
|
pQueryFrame->_fScopesAddedAsync = FALSE; // all scopes have been added
|
||
|
|
||
|
if (pQueryFrame->_pOpenQueryWnd->dwFlags & OQWF_ISSUEONOPEN)
|
||
|
PostMessage(pQueryFrame->_hwnd, CQFWM_STARTQUERY, 0, 0);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
case CQFWM_STARTQUERY:
|
||
|
pQueryFrame->OnFindNow();
|
||
|
return 1;
|
||
|
|
||
|
case CQFWM_SETDEFAULTFOCUS:
|
||
|
{
|
||
|
HWND hwndNextTab = _NextTabStop(pQueryFrame->_pCurrentFormPage->hwndPage, FALSE);
|
||
|
SendMessage(pQueryFrame->_pCurrentFormPage->hwndPage, WM_NEXTDLGCTL, (WPARAM)hwndNextTab, 1);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::CloseQueryFrame
|
||
|
/ ----------------------------
|
||
|
/ Close the query window passing back the data object if required, and ensuring
|
||
|
/ that our result code indicates what is going on.
|
||
|
/
|
||
|
/ In:
|
||
|
/ hResult = result code to pass to the caller
|
||
|
/
|
||
|
/ Out:
|
||
|
/ -
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
VOID CQueryFrame::CloseQueryFrame(HRESULT hres)
|
||
|
{
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::CloseQueryFrame");
|
||
|
Trace(TEXT("hResult %08x"), hres);
|
||
|
|
||
|
// If we succeeded then attempt to collect the IDataObject and pass it
|
||
|
// back to the caller.
|
||
|
|
||
|
if (hres == S_OK)
|
||
|
{
|
||
|
if (_ppDataObject)
|
||
|
{
|
||
|
hres = _pQueryHandler->GetViewObject(CQRVS_SELECTION, IID_IDataObject, (LPVOID*)_ppDataObject);
|
||
|
FailGracefully(hres, "Failed when collecting the data object");
|
||
|
}
|
||
|
|
||
|
if ((_pOpenQueryWnd->dwFlags & OQWF_SAVEQUERYONOK) && _pOpenQueryWnd->pPersistQuery)
|
||
|
{
|
||
|
hres = SaveQuery(_pOpenQueryWnd->pPersistQuery);
|
||
|
FailGracefully(hres, "Failed when persisting query to IPersistQuery blob");
|
||
|
}
|
||
|
|
||
|
hres = S_OK; // success
|
||
|
}
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
_hResult = hres;
|
||
|
_fExitModalLoop = TRUE; // bomb out of the modal loop
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::FrameMessageBox
|
||
|
/ ----------------------------
|
||
|
/ Our message box for putting up prompts that relate to the current
|
||
|
/ query. We handle getting the view information and displaying
|
||
|
/ the prompt, returning the result from MessageBox.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pPrompt = text displayed as a prompt
|
||
|
/ uType = message box type
|
||
|
/
|
||
|
/ Out:
|
||
|
/ INT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
INT CQueryFrame::FrameMessageBox(LPCTSTR pPrompt, UINT uType)
|
||
|
{
|
||
|
TCHAR szTitle[MAX_PATH];
|
||
|
CQVIEWINFO vi;
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::FrameMessageBox");
|
||
|
|
||
|
ZeroMemory(&vi, SIZEOF(vi));
|
||
|
//vi. dwFlags = 0; // display attributes
|
||
|
|
||
|
if (SUCCEEDED(_pQueryHandler->GetViewInfo(&vi)) && vi.hInstance && vi.idTitle)
|
||
|
LoadString(vi.hInstance, vi.idTitle, szTitle, ARRAYSIZE(szTitle));
|
||
|
else
|
||
|
GetWindowText(_hwnd, szTitle, ARRAYSIZE(szTitle));
|
||
|
|
||
|
TraceLeaveValue(MessageBox(_hwnd, pPrompt, szTitle, uType));
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnInitDlg
|
||
|
/ ----------------------
|
||
|
/ Handle a WM_INITDAILOG message, this is sent as the first thing the
|
||
|
/ dialog receives, therefore we must handle our initialization that
|
||
|
/ was not handled in the constructor.
|
||
|
/
|
||
|
/ In:
|
||
|
/ hwnd = handle of dialog we are initializing
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::OnInitDialog(HWND hwnd)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
HICON hIcon = NULL;
|
||
|
TCHAR szGUID[GUIDSTR_MAX+1];
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
CQVIEWINFO vi;
|
||
|
INT dyControls = 0;
|
||
|
RECT rect, rect2;
|
||
|
SIZE size;
|
||
|
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnInitDialog");
|
||
|
|
||
|
// get the HKEY for the handler we are using
|
||
|
|
||
|
hres = GetKeyForCLSID(_pOpenQueryWnd->clsidHandler, NULL, &_hkHandler);
|
||
|
FailGracefully(hres, "Failed to open handlers HKEY");
|
||
|
|
||
|
// pick up the control handles and store them, saves picking them up later
|
||
|
|
||
|
_hwnd = hwnd;
|
||
|
_hwndFrame = GetDlgItem(hwnd, IDC_FORMAREA);
|
||
|
_hwndLookForLabel = GetDlgItem(hwnd, CQID_LOOKFORLABEL);
|
||
|
_hwndLookFor = GetDlgItem(hwnd, CQID_LOOKFOR);
|
||
|
_hwndLookInLabel = GetDlgItem(hwnd, CQID_LOOKINLABEL);
|
||
|
_hwndLookIn = GetDlgItem(hwnd, CQID_LOOKIN);
|
||
|
_hwndBrowse = GetDlgItem(hwnd, CQID_BROWSE);
|
||
|
_hwndFindNow = GetDlgItem(hwnd, CQID_FINDNOW);
|
||
|
_hwndStop = GetDlgItem(hwnd, CQID_STOP);
|
||
|
_hwndNewQuery = GetDlgItem(hwnd, CQID_CLEARALL);
|
||
|
_hwndFindAnimation = GetDlgItem(hwnd, IDC_FINDANIMATION);
|
||
|
_hwndOK = GetDlgItem(hwnd, IDOK);
|
||
|
_hwndCancel = GetDlgItem(hwnd, IDCANCEL);
|
||
|
|
||
|
// when enable is called this will be the first
|
||
|
_fFormFirstEnable = TRUE;
|
||
|
|
||
|
// call the IQueryHandler interface and get its display attributes,
|
||
|
// then reflect these into the dialog we are about to display to the
|
||
|
// outside world.
|
||
|
|
||
|
vi.dwFlags = 0;
|
||
|
vi.hInstance = NULL;
|
||
|
vi.idLargeIcon = 0;
|
||
|
vi.idSmallIcon = 0;
|
||
|
vi.idTitle = 0;
|
||
|
vi.idAnimation = 0;
|
||
|
|
||
|
hres = _pQueryHandler->GetViewInfo(&vi);
|
||
|
FailGracefully(hres, "Failed when getting the view info from the handler");
|
||
|
|
||
|
_dwHandlerViewFlags = vi.dwFlags;
|
||
|
|
||
|
if (vi.hInstance)
|
||
|
{
|
||
|
HICON hiTemp = NULL;
|
||
|
|
||
|
if (vi.idLargeIcon)
|
||
|
{
|
||
|
_hiconLarge = (HICON)LoadImage(vi.hInstance,
|
||
|
MAKEINTRESOURCE(vi.idLargeIcon),
|
||
|
IMAGE_ICON,
|
||
|
0, 0,
|
||
|
LR_DEFAULTCOLOR|LR_DEFAULTSIZE);
|
||
|
if (_hiconLarge)
|
||
|
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)_hiconLarge);
|
||
|
}
|
||
|
|
||
|
if (vi.idSmallIcon)
|
||
|
{
|
||
|
_hiconSmall = (HICON)LoadImage(vi.hInstance,
|
||
|
MAKEINTRESOURCE(vi.idLargeIcon),
|
||
|
IMAGE_ICON,
|
||
|
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
|
||
|
LR_DEFAULTCOLOR);
|
||
|
if (_hiconSmall)
|
||
|
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)_hiconSmall);
|
||
|
}
|
||
|
|
||
|
if (vi.idTitle)
|
||
|
{
|
||
|
LoadString(vi.hInstance, vi.idTitle, szBuffer, ARRAYSIZE(szBuffer));
|
||
|
SetWindowText(hwnd, szBuffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (vi.hInstance && vi.idAnimation)
|
||
|
{
|
||
|
SetWindowLongPtr(_hwndFindAnimation, GWLP_HINSTANCE, (LRESULT)vi.hInstance);
|
||
|
Animate_Open(_hwndFindAnimation, MAKEINTRESOURCE(vi.idAnimation));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Animate_Open(_hwndFindAnimation, MAKEINTRESOURCE(IDR_FINDANIMATION));
|
||
|
}
|
||
|
|
||
|
// now adjust the positions and hide the controls we are not interested in
|
||
|
|
||
|
if (_pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS)
|
||
|
{
|
||
|
ShowWindow(_hwndLookForLabel, SW_HIDE);
|
||
|
ShowWindow(_hwndLookFor, SW_HIDE);
|
||
|
}
|
||
|
|
||
|
if (_pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES)
|
||
|
{
|
||
|
ShowWindow(_hwndLookInLabel, SW_HIDE);
|
||
|
ShowWindow(_hwndLookIn, SW_HIDE);
|
||
|
ShowWindow(_hwndBrowse, SW_HIDE);
|
||
|
}
|
||
|
|
||
|
// hiding both the scopes and the forms control causes us to
|
||
|
// move all the controls up by so many units.
|
||
|
|
||
|
if ((_pOpenQueryWnd->dwFlags & (OQWF_REMOVEFORMS|OQWF_REMOVESCOPES))
|
||
|
== (OQWF_REMOVEFORMS|OQWF_REMOVESCOPES))
|
||
|
{
|
||
|
GetRealWindowInfo(_hwndLookForLabel, &rect, NULL);
|
||
|
GetRealWindowInfo(_hwndFrame, &rect2, NULL);
|
||
|
|
||
|
dyControls += rect2.top - rect.top;
|
||
|
Trace(TEXT("Moving all controls up by %d units"), dyControls);
|
||
|
|
||
|
OffsetWindow(_hwndFrame, 0, -dyControls);
|
||
|
OffsetWindow(_hwndFindNow, 0, -dyControls);
|
||
|
OffsetWindow(_hwndStop, 0, -dyControls);
|
||
|
OffsetWindow(_hwndNewQuery, 0, -dyControls);
|
||
|
OffsetWindow(_hwndFindAnimation, 0, -dyControls);
|
||
|
OffsetWindow(_hwndOK, 0, -dyControls);
|
||
|
|
||
|
if (_hwndCancel)
|
||
|
OffsetWindow(_hwndCancel, 0, -dyControls);
|
||
|
}
|
||
|
|
||
|
// hiding OK/Cancel so lets adjust the size here to include the
|
||
|
// OK/Cancel buttons disappearing, note that we update dyControls
|
||
|
// to include this delta
|
||
|
|
||
|
if (!(_pOpenQueryWnd->dwFlags & OQWF_OKCANCEL))
|
||
|
{
|
||
|
ShowWindow(_hwndOK, SW_HIDE);
|
||
|
|
||
|
if (_hwndCancel)
|
||
|
ShowWindow(_hwndCancel, SW_HIDE);
|
||
|
|
||
|
// if this is the filter dialog then lets ensure that
|
||
|
// we trim the OK/Cancel buttons from the size by adjusting the
|
||
|
// dyControls further.
|
||
|
|
||
|
GetRealWindowInfo(_hwndOK, &rect, NULL);
|
||
|
GetRealWindowInfo(_hwndFrame, &rect2, NULL);
|
||
|
dyControls += rect.bottom - rect2.bottom;
|
||
|
}
|
||
|
|
||
|
// having performed that extra bit of initialization lets cache the
|
||
|
// positions of the various controls, to make sizing more fun...
|
||
|
|
||
|
GetClientRect(hwnd, &rect2);
|
||
|
rect2.bottom -= dyControls;
|
||
|
|
||
|
_dyResultsTop = rect2.bottom;
|
||
|
|
||
|
GetRealWindowInfo(hwnd, NULL, &size);
|
||
|
GetRealWindowInfo(_hwndFrame, &rect, &_szForm);
|
||
|
|
||
|
Trace(TEXT("dyControls %d"), dyControls);
|
||
|
size.cy -= dyControls;
|
||
|
|
||
|
_dxFormAreaLeft = rect.left;
|
||
|
_dxFormAreaRight = rect2.right - rect.right;
|
||
|
|
||
|
_szMinTrack.cx = size.cx - _szForm.cx;
|
||
|
_szMinTrack.cy = size.cy - _szForm.cy;
|
||
|
|
||
|
if (!(_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS))
|
||
|
{
|
||
|
TraceMsg("Adjusting _szMinTrack.cy to account for menu bar");
|
||
|
_szMinTrack.cy += GetSystemMetrics(SM_CYMENU);
|
||
|
}
|
||
|
|
||
|
GetRealWindowInfo(_hwndBrowse, &rect, NULL);
|
||
|
_dxButtonsLeft = rect2.right - rect.left;
|
||
|
|
||
|
GetRealWindowInfo(_hwndLookIn, &rect, NULL);
|
||
|
_dxGap = (rect2.right - rect.right) - _dxButtonsLeft;
|
||
|
|
||
|
GetRealWindowInfo(_hwndFindAnimation, &rect, NULL);
|
||
|
_dxAnimationLeft = rect2.right - rect.left;
|
||
|
|
||
|
GetRealWindowInfo(_hwndOK, &rect, NULL);
|
||
|
_dyOKTop = rect2.bottom - rect.top;
|
||
|
_dyGap = size.cy - rect.bottom;
|
||
|
|
||
|
// Now collect the forms and pages, then walk them building the size
|
||
|
// information that we need.
|
||
|
|
||
|
hres = GatherForms();
|
||
|
FailGracefully(hres, "Failed to init form list");
|
||
|
|
||
|
_szMinTrack.cx += _szForm.cx;
|
||
|
_szMinTrack.cy += _szForm.cy;
|
||
|
|
||
|
// Populate the scope control by querying the handler for them,
|
||
|
// if there are none then we display a suitable message box and
|
||
|
// let the user know that something went wrong.
|
||
|
|
||
|
hres = PopulateScopeControl();
|
||
|
FailGracefully(hres, "Failed to init scope list");
|
||
|
|
||
|
_fScopesPopulated = TRUE; // scope control now populated
|
||
|
|
||
|
// perform final fix up of the window, ensure that we size it so that
|
||
|
// the entire form and buttons are visible. Then set ourselves into the
|
||
|
// no query state and reset the animation.
|
||
|
|
||
|
SetWindowPos(hwnd,
|
||
|
NULL,
|
||
|
0, 0,
|
||
|
_szMinTrack.cx, _szMinTrack.cy,
|
||
|
SWP_NOMOVE|SWP_NOZORDER);
|
||
|
|
||
|
|
||
|
if (_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS)
|
||
|
::SetMenu(hwnd, NULL);
|
||
|
|
||
|
hres = PopulateFormControl(_pOpenQueryWnd->dwFlags & OQWF_SHOWOPTIONAL);
|
||
|
FailGracefully(hres, "Failed to populate form control");
|
||
|
|
||
|
// Now load the query which inturn selects the form that we should be using,
|
||
|
// if there is no query to load then either use the default form or
|
||
|
// the first in the list.
|
||
|
|
||
|
if ((_pOpenQueryWnd->dwFlags & OQWF_LOADQUERY) && _pOpenQueryWnd->pPersistQuery)
|
||
|
{
|
||
|
hres = LoadQuery(_pOpenQueryWnd->pPersistQuery);
|
||
|
FailGracefully(hres, "Failed when to load query from supplied IPersistQuery");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (_pOpenQueryWnd->dwFlags & OQWF_DEFAULTFORM)
|
||
|
{
|
||
|
SelectForm(_pOpenQueryWnd->clsidDefaultForm);
|
||
|
|
||
|
if (!_pCurrentForm)
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to select the query form");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
INT iForm = (int)ComboBox_GetItemData(_hwndLookFor, 0);
|
||
|
LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
|
||
|
TraceAssert(pQueryForm);
|
||
|
|
||
|
SelectForm(pQueryForm->clsidForm);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
StartQuery(FALSE);
|
||
|
|
||
|
// issue on open, therefore lets get the query going, if there is async
|
||
|
// scope collection then the query will be issued by the bg thread.
|
||
|
|
||
|
if (_pOpenQueryWnd->dwFlags & OQWF_ISSUEONOPEN)
|
||
|
PostMessage(_hwnd, CQFWM_STARTQUERY, 0, 0);
|
||
|
|
||
|
SetForegroundWindow(hwnd);
|
||
|
|
||
|
hres = S_OK; // success
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::EnableControls
|
||
|
/ ---------------------------
|
||
|
/ Set the controls into their enabled/disabled state based on the
|
||
|
/ state of the dialog.
|
||
|
/
|
||
|
/ In:
|
||
|
/ -
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
VOID CQueryFrame::DoEnableControls(VOID)
|
||
|
{
|
||
|
BOOL fScopes = (_fAddScopesNYI || ComboBox_GetCount(_hwndLookIn));
|
||
|
BOOL fEnable = fScopes;
|
||
|
UINT uEnable = fScopes ? MF_ENABLED:MF_GRAYED;
|
||
|
HMENU hMenu = GetMenu(_hwnd);
|
||
|
INT i;
|
||
|
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::DoEnableControls");
|
||
|
|
||
|
EnableWindow(_hwndFindNow, !_fQueryRunning && fEnable);
|
||
|
EnableWindow(_hwndStop, _fQueryRunning && fEnable);
|
||
|
EnableWindow(_hwndNewQuery, fEnable);
|
||
|
|
||
|
EnableWindow(_hwndLookFor, !_fQueryRunning && fEnable);
|
||
|
EnableWindow(_hwndLookIn, !_fQueryRunning && fEnable);
|
||
|
EnableWindow(_hwndBrowse, !_fQueryRunning && fEnable);
|
||
|
|
||
|
if (_pCurrentForm)
|
||
|
{
|
||
|
CallFormPages(_pCurrentForm, CQPM_ENABLE, (BOOL)(!_fQueryRunning && fEnable), 0);
|
||
|
|
||
|
if (_fFormFirstEnable)
|
||
|
{
|
||
|
PostMessage(_hwnd, CQFWM_SETDEFAULTFOCUS, 0, 0);
|
||
|
_fFormFirstEnable = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (_hwndOK)
|
||
|
EnableWindow(_hwndOK, !_fQueryRunning && fEnable);
|
||
|
if (_hwndCancel)
|
||
|
EnableWindow(_hwndCancel, !_fQueryRunning && fEnable);
|
||
|
|
||
|
for (i = 0 ; i < GetMenuItemCount(hMenu) ; i++)
|
||
|
EnableMenuItem(hMenu, i, MF_BYPOSITION|uEnable);
|
||
|
|
||
|
DrawMenuBar(_hwnd);
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnNotify
|
||
|
/ ---------------------
|
||
|
/ Notify event received, decode it and handle accordingly
|
||
|
/
|
||
|
/ In:
|
||
|
/ idCtrl = ID of control issuing notify
|
||
|
/ pNotify -> LPNMHDR structure
|
||
|
/
|
||
|
/ Out:
|
||
|
/ LRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
LRESULT CQueryFrame::OnNotify(INT idCtrl, LPNMHDR pNotify)
|
||
|
{
|
||
|
LRESULT lr = 0;
|
||
|
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnNotify");
|
||
|
|
||
|
// TCN_SELCHANGE used to indicate that the currently active
|
||
|
// tab has been changed
|
||
|
|
||
|
if (pNotify->code == TCN_SELCHANGE)
|
||
|
{
|
||
|
INT iPage = TabCtrl_GetCurSel(_hwndFrame);
|
||
|
TraceAssert(iPage >= 0);
|
||
|
|
||
|
if (iPage >= 0)
|
||
|
{
|
||
|
SelectFormPage(_pCurrentForm, iPage);
|
||
|
lr = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TraceLeaveResult((HRESULT)lr);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnSize
|
||
|
/ -------------------
|
||
|
/ The window is being sized and we received a WM_SIZE, therefore move
|
||
|
/ the content of the window about.
|
||
|
/
|
||
|
/ In:
|
||
|
/ cx = new width
|
||
|
/ cy = new height
|
||
|
/
|
||
|
/ Out:
|
||
|
/ -
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
VOID CQueryFrame::OnSize(INT cx, INT cy)
|
||
|
{
|
||
|
HDWP hdwp;
|
||
|
RECT rect, rect2;
|
||
|
SIZE sz, sz2;
|
||
|
INT x, cxForm, cyForm;
|
||
|
INT dyResultsTop = 0;
|
||
|
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnSize");
|
||
|
|
||
|
// do as much as we can within a DefWindowPos to aVOID too
|
||
|
// much flicker.
|
||
|
|
||
|
hdwp = BeginDeferWindowPos(16);
|
||
|
|
||
|
if (hdwp)
|
||
|
{
|
||
|
{
|
||
|
// adjust the look for controls, if there is no scope then
|
||
|
// stretch the look for control over the entire client area
|
||
|
// of the window.
|
||
|
|
||
|
if (!(_pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS))
|
||
|
{
|
||
|
if (_pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES)
|
||
|
{
|
||
|
GetRealWindowInfo(_hwndLookFor, &rect, &sz);
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndLookFor, NULL,
|
||
|
0, 0,
|
||
|
(cx - _dxFormAreaRight) - rect.left, sz.cy,
|
||
|
SWP_NOZORDER|SWP_NOMOVE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// adjust the "look in" controls, if there is a form control
|
||
|
// then stretch across the remaining space, otherwise move the
|
||
|
// label and stretch the scope over the remaining space.
|
||
|
|
||
|
if (!(_pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES))
|
||
|
{
|
||
|
INT xScopeRight;
|
||
|
|
||
|
GetRealWindowInfo(_hwndLookIn, &rect, &sz);
|
||
|
xScopeRight = cx - _dxFormAreaRight - _dxGap;
|
||
|
|
||
|
if (_pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHUI)
|
||
|
{
|
||
|
//
|
||
|
// when hiding the search UI, then adjust the button position to account for the
|
||
|
// right edge of the dialog not having buttons.
|
||
|
//
|
||
|
|
||
|
xScopeRight -= (_dxButtonsLeft - _dxFormAreaRight) + _dxGap;
|
||
|
}
|
||
|
|
||
|
if (_pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS)
|
||
|
{
|
||
|
GetRealWindowInfo(_hwndLookInLabel, &rect2, &sz2);
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndLookInLabel, NULL,
|
||
|
_dxFormAreaLeft, rect2.top,
|
||
|
0, 0,
|
||
|
SWP_NOSIZE|SWP_NOZORDER);
|
||
|
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndLookIn, NULL,
|
||
|
_dxFormAreaLeft+sz2.cx, rect.top,
|
||
|
xScopeRight - (_dxFormAreaLeft + sz2.cx), sz.cy,
|
||
|
SWP_NOZORDER);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndLookIn, NULL,
|
||
|
0, 0,
|
||
|
xScopeRight - rect.left, sz.cy,
|
||
|
SWP_NOZORDER|SWP_NOMOVE);
|
||
|
}
|
||
|
|
||
|
// browse control is displayed always if we are showing the
|
||
|
// scopes.
|
||
|
|
||
|
GetRealWindowInfo(_hwndBrowse, &rect, NULL);
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndBrowse, NULL,
|
||
|
xScopeRight+_dxGap, rect.top,
|
||
|
0, 0,
|
||
|
SWP_NOZORDER|SWP_NOSIZE);
|
||
|
}
|
||
|
|
||
|
// all the buttons have a fixed offset from the right edege
|
||
|
// of the dialog, so just handle that as we can.
|
||
|
|
||
|
if (!(_pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHUI))
|
||
|
{
|
||
|
GetRealWindowInfo(_hwndFindNow, &rect, NULL);
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndFindNow, NULL,
|
||
|
(cx - _dxButtonsLeft), rect.top,
|
||
|
0, 0,
|
||
|
SWP_NOZORDER|SWP_NOSIZE);
|
||
|
|
||
|
GetRealWindowInfo(_hwndStop, &rect, &sz);
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndStop, NULL,
|
||
|
(cx - _dxButtonsLeft), rect.top,
|
||
|
0, 0,
|
||
|
SWP_NOZORDER|SWP_NOSIZE);
|
||
|
|
||
|
GetRealWindowInfo(_hwndNewQuery, &rect, NULL);
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndNewQuery, NULL,
|
||
|
(cx - _dxButtonsLeft), rect.top,
|
||
|
0, 0,
|
||
|
SWP_NOZORDER|SWP_NOSIZE);
|
||
|
|
||
|
GetRealWindowInfo(_hwndFindAnimation, &rect2, &sz2);
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndFindAnimation, NULL,
|
||
|
(cx - _dxAnimationLeft), rect2.top,
|
||
|
0, 0,
|
||
|
SWP_NOZORDER|SWP_NOSIZE);
|
||
|
}
|
||
|
|
||
|
// position the form "frame" control
|
||
|
|
||
|
GetRealWindowInfo(_hwndFrame, &rect, &sz);
|
||
|
cxForm = (cx - _dxFormAreaRight) - rect.left;
|
||
|
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndFrame, NULL,
|
||
|
0, 0,
|
||
|
cxForm, _szForm.cy,
|
||
|
SWP_NOZORDER|SWP_NOMOVE);
|
||
|
|
||
|
dyResultsTop = _dyResultsTop;
|
||
|
|
||
|
// when we have a cancel button then ensure that it is to the right
|
||
|
// of the OK button.
|
||
|
|
||
|
if (_hwndCancel)
|
||
|
{
|
||
|
GetRealWindowInfo(_hwndCancel, &rect, &sz);
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndCancel, NULL,
|
||
|
(cx - _dxButtonsLeft), dyResultsTop - _dyOKTop,
|
||
|
0, 0,
|
||
|
SWP_NOZORDER|SWP_NOSIZE);
|
||
|
|
||
|
GetRealWindowInfo(_hwndOK, &rect, &sz);
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndOK, NULL,
|
||
|
(cx - _dxButtonsLeft - _dxGap - sz.cx), dyResultsTop - _dyOKTop,
|
||
|
0, 0,
|
||
|
SWP_NOZORDER|SWP_NOSIZE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GetRealWindowInfo(_hwndOK, &rect, &sz);
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndOK, NULL,
|
||
|
(cx - _dxButtonsLeft), dyResultsTop - _dyOKTop,
|
||
|
0, 0,
|
||
|
SWP_NOZORDER|SWP_NOSIZE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// move the results and status bar as required
|
||
|
|
||
|
if (_hwndResults)
|
||
|
{
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndStatus, NULL,
|
||
|
0, cy - _cyStatus,
|
||
|
cx, _cyStatus,
|
||
|
SWP_SHOWWINDOW|SWP_NOZORDER);
|
||
|
|
||
|
hdwp = DeferWindowPos(hdwp, _hwndResults, NULL,
|
||
|
0, dyResultsTop,
|
||
|
cx, max(0, cy - (dyResultsTop + _cyStatus)),
|
||
|
SWP_SHOWWINDOW|SWP_NOZORDER);
|
||
|
}
|
||
|
|
||
|
EndDeferWindowPos(hdwp);
|
||
|
|
||
|
// here is the strange bit, by this point we have moved & sized all the
|
||
|
// controls on the dialog except the current page, as this is a child window
|
||
|
// and not a control which in turn has controls doing this would break
|
||
|
// the DefWindowPos path, therefore having updated everybody, lets update
|
||
|
// the page.
|
||
|
|
||
|
if (_pCurrentFormPage && _pCurrentFormPage->hwndPage)
|
||
|
{
|
||
|
GetRealWindowInfo(_hwndFrame, &rect, NULL);
|
||
|
TabCtrl_AdjustRect(_hwndFrame, FALSE, &rect);
|
||
|
|
||
|
cxForm = rect.right - rect.left;
|
||
|
cyForm = rect.bottom - rect.top;
|
||
|
|
||
|
SetWindowPos(_pCurrentFormPage->hwndPage, NULL,
|
||
|
rect.left, rect.top, cxForm, cyForm,
|
||
|
SWP_NOZORDER);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnGetMinMaxInfo
|
||
|
/ ----------------------------
|
||
|
/ The window is being sized and we received a WM_SIZE, therefore move
|
||
|
/ the content of the window about.
|
||
|
/
|
||
|
/ In:
|
||
|
/ lpmmin -> MINMAXINFO structure
|
||
|
/
|
||
|
/ Out:
|
||
|
/ -
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
VOID CQueryFrame::OnGetMinMaxInfo(LPMINMAXINFO lpmmi)
|
||
|
{
|
||
|
RECT rect = {0, 0, 0, 0};
|
||
|
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnGetMinMaxInfo");
|
||
|
|
||
|
#if 0
|
||
|
if (!_fHideSearchPane)
|
||
|
#endif
|
||
|
{
|
||
|
lpmmi->ptMinTrackSize.x = _szMinTrack.cx;
|
||
|
lpmmi->ptMinTrackSize.y = _szMinTrack.cy;
|
||
|
|
||
|
if (!_hwndResults)
|
||
|
{
|
||
|
lpmmi->ptMaxSize.y = lpmmi->ptMinTrackSize.y;
|
||
|
lpmmi->ptMaxTrackSize.y = lpmmi->ptMinTrackSize.y;
|
||
|
}
|
||
|
}
|
||
|
#if 0
|
||
|
else
|
||
|
{
|
||
|
AdjustWindowRect(&rect, GetWindowLong(_hwnd, GWL_STYLE), (NULL != GetMenu(_hwnd)));
|
||
|
lpmmi->ptMinTrackSize.y = rect.bottom - rect.top;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (_hwndResults && _hwndStatus)
|
||
|
lpmmi->ptMinTrackSize.y += _cyStatus;
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnCommand
|
||
|
/ ----------------------
|
||
|
/ We have recieved a WM_COMMAND so process it accordingly.
|
||
|
/
|
||
|
/ In:
|
||
|
/ wParam, lParam = parameters from the message
|
||
|
/
|
||
|
/ Out:
|
||
|
/ -
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
VOID CQueryFrame::OnCommand(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
UINT uID = LOWORD(wParam);
|
||
|
UINT uNotify = HIWORD(wParam);
|
||
|
HWND hwndControl = (HWND)lParam;
|
||
|
INT i;
|
||
|
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnCommand");
|
||
|
Trace(TEXT("uID %08x, uNotify %d, hwndControl %08x"), uID, uNotify, hwndControl);
|
||
|
|
||
|
switch (uID)
|
||
|
{
|
||
|
case IDOK:
|
||
|
TraceMsg("IDOK received");
|
||
|
CloseQueryFrame(S_OK);
|
||
|
break;
|
||
|
|
||
|
case IDCANCEL:
|
||
|
TraceMsg("IDCANCEL received");
|
||
|
CloseQueryFrame(S_FALSE);
|
||
|
break;
|
||
|
|
||
|
case CQID_LOOKFOR:
|
||
|
{
|
||
|
if (uNotify == CBN_SELCHANGE)
|
||
|
{
|
||
|
INT iSel = ComboBox_GetCurSel(_hwndLookFor);
|
||
|
INT iForm = (int)ComboBox_GetItemData(_hwndLookFor, iSel);
|
||
|
LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
|
||
|
TraceAssert(pQueryForm);
|
||
|
|
||
|
if (S_FALSE == SelectForm(pQueryForm->clsidForm))
|
||
|
{
|
||
|
TraceMsg("SelectForm return S_FALSE, so the user doesn't want the new form");
|
||
|
PostMessage(_hwndLookFor, CB_SETCURSEL, (WPARAM)_pCurrentForm->iForm, 0);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case CQID_BROWSE:
|
||
|
OnBrowse();
|
||
|
break;
|
||
|
|
||
|
case CQID_FINDNOW:
|
||
|
OnFindNow();
|
||
|
break;
|
||
|
|
||
|
case CQID_STOP:
|
||
|
{
|
||
|
LONG style;
|
||
|
|
||
|
_pQueryHandler->StopQuery();
|
||
|
// For some reason, the standard method of getting the old
|
||
|
// def button used in SetDefButton() below isn't working,
|
||
|
// so we have to forcibly remove the BS_DEFPUSHBUTTON style
|
||
|
// from the CQID_STOP button.
|
||
|
style = GetWindowLong(_hwndStop, GWL_STYLE) & ~BS_DEFPUSHBUTTON;
|
||
|
SendMessage(_hwndStop,
|
||
|
BM_SETSTYLE,
|
||
|
MAKEWPARAM(style, 0),
|
||
|
MAKELPARAM(TRUE, 0));
|
||
|
SetDefButton(_hwnd, CQID_FINDNOW);
|
||
|
SetFocus(_hwndFindNow);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case CQID_CLEARALL:
|
||
|
OnNewQuery(TRUE); // discard the current query
|
||
|
break;
|
||
|
|
||
|
case CQID_FILE_CLOSE:
|
||
|
TraceMsg("CQID_FILE_CLOSE received");
|
||
|
CloseQueryFrame(S_FALSE);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
_pQueryHandler->InvokeCommand(_hwnd, uID);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnInitMenu
|
||
|
/ -----------------------
|
||
|
/ Handle telling the handler that the menu is being initialised, however
|
||
|
/ this should only happen if the menu being activated is the
|
||
|
/ menu bar, otherwise we assume that the caller is tracking a popup
|
||
|
/ menu and has performed the required initalization.
|
||
|
/
|
||
|
/ In:
|
||
|
/ wParam, lParam = parameters from the WM_INITMENU
|
||
|
/
|
||
|
/ Out:
|
||
|
/ -
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
VOID CQueryFrame::OnInitMenu(HMENU hMenu)
|
||
|
{
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnInitMenu");
|
||
|
|
||
|
_fTrackingMenuBar = (GetMenu(_hwnd) == hMenu);
|
||
|
|
||
|
if (_fTrackingMenuBar)
|
||
|
{
|
||
|
TraceMsg("Tracking the menu bar, sending activate");
|
||
|
|
||
|
_pQueryHandler->ActivateView(CQRVA_INITMENUBAR, (WPARAM)hMenu, 0L);
|
||
|
|
||
|
EnableMenuItem(hMenu, CQID_VIEW_SEARCHPANE,
|
||
|
MF_BYCOMMAND|(_hwndResults != NULL) ? MF_ENABLED:MF_GRAYED);
|
||
|
}
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnEnterMenuLoop
|
||
|
/ ----------------------------
|
||
|
/ When the user displays a menu we must reflect this into the status bar
|
||
|
/ so that we can give the user help text relating to the commands they
|
||
|
/ select.
|
||
|
/
|
||
|
/ In:
|
||
|
/ fEntering = entering the menu loop, or leaving.
|
||
|
/
|
||
|
/ Out:
|
||
|
/ -
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
VOID CQueryFrame::OnEnterMenuLoop(BOOL fEntering)
|
||
|
{
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnEnterMenuLoop");
|
||
|
|
||
|
if (_hwndStatus)
|
||
|
{
|
||
|
if (fEntering)
|
||
|
{
|
||
|
SendMessage(_hwndStatus, SB_SIMPLE, (WPARAM)TRUE, 0L);
|
||
|
SendMessage(_hwndStatus, SB_SETTEXT, (WPARAM)SBT_NOBORDERS|255, 0L);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SendMessage(_hwndStatus, SB_SIMPLE, (WPARAM)FALSE, 0L);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnMenuSelect
|
||
|
/ -------------------------
|
||
|
/ Get the status text for this menu item and display it to the user,
|
||
|
/ if this doesn't map to any particular command then NULL out
|
||
|
/ the string. At this point we also trap our commands.
|
||
|
/
|
||
|
/ In:
|
||
|
/ hMenu = menu the user is on
|
||
|
/ uID = command ID for that item
|
||
|
/
|
||
|
/ Out:
|
||
|
/ -
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
VOID CQueryFrame::OnMenuSelect(HMENU hMenu, UINT uID)
|
||
|
{
|
||
|
TCHAR szBuffer[MAX_PATH] = { TEXT('\0') };
|
||
|
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnMenuSelect");
|
||
|
Trace(TEXT("hMenu %08x, uID %08x"), hMenu, uID);
|
||
|
|
||
|
if (_hwndStatus)
|
||
|
{
|
||
|
switch (uID)
|
||
|
{
|
||
|
case CQID_FILE_CLOSE:
|
||
|
case CQID_VIEW_SEARCHPANE:
|
||
|
LoadString(GLOBAL_HINSTANCE, uID, szBuffer, ARRAYSIZE(szBuffer));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
_pQueryHandler->GetCommandString(uID, 0x0, szBuffer, ARRAYSIZE(szBuffer));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Trace(TEXT("Setting status bar to: %s"), szBuffer);
|
||
|
SendMessage(_hwndStatus, SB_SETTEXT, (WPARAM)SBT_NOBORDERS|255, (LPARAM)szBuffer);
|
||
|
}
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnFindNow
|
||
|
/ ----------------------
|
||
|
// Issue the query, resulting in a view window being created and then issuing
|
||
|
// the parameter block to the query client.
|
||
|
/
|
||
|
/ In:
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::OnFindNow(VOID)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
CQPARAMS qp = { 0 };
|
||
|
LPQUERYSCOPE pQueryScope = NULL;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
BOOL fFixSize = TRUE;
|
||
|
RECT rc;
|
||
|
DECLAREWAITCURSOR;
|
||
|
BOOL fSetCursor = FALSE;
|
||
|
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnFindNow");
|
||
|
TraceAssert(_pCurrentForm != NULL);
|
||
|
|
||
|
if (_fQueryRunning)
|
||
|
ExitGracefully(hres, E_FAIL, "Quyery is already running");
|
||
|
|
||
|
SetWaitCursor();
|
||
|
|
||
|
fSetCursor = TRUE;
|
||
|
|
||
|
// If we have not created the viewer before now lets do so, also at the
|
||
|
// same time we attempt to fix the window size to ensure that enough
|
||
|
// of the view is visible.
|
||
|
|
||
|
if (!_hwndResults)
|
||
|
{
|
||
|
if (!_hwndStatus)
|
||
|
{
|
||
|
_hwndStatus = CreateStatusWindow(WS_CHILD, NULL, _hwnd, IDC_STATUS);
|
||
|
GetClientRect(_hwndStatus, &rc);
|
||
|
_cyStatus = rc.bottom - rc.top;
|
||
|
}
|
||
|
|
||
|
// Now construct the result viewer for us to use
|
||
|
|
||
|
hres = _pQueryHandler->CreateResultView(_hwnd, &_hwndResults);
|
||
|
FailGracefully(hres, "Failed when creating the view object");
|
||
|
|
||
|
GetWindowRect(_hwnd, &rc);
|
||
|
SetWindowPos(_hwnd, NULL,
|
||
|
0, 0,
|
||
|
rc.right - rc.left,
|
||
|
_szMinTrack.cy + VIEWER_DEFAULT_CY,
|
||
|
SWP_NOZORDER|SWP_NOMOVE);
|
||
|
}
|
||
|
|
||
|
// are we still collecting the scopes async? If so then lets wait until
|
||
|
// they have all arrived before we set the UI running.
|
||
|
|
||
|
if (_hdsaScopes && DSA_GetItemCount(_hdsaScopes))
|
||
|
{
|
||
|
// Collect the parameters ready for starting the query, if this fails then
|
||
|
// there is no point us continuing.
|
||
|
|
||
|
ZeroMemory(&qp, SIZEOF(qp));
|
||
|
qp.cbStruct = SIZEOF(qp);
|
||
|
//qp.dwFlags = 0x0;
|
||
|
qp.clsidForm = _pCurrentForm->clsidForm; // new NT5 beta 2
|
||
|
|
||
|
hres = GetSelectedScope(&pQueryScope);
|
||
|
FailGracefully(hres, "Failed to get the scope from the LookIn control");
|
||
|
|
||
|
if (pQueryScope)
|
||
|
{
|
||
|
Trace(TEXT("pQueryScope %08x"), pQueryScope);
|
||
|
qp.pQueryScope = pQueryScope->pScope;
|
||
|
}
|
||
|
|
||
|
hres = CallFormPages(_pCurrentForm, CQPM_GETPARAMETERS, 0, (LPARAM)&qp.pQueryParameters);
|
||
|
FailGracefully(hres, "Failed when collecting parameters from form");
|
||
|
|
||
|
if (!qp.pQueryParameters)
|
||
|
{
|
||
|
LoadString(GLOBAL_HINSTANCE, IDS_ERR_NOPARAMS, szBuffer, ARRAYSIZE(szBuffer));
|
||
|
FrameMessageBox(szBuffer, MB_ICONERROR|MB_OK);
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to issue the query, no parameters");
|
||
|
}
|
||
|
|
||
|
// We either already had a view, or have just created one. Either way
|
||
|
// we must now prepare the query for sending.
|
||
|
|
||
|
Trace(TEXT("qp.cbStruct %08x"), qp.cbStruct);
|
||
|
Trace(TEXT("qp.dwFlags %08x"), qp.dwFlags);
|
||
|
Trace(TEXT("qp.pQueryScope %08x"), qp.pQueryScope);
|
||
|
Trace(TEXT("qp.pQueryParameters %08x"), qp.pQueryParameters);
|
||
|
TraceGUID("qp.clsidForm: ", qp.clsidForm);
|
||
|
|
||
|
hres = _pQueryHandler->IssueQuery(&qp);
|
||
|
FailGracefully(hres, "Failed in IssueQuery");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// set the status text to reflect that we are initializng, otherwise it is
|
||
|
// left empty and looks like we have crashed.
|
||
|
|
||
|
if (LoadString(GLOBAL_HINSTANCE, IDS_INITIALIZING, szBuffer, ARRAYSIZE(szBuffer)))
|
||
|
{
|
||
|
SetStatusText(szBuffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hres = S_OK; // success
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
if (qp.pQueryParameters)
|
||
|
CoTaskMemFree(qp.pQueryParameters);
|
||
|
|
||
|
if (fSetCursor)
|
||
|
ResetWaitCursor();
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnNewQuery
|
||
|
/ -----------------------
|
||
|
/ Discard the current query, prompting the user as requierd.
|
||
|
/
|
||
|
/ In:
|
||
|
/ fAlwaysPrompt = TRUE if we force prompting of the user
|
||
|
/
|
||
|
/ Out:
|
||
|
/ BOOL
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
BOOL CQueryFrame::OnNewQuery(BOOL fAlwaysPrompt)
|
||
|
{
|
||
|
BOOL fQueryCleared = TRUE;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
RECT rc;
|
||
|
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnNewQuery");
|
||
|
|
||
|
if (_hwndResults || fAlwaysPrompt)
|
||
|
{
|
||
|
LoadString(GLOBAL_HINSTANCE, IDS_CLEARCURRENT, szBuffer, ARRAYSIZE(szBuffer));
|
||
|
if (IDOK != FrameMessageBox(szBuffer, MB_ICONINFORMATION|MB_OKCANCEL))
|
||
|
ExitGracefully(fQueryCleared, FALSE, "Used cancled new query");
|
||
|
|
||
|
if (_pQueryHandler)
|
||
|
_pQueryHandler->StopQuery();
|
||
|
|
||
|
CallFormPages(_pCurrentForm, CQPM_CLEARFORM, 0, 0);
|
||
|
|
||
|
if (_hwndResults)
|
||
|
{
|
||
|
DestroyWindow(_hwndResults); // no result view now
|
||
|
_hwndResults = NULL;
|
||
|
|
||
|
DestroyWindow(_hwndStatus); // no status bar
|
||
|
_hwndStatus = NULL;
|
||
|
|
||
|
GetWindowRect(_hwnd, &rc); // shrink the window
|
||
|
SetWindowPos(_hwnd, NULL,
|
||
|
0, 0, rc.right - rc.left, _szMinTrack.cy,
|
||
|
SWP_NOZORDER|SWP_NOMOVE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveValue(fQueryCleared);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnBrowse
|
||
|
/ ---------------------
|
||
|
/ Browse for a new scope, adding it to the list if not already present,
|
||
|
/ or selecting the previous scope.
|
||
|
/
|
||
|
/ In:
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::OnBrowse(VOID)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
LPQUERYSCOPE pQueryScope = NULL;
|
||
|
LPCQSCOPE pScope = NULL;
|
||
|
|
||
|
TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnBrowse");
|
||
|
|
||
|
// Call the handler and get a scope allocation back, then add it to the list
|
||
|
// of scopes to be displayed.
|
||
|
|
||
|
hres = GetSelectedScope(&pQueryScope);
|
||
|
FailGracefully(hres, "Failed to get the scope from the LookIn control");
|
||
|
|
||
|
Trace(TEXT("Calling BrowseForScope _hwnd %08x, pQueryScope %08x (%08x)"),
|
||
|
_hwnd, pQueryScope, pQueryScope->pScope);
|
||
|
|
||
|
hres = _pQueryHandler->BrowseForScope(_hwnd, pQueryScope ? pQueryScope->pScope:NULL, &pScope);
|
||
|
FailGracefully(hres, "Failed when calling BrowseForScope");
|
||
|
|
||
|
if ((hres != S_FALSE) && pScope)
|
||
|
{
|
||
|
hres = InsertScopeIntoList(pScope, DA_LAST, TRUE);
|
||
|
FailGracefully(hres, "Failed when adding the scope to the control");
|
||
|
|
||
|
ComboBox_SetCurSel(_hwndLookIn, ShortFromResult(hres));
|
||
|
}
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
if (pScope)
|
||
|
CoTaskMemFree(pScope);
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::OnHelp
|
||
|
/ -------------------
|
||
|
/ Invoke the context sensitive help for the window, catch the
|
||
|
/ handler specific and page specific stuff and pass those help
|
||
|
/ requests down to the relevant objects.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pHelpInfo -> help info structure
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::OnHelp(LPHELPINFO pHelpInfo)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
RECT rc;
|
||
|
HWND hwnd = (HWND)pHelpInfo->hItemHandle;
|
||
|
|
||
|
TraceEnter(TRACE_FRAME, "CQueryFrame::OnHelp");
|
||
|
|
||
|
// We are invoking help, theroefore we need ot check to see where element
|
||
|
// of the window we are being invoked for. If it is the
|
||
|
// result view then route the message to that, if its the form then
|
||
|
// likewise.
|
||
|
//
|
||
|
// If we don't hit any of the extension controls then lets pass the
|
||
|
// help onto WinHelp and get it to display the topics we have.
|
||
|
|
||
|
if (pHelpInfo->iContextType != HELPINFO_WINDOW)
|
||
|
ExitGracefully(hres, E_FAIL, "WM_HELP handler only copes with WINDOW objects");
|
||
|
|
||
|
if (_pCurrentFormPage->hwndPage && IsChild(_pCurrentFormPage->hwndPage, hwnd))
|
||
|
{
|
||
|
// it was on the query form page, therefore let it go there, that way
|
||
|
// they can provide topics specific to them
|
||
|
|
||
|
TraceMsg("Invoking help on the form pane");
|
||
|
|
||
|
hres = _CallPageProc(_pCurrentFormPage, CQPM_HELP, 0, (LPARAM)pHelpInfo);
|
||
|
FailGracefully(hres, "Failed when calling page proc to get help");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// pass the help information through to the handler as an activation,
|
||
|
// this should really just be a new method, but this works.
|
||
|
|
||
|
TraceMsg("Invoking help on the results pane");
|
||
|
TraceAssert(_pQueryHandler);
|
||
|
|
||
|
hres = _pQueryHandler->ActivateView(CQRVA_HELP, 0, (LPARAM)pHelpInfo);
|
||
|
FailGracefully(hres, "Handler WndProc returned FALSE");
|
||
|
}
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ Scope helper functions
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ _CallScopeProc
|
||
|
/ --------------
|
||
|
/ Releae the given scope object, freeing the object that is referenced
|
||
|
/ and passing a CQSM_RELEASE message to it.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pQueryScope -> scope object to be called
|
||
|
/ uMsg, pVoid -> parameters for the scope
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT _CallScopeProc(LPQUERYSCOPE pQueryScope, UINT uMsg, LPVOID pVoid)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
TraceEnter(TRACE_SCOPES, "_CallScopeProc");
|
||
|
Trace(TEXT("pQueryScope %08x, uMsg %d, pVoid %08x"), pQueryScope, uMsg, pVoid);
|
||
|
|
||
|
Trace(TEXT("(cbStruct %d, pScopeProc %08x, lParam %08x)"),
|
||
|
pQueryScope->pScope->cbStruct,
|
||
|
pQueryScope->pScope->pScopeProc,
|
||
|
pQueryScope->pScope->lParam);
|
||
|
|
||
|
if (!pQueryScope)
|
||
|
ExitGracefully(hres, S_OK, "pQueryScope == NULL");
|
||
|
|
||
|
hres = (pQueryScope->pScope->pScopeProc)(pQueryScope->pScope, uMsg, pVoid);
|
||
|
FailGracefully(hres, "Failed calling ScopeProc");
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ _FreeScope
|
||
|
/ ----------
|
||
|
/ Releae the given scope object, freeing the object that is referenced
|
||
|
/ and passing a CQSM_RELEASE message to it.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pQueryScope -> scope object to be released
|
||
|
/
|
||
|
/ Out:
|
||
|
/ INT == 1 always
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
INT _FreeScopeCB(LPVOID pItem, LPVOID pData)
|
||
|
{
|
||
|
return _FreeScope((LPQUERYSCOPE)pItem);
|
||
|
}
|
||
|
|
||
|
INT _FreeScope(LPQUERYSCOPE pQueryScope)
|
||
|
{
|
||
|
TraceEnter(TRACE_SCOPES, "_FreeScope");
|
||
|
Trace(TEXT("pQueryScope %08x, pQueryScope->pScope %08x"), pQueryScope, pQueryScope->pScope);
|
||
|
|
||
|
if (pQueryScope)
|
||
|
{
|
||
|
_CallScopeProc(pQueryScope, CQSM_RELEASE, NULL);
|
||
|
|
||
|
if (pQueryScope->pScope)
|
||
|
{
|
||
|
LocalFree((HLOCAL)pQueryScope->pScope);
|
||
|
pQueryScope->pScope = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TraceLeaveValue(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::InsertScopeIntoList
|
||
|
/ --------------------------------
|
||
|
/ Adds the given scope to the scope picker.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pQueryScope -> zcope object to be added to the view
|
||
|
/ i = index to insert the scope at
|
||
|
/ fAddToControl = add the scope the picker control
|
||
|
/ ppQueryScope -> recieves the new query scope object / = NULL
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::InsertScopeIntoList(LPCQSCOPE pScope, INT i, BOOL fAddToControl)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
QUERYSCOPE qs;
|
||
|
INT iScope;
|
||
|
|
||
|
TraceEnter(TRACE_SCOPES, "CQueryFrame::InsertScopeIntoList");
|
||
|
Trace(TEXT("pScope %08x, i %d, fAddToControl %d"), pScope, i, fAddToControl);
|
||
|
|
||
|
if (!pScope)
|
||
|
ExitGracefully(hres, E_INVALIDARG, "pScope == NULL, not allowed");
|
||
|
|
||
|
// if we don't have any scopes then allocate the DSA
|
||
|
|
||
|
if (!_hdsaScopes)
|
||
|
{
|
||
|
_hdsaScopes = DSA_Create(SIZEOF(QUERYSCOPE), 4);
|
||
|
TraceAssert(_hdsaScopes);
|
||
|
|
||
|
if (!_hdsaScopes)
|
||
|
ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate the scope DPA");
|
||
|
}
|
||
|
|
||
|
// Walk the list of scopes checking to see if this one is already in
|
||
|
// there, if not then we can add it.
|
||
|
|
||
|
for (iScope = 0 ; iScope < DSA_GetItemCount(_hdsaScopes) ; iScope++)
|
||
|
{
|
||
|
LPQUERYSCOPE pQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, iScope);
|
||
|
TraceAssert(pQueryScope);
|
||
|
|
||
|
if (S_OK == _CallScopeProc(pQueryScope, CQSM_SCOPEEQUAL, pScope))
|
||
|
{
|
||
|
hres = ResultFromShort(iScope);
|
||
|
goto exit_gracefully;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Take a copy of the scope blob passed by the caller. We copy the entire
|
||
|
// structure who's size is defined by cbStruct into a LocalAlloc block,
|
||
|
// once we have this we can then build the QUERYSCOPE structure that references
|
||
|
// it.
|
||
|
|
||
|
Trace(TEXT("pScope->cbStruct == %d"), pScope->cbStruct);
|
||
|
qs.pScope = (LPCQSCOPE)LocalAlloc(LPTR, pScope->cbStruct);
|
||
|
|
||
|
if (!qs.pScope)
|
||
|
ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate query scope");
|
||
|
|
||
|
Trace(TEXT("Copying structure qs.pScope %08x, pScope %08x"), qs.pScope, pScope);
|
||
|
CopyMemory(qs.pScope, pScope, pScope->cbStruct);
|
||
|
|
||
|
//qs.pScope = NULL;
|
||
|
qs.iImage = -1; // no image
|
||
|
|
||
|
// We have a QUERYSCOPE, so initialize it, if that works then append it to the
|
||
|
// DSA before either setting the return value or appending it to the control.
|
||
|
|
||
|
_CallScopeProc(&qs, CQSM_INITIALIZE, NULL);
|
||
|
|
||
|
iScope = DSA_InsertItem(_hdsaScopes, i, &qs);
|
||
|
Trace(TEXT("iScope = %d"), iScope);
|
||
|
|
||
|
if (iScope == -1)
|
||
|
{
|
||
|
_FreeScope(&qs);
|
||
|
ExitGracefully(hres, E_OUTOFMEMORY, "Failed to add scope to DSA");
|
||
|
}
|
||
|
|
||
|
if (fAddToControl)
|
||
|
{
|
||
|
LPQUERYSCOPE pQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, iScope);
|
||
|
TraceAssert(pQueryScope);
|
||
|
|
||
|
Trace(TEXT("Calling AddScopeToControl with %08x (%d)"), pQueryScope, iScope);
|
||
|
hres = AddScopeToControl(pQueryScope, iScope);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hres = ResultFromShort(iScope);
|
||
|
}
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::AddScopeToControl
|
||
|
/ ------------------------------
|
||
|
/ Adds the given scope to the scope picker.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pQueryScope -> zcope object to be added to the view
|
||
|
/ i = index into view where to insert the scope
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT (== index of item added)
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::AddScopeToControl(LPQUERYSCOPE pQueryScope, INT i)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
CQSCOPEDISPLAYINFO cqsdi;
|
||
|
COMBOBOXEXITEM cbi;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
TCHAR szIconLocation[MAX_PATH] = { 0 };
|
||
|
INT item;
|
||
|
|
||
|
TraceEnter(TRACE_SCOPES, "CQueryFrame::AddScopeToControl");
|
||
|
|
||
|
if (!pQueryScope)
|
||
|
ExitGracefully(hres, E_INVALIDARG, "No scope specified");
|
||
|
|
||
|
// Call the scope to get the display information about this
|
||
|
// scope before we attempt to add it.
|
||
|
|
||
|
cqsdi.cbStruct = SIZEOF(cqsdi);
|
||
|
cqsdi.dwFlags = 0;
|
||
|
cqsdi.pDisplayName = szBuffer;
|
||
|
cqsdi.cchDisplayName = ARRAYSIZE(szBuffer);
|
||
|
cqsdi.pIconLocation = szIconLocation;
|
||
|
cqsdi.cchIconLocation = ARRAYSIZE(szIconLocation);
|
||
|
cqsdi.iIconResID = 0;
|
||
|
cqsdi.iIndent = 0;
|
||
|
|
||
|
hres = _CallScopeProc(pQueryScope, CQSM_GETDISPLAYINFO, &cqsdi);
|
||
|
FailGracefully(hres, "Failed to get display info for the scope");
|
||
|
|
||
|
// Now add the item to the control, if they gave as an image then
|
||
|
// add that to the image list (and tweak the INSERTITEM structure
|
||
|
// accordingly).
|
||
|
|
||
|
cbi.mask = CBEIF_TEXT|CBEIF_INDENT;
|
||
|
cbi.iItem = i;
|
||
|
cbi.pszText = cqsdi.pDisplayName;
|
||
|
cbi.iIndent = cqsdi.iIndent;
|
||
|
|
||
|
Trace(TEXT("Indent is %d"), cqsdi.iIndent);
|
||
|
|
||
|
if (szIconLocation[0] && cqsdi.iIconResID)
|
||
|
{
|
||
|
INT iImage;
|
||
|
|
||
|
if (!_fScopeImageListSet)
|
||
|
{
|
||
|
HIMAGELIST himlSmall;
|
||
|
|
||
|
Shell_GetImageLists(NULL, &himlSmall);
|
||
|
SendMessage(_hwndLookIn, CBEM_SETIMAGELIST, 0, (LPARAM)himlSmall);
|
||
|
|
||
|
_fScopeImageListSet = TRUE;
|
||
|
}
|
||
|
|
||
|
cbi.mask |= CBEIF_IMAGE|CBEIF_SELECTEDIMAGE;
|
||
|
cbi.iImage = Shell_GetCachedImageIndex(szIconLocation, cqsdi.iIconResID, 0x0);;
|
||
|
cbi.iSelectedImage = cbi.iImage;
|
||
|
|
||
|
Trace(TEXT("Image index set to: %d"), cbi.iImage);
|
||
|
}
|
||
|
|
||
|
item = (INT)SendMessage(_hwndLookIn, CBEM_INSERTITEM, 0, (LPARAM)&cbi);
|
||
|
|
||
|
if (item == -1)
|
||
|
ExitGracefully(hres, E_FAIL, "Failed when inserting the scope to the list");
|
||
|
|
||
|
DoEnableControls(); // reflect button changes into UI
|
||
|
|
||
|
hres = ResultFromShort(item);
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::PopulateScopeControl
|
||
|
/ ---------------------------------
|
||
|
/ Collect the scopes that we want to display in the scope control and
|
||
|
/ then populate it. If the handler doesn't return any scopes then
|
||
|
/ we remove the control and assume that know what to do when they
|
||
|
/ don't receive a scope pointer.
|
||
|
/
|
||
|
/ In:
|
||
|
/ -
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::PopulateScopeControl(VOID)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
LPQUERYSCOPE pQueryScope;
|
||
|
INT i;
|
||
|
|
||
|
TraceEnter(TRACE_SCOPES, "CQueryFrame::PopulateScopeControl");
|
||
|
|
||
|
// Collect the scopes that we should be showing in the view, if we don't
|
||
|
// get any back then we disable the scope control, if we do get some then
|
||
|
// populate the scope control with them.
|
||
|
|
||
|
hres = _pQueryHandler->AddScopes();
|
||
|
_fAddScopesNYI = (hres == E_NOTIMPL);
|
||
|
|
||
|
if (hres != E_NOTIMPL)
|
||
|
FailGracefully(hres, "Failed when calling handler to add scopes");
|
||
|
|
||
|
if (_hdsaScopes)
|
||
|
{
|
||
|
// We have some scopes, so now we create the image list that we can use
|
||
|
// for icons with scopes. Then walk through the DPA getting the scope
|
||
|
// to give us some display information about itself that we can
|
||
|
// add to the combo box.
|
||
|
|
||
|
ComboBox_SetExtendedUI(_hwndLookIn, TRUE);
|
||
|
|
||
|
for (i = 0 ; i < DSA_GetItemCount(_hdsaScopes); i++)
|
||
|
{
|
||
|
pQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, i);
|
||
|
TraceAssert(pQueryScope);
|
||
|
|
||
|
AddScopeToControl(pQueryScope, i);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// we don't have any scopes after calling AddScopes, this is either
|
||
|
// because the ::AddScopes method is not implemented, or the
|
||
|
// scopes are being added async. If IssueQuery returned a success
|
||
|
// we assume they are coming in async and flag as such in our
|
||
|
// state.
|
||
|
|
||
|
if (!_fAddScopesNYI)
|
||
|
{
|
||
|
TraceMsg("Handler adding scopes async, so marking so");
|
||
|
_fScopesAddedAsync = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hres = S_OK; // success
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
Trace(TEXT("Default scope is index %d"), _iDefaultScope);
|
||
|
ComboBox_SetCurSel(_hwndLookIn, _iDefaultScope);
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::GetSelectedScope
|
||
|
/ -----------------------------
|
||
|
/ Get the selected from the the scope ComboBox, this is a reference into the
|
||
|
/ scope DSA.
|
||
|
/
|
||
|
/ In:
|
||
|
/ ppQueryScope = receives a pointer to the new scope
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::GetSelectedScope(LPQUERYSCOPE* ppQueryScope)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
COMBOBOXEXITEM cbi;
|
||
|
INT iScope;
|
||
|
|
||
|
TraceEnter(TRACE_SCOPES, "CQueryFrame::GetSelectedScope");
|
||
|
|
||
|
*ppQueryScope = NULL;
|
||
|
|
||
|
if (_hdsaScopes)
|
||
|
{
|
||
|
// Get the index for the current scope, if it doesn't give a real
|
||
|
// index to a item in our view then barf! Otherwise look up the
|
||
|
// associated scope.
|
||
|
|
||
|
iScope = ComboBox_GetCurSel(_hwndLookIn);
|
||
|
Trace(TEXT("iScope %d"), iScope);
|
||
|
|
||
|
if (iScope == -1)
|
||
|
ExitGracefully(hres, E_FAIL, "User entered scopes not supported yet");
|
||
|
|
||
|
*ppQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, iScope);
|
||
|
TraceAssert(*ppQueryScope);
|
||
|
}
|
||
|
|
||
|
hres = *ppQueryScope ? S_OK : E_FAIL;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
Trace(TEXT("Returning LPQUERYSCOPE %08x"), *ppQueryScope);
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ Form handling functions
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ _FreeQueryForm
|
||
|
/ ---------------
|
||
|
/ Destroy the QUERYFORM allocation being used to describe the form in
|
||
|
/ our DPA. We ensure that we issue a CQPM_RELEASE before doing anything
|
||
|
/
|
||
|
/ In:
|
||
|
/ pQueryForm -> query form to be destroyed
|
||
|
/
|
||
|
/ Out:
|
||
|
/ INT == 1 always
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
INT _FreeQueryFormCB(LPVOID pItem, LPVOID pData)
|
||
|
{
|
||
|
return _FreeQueryForm((LPQUERYFORM)pItem);
|
||
|
}
|
||
|
|
||
|
INT _FreeQueryForm(LPQUERYFORM pQueryForm)
|
||
|
{
|
||
|
TraceEnter(TRACE_FORMS, "_FreeQueryForm");
|
||
|
|
||
|
if (pQueryForm)
|
||
|
{
|
||
|
if (pQueryForm->hdsaPages)
|
||
|
{
|
||
|
DSA_DestroyCallback(pQueryForm->hdsaPages, _FreeQueryFormPageCB, NULL);
|
||
|
pQueryForm->hdsaPages = NULL;
|
||
|
}
|
||
|
|
||
|
Str_SetPtr(&pQueryForm->pTitle, NULL);
|
||
|
if (pQueryForm->hIcon)
|
||
|
{
|
||
|
DestroyIcon(pQueryForm->hIcon);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TraceLeaveValue(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ _FreeQueryFormPage
|
||
|
/ ------------------
|
||
|
/ Given a pointer to a query form page structure release the members that
|
||
|
// are of interest, including calling the PAGEPROC to releasee the underlying
|
||
|
/ object.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pQueryFormPage -> page to be removed
|
||
|
/
|
||
|
/ Out:
|
||
|
/ INT == 1 always
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
INT _FreeQueryFormPageCB(LPVOID pItem, LPVOID pData)
|
||
|
{
|
||
|
return _FreeQueryFormPage((LPQUERYFORMPAGE)pItem);
|
||
|
}
|
||
|
|
||
|
INT _FreeQueryFormPage(LPQUERYFORMPAGE pQueryFormPage)
|
||
|
{
|
||
|
TraceEnter(TRACE_FORMS, "_FreeQueryFormPage");
|
||
|
|
||
|
if (pQueryFormPage)
|
||
|
{
|
||
|
_CallPageProc(pQueryFormPage, CQPM_RELEASE, 0, 0); // NB: ignore return code
|
||
|
|
||
|
if (pQueryFormPage->hwndPage)
|
||
|
{
|
||
|
EnableThemeDialogTexture(pQueryFormPage->hwndPage, ETDT_DISABLE);
|
||
|
|
||
|
DestroyWindow(pQueryFormPage->hwndPage);
|
||
|
pQueryFormPage->hwndPage = NULL;
|
||
|
}
|
||
|
|
||
|
if (pQueryFormPage->pPage)
|
||
|
{
|
||
|
LocalFree(pQueryFormPage->pPage);
|
||
|
pQueryFormPage->pPage = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TraceLeaveValue(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ _CallPageProc
|
||
|
/ -------------
|
||
|
/ Call the given page object thunking the arguments as required if the
|
||
|
/ page object is non-UNICODE (only if building UNICODE).
|
||
|
/
|
||
|
/ In:
|
||
|
/ pQueryFormPage -> page object to be called
|
||
|
/ uMsg, wParam, lParam = parameters for message
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT _CallPageProc(LPQUERYFORMPAGE pQueryFormPage, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "_CallPageProc");
|
||
|
Trace(TEXT("pQueryFormPage %08x, pPage %08x, uMsg %d, wParam %08x, lParam %08x"),
|
||
|
pQueryFormPage, pQueryFormPage->pPage, uMsg, wParam, lParam);
|
||
|
|
||
|
if (!pQueryFormPage)
|
||
|
ExitGracefully(hres, S_OK, "pQueryFormPage == NULL");
|
||
|
|
||
|
hres = (pQueryFormPage->pPage->pPageProc)(pQueryFormPage->pPage, pQueryFormPage->hwndPage, uMsg, wParam, lParam);
|
||
|
FailGracefully(hres, "Failed calling PageProc");
|
||
|
|
||
|
// hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ Functions for adding query forms/pages
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
// CB to add forms to the form DSA.
|
||
|
|
||
|
HRESULT _AddFormsProc(LPARAM lParam, LPCQFORM pForm)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
QUERYFORM qf = {0};
|
||
|
HDSA hdsaForms = (HDSA)lParam;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "_AddFormsProc");
|
||
|
|
||
|
if (!pForm || !hdsaForms)
|
||
|
ExitGracefully(hres, E_INVALIDARG, "Failed to add page pForm == NULL");
|
||
|
|
||
|
// Allocate and thunk as required
|
||
|
|
||
|
qf.hdsaPages = NULL; // DSA of pages
|
||
|
qf.dwFlags = pForm->dwFlags; // flags
|
||
|
qf.clsidForm = pForm->clsid; // CLSID identifier for this form
|
||
|
qf.pTitle = NULL; // title used for drop down / title bar
|
||
|
qf.hIcon = pForm->hIcon; // hIcon passed by caller
|
||
|
qf.iImage = -1; // image list index of icon
|
||
|
qf.iForm = 0; // visible index of form in control
|
||
|
qf.iPage = 0; // currently selected page on form
|
||
|
|
||
|
if (!Str_SetPtr(&qf.pTitle, pForm->pszTitle))
|
||
|
ExitGracefully(hres, E_OUTOFMEMORY, "Failed to copy form title string");
|
||
|
|
||
|
// Allocate the DSA if one doesn't exist yet, then add in the form
|
||
|
// structure as required.
|
||
|
|
||
|
if (-1 == DSA_AppendItem(hdsaForms, &qf))
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to add form to the form DSA");
|
||
|
|
||
|
hres = S_OK; // success
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
if (FAILED(hres))
|
||
|
_FreeQueryForm(&qf);
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
// CB to add pages to the page DSA.
|
||
|
|
||
|
HRESULT _AddPagesProc(LPARAM lParam, REFCLSID clsidForm, LPCQPAGE pPage)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
QUERYFORMPAGE qfp = {0};
|
||
|
HDSA hdsaPages = (HDSA)lParam;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "_AddPagesProc");
|
||
|
|
||
|
if (!pPage || !hdsaPages)
|
||
|
ExitGracefully(hres, E_INVALIDARG, "Failed to add page pPage == NULL");
|
||
|
|
||
|
// copy the pPage structure for us to pass to the PAGEPROC later, nb: we
|
||
|
// use the cbStruct field to indicate the size of blob we must copy.
|
||
|
|
||
|
Trace(TEXT("pPage->cbStruct == %d"), pPage->cbStruct);
|
||
|
qfp.pPage = (LPCQPAGE)LocalAlloc(LPTR, pPage->cbStruct);
|
||
|
|
||
|
if (!qfp.pPage)
|
||
|
ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate copy of page structure");
|
||
|
|
||
|
Trace(TEXT("Copying structure qfp.pPage %08x, pPage %08x"), qfp.pPage, pPage);
|
||
|
CopyMemory(qfp.pPage, pPage, pPage->cbStruct); // copy the page structure
|
||
|
|
||
|
//qfp.pPage = NULL;
|
||
|
qfp.clsidForm = clsidForm;
|
||
|
qfp.pPageProc = pPage->pPageProc;
|
||
|
qfp.lParam = pPage->lParam;
|
||
|
qfp.hwndPage = NULL;
|
||
|
|
||
|
_CallPageProc(&qfp, CQPM_INITIALIZE, 0, 0);
|
||
|
|
||
|
if (-1 == DSA_AppendItem(hdsaPages, &qfp))
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to add the form to the DSA");
|
||
|
|
||
|
hres = S_OK; // succcess
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
if (FAILED(hres))
|
||
|
_FreeQueryFormPage(&qfp);
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
// Add forms/pages from a UNICODE IQueryForm iface
|
||
|
|
||
|
HRESULT CQueryFrame::AddFromIQueryForm(IQueryForm* pQueryForm, HKEY hKeyForm)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "CQueryFrame::AddFromIQueryForm");
|
||
|
|
||
|
if (!pQueryForm)
|
||
|
ExitGracefully(hres, E_FAIL, "pQueryForm == NULL, failing");
|
||
|
|
||
|
hres = pQueryForm->Initialize(hKeyForm);
|
||
|
FailGracefully(hres, "Failed in IQueryFormW::Initialize");
|
||
|
|
||
|
// Call the form object to add its form and then its pages
|
||
|
|
||
|
hres = pQueryForm->AddForms(_AddFormsProc, (LPARAM)_hdsaForms);
|
||
|
|
||
|
if (SUCCEEDED(hres) || (hres == E_NOTIMPL))
|
||
|
{
|
||
|
hres = pQueryForm->AddPages(_AddPagesProc, (LPARAM)_hdsaPages);
|
||
|
FailGracefully(hres, "Failed in IQueryForm::AddPages");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FailGracefully(hres, "Failed when calling IQueryForm::AddForms");
|
||
|
}
|
||
|
|
||
|
hres = S_OK; // success
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
#ifdef UNICODE
|
||
|
#define ADD_FROM_IQUERYFORM AddFromIQueryFormW
|
||
|
#else
|
||
|
#define ADD_FROM_IQUERYFORM AddFromIQueryFormA
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::GatherForms
|
||
|
/ ------------------------
|
||
|
/ Enumerate all the query forms for the given query handler and build
|
||
|
/ the DPA containing the list of them. Once we have done this we
|
||
|
/ can then populate the control at some more convientent moment.
|
||
|
/
|
||
|
/ When gathering we first hit the "handler", then the "Forms" sub-key
|
||
|
/ trying to load all the InProc servers that provide forms. We build
|
||
|
/ list of hidden, never shown etc.
|
||
|
/
|
||
|
/ In:
|
||
|
/ -
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
|
||
|
HRESULT _AddPageToForm(LPQUERYFORM pQueryForm, LPQUERYFORMPAGE pQueryFormPage, BOOL fClone)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
QUERYFORMPAGE qfp;
|
||
|
LPCQPAGE pPage;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "_AddPageToForm");
|
||
|
TraceAssert(pQueryForm);
|
||
|
TraceAssert(pQueryFormPage);
|
||
|
|
||
|
// ensure that we have a page DSA for this form object
|
||
|
|
||
|
if (!pQueryForm->hdsaPages)
|
||
|
{
|
||
|
TraceMsg("Creating a new page DSA for form");
|
||
|
pQueryForm->hdsaPages = DSA_Create(SIZEOF(QUERYFORMPAGE), 4);
|
||
|
|
||
|
if (!pQueryForm->hdsaPages)
|
||
|
ExitGracefully(hres, E_OUTOFMEMORY, "*** No page DSA on form object ***");
|
||
|
}
|
||
|
|
||
|
if (!fClone)
|
||
|
{
|
||
|
// Moving this page structure to the one associated with the query form,
|
||
|
// therefore just ensure that the form has a DSA for pages and just
|
||
|
// insert an item at the header (yes, we add the pages in reverse).
|
||
|
|
||
|
Trace(TEXT("Adding page %08x to form %s"), pQueryFormPage, pQueryForm->pTitle);
|
||
|
|
||
|
if (-1 == DSA_InsertItem(pQueryForm->hdsaPages, 0, pQueryFormPage))
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to copy page to form page DSA");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LPCQPAGE pPage = pQueryFormPage->pPage;
|
||
|
|
||
|
// Copying the page structure (it must be global), therefore clone
|
||
|
// the QUERYFORMPAGE strucutre and the CQPAGE into a new allocation
|
||
|
// and insert that into the page DSA.
|
||
|
|
||
|
Trace(TEXT("Cloning page %08x to form %s"), pQueryFormPage, pQueryForm->pTitle);
|
||
|
|
||
|
CopyMemory(&qfp, pQueryFormPage, SIZEOF(QUERYFORMPAGE));
|
||
|
qfp.pPage = (LPCQPAGE)LocalAlloc(LPTR, pPage->cbStruct);
|
||
|
|
||
|
if (!qfp.pPage)
|
||
|
ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate copy of page structure");
|
||
|
|
||
|
Trace(TEXT("Copying structure qfp.pPage %08x, pPage %08x"), qfp.pPage, pPage);
|
||
|
CopyMemory(qfp.pPage, pPage, pPage->cbStruct); // copy the page structure
|
||
|
|
||
|
_CallPageProc(&qfp, CQPM_INITIALIZE, 0, 0);
|
||
|
|
||
|
if (-1 == DSA_AppendItem(pQueryForm->hdsaPages, &qfp))
|
||
|
{
|
||
|
_FreeQueryFormPage(&qfp);
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to copy page to form DSA");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hres = S_OK; // success
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
HRESULT CQueryFrame::GatherForms(VOID)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
IQueryForm* pQueryForm = NULL;
|
||
|
HKEY hKeyForms = NULL;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
INT i, iPage, iForm;
|
||
|
RECT rect;
|
||
|
TC_ITEM tci;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "CQueryFrame::GatherForms");
|
||
|
|
||
|
// Construct DSA's so we can store the forms and pages as required.
|
||
|
|
||
|
_hdsaForms = DSA_Create(SIZEOF(QUERYFORM), 4);
|
||
|
_hdsaPages = DSA_Create(SIZEOF(QUERYFORMPAGE), 4);
|
||
|
|
||
|
if (!_hdsaForms || !_hdsaPages)
|
||
|
ExitGracefully(hres, E_OUTOFMEMORY, "Failed to create DSA's for storing pages/forms");
|
||
|
|
||
|
// First check the IQueryHandler to see if it supports IQueryForm, if it does
|
||
|
// then call it to add its objects. Note that we don't bother with ANSI/UNICODE
|
||
|
// at this point as the handler is assumed to be built the same the
|
||
|
// the query framework.
|
||
|
|
||
|
if (SUCCEEDED(_pQueryHandler->QueryInterface(IID_IQueryForm, (LPVOID*)&pQueryForm)))
|
||
|
{
|
||
|
hres = AddFromIQueryForm(pQueryForm, NULL);
|
||
|
FailGracefully(hres, "Failed when calling AddFromIQueryForm on handlers IQueryForm iface)");
|
||
|
}
|
||
|
|
||
|
// now attempt to build the list of forms and pages from the registered form
|
||
|
// extensions. These are declared under the handlers CLSID in the registry,
|
||
|
// under the sub-key "Forms".
|
||
|
|
||
|
if (ERROR_SUCCESS != RegOpenKeyEx(_hkHandler, c_szForms, NULL, KEY_READ, &hKeyForms))
|
||
|
{
|
||
|
TraceMsg("No 'Forms' sub-key found, therefore skipping");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Enumerate all the keys in the "Forms" key, these are assumed to be a list of
|
||
|
// the form handlers.
|
||
|
|
||
|
for (i = 0 ; TRUE ; i++)
|
||
|
{
|
||
|
DWORD cchStruct = ARRAYSIZE(szBuffer);
|
||
|
if (ERROR_SUCCESS != RegEnumKeyEx(hKeyForms, i, szBuffer, &cchStruct, NULL, NULL, NULL, NULL))
|
||
|
{
|
||
|
TraceMsg("RegEnumKeyEx return's false, therefore stopping eunmeration");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
GetForms(hKeyForms, szBuffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now tally the form/page information together and remove duplicates and attach the pages
|
||
|
// to forms, take special note of the global pages. As all forms will now be in the
|
||
|
// DSA we can check for a zero count and we don't have to worry about the order
|
||
|
// in which the the forms and pages were added.
|
||
|
|
||
|
if (!DSA_GetItemCount(_hdsaForms) || !DSA_GetItemCount(_hdsaPages))
|
||
|
ExitGracefully(hres, E_FAIL, "Either the forms or pages DSA is empty");
|
||
|
|
||
|
for (iPage = DSA_GetItemCount(_hdsaPages) ; --iPage >= 0 ;)
|
||
|
{
|
||
|
LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(_hdsaPages, iPage);
|
||
|
TraceAssert(pQueryFormPage);
|
||
|
|
||
|
Trace(TEXT("iPage %d (of %d)"), iPage, DSA_GetItemCount(_hdsaPages));
|
||
|
|
||
|
if (!(pQueryFormPage->pPage->dwFlags & CQPF_ISGLOBAL))
|
||
|
{
|
||
|
LPQUERYFORM pQueryForm = FindQueryForm(pQueryFormPage->clsidForm);
|
||
|
TraceAssert(pQueryForm);
|
||
|
|
||
|
TraceGUID("Adding page to form:", pQueryFormPage->clsidForm);
|
||
|
|
||
|
if (pQueryForm)
|
||
|
{
|
||
|
hres = _AddPageToForm(pQueryForm, pQueryFormPage, FALSE);
|
||
|
FailGracefully(hres, "Failed when adding page to form");
|
||
|
|
||
|
if (!DSA_DeleteItem(_hdsaPages, iPage))
|
||
|
TraceMsg("**** Failed to remove page from global DSA ****");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (iPage = DSA_GetItemCount(_hdsaPages) ; --iPage >= 0 ;)
|
||
|
{
|
||
|
LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(_hdsaPages, iPage);
|
||
|
TraceAssert(pQueryFormPage);
|
||
|
|
||
|
if ((pQueryFormPage->pPage->dwFlags & CQPF_ISGLOBAL))
|
||
|
{
|
||
|
Trace(TEXT("Adding global page to %d forms"), DSA_GetItemCount(_hdsaForms));
|
||
|
|
||
|
for (iForm = 0 ; iForm < DSA_GetItemCount(_hdsaForms); iForm++)
|
||
|
{
|
||
|
LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
|
||
|
TraceAssert(pQueryForm);
|
||
|
|
||
|
if (!(pQueryForm->dwFlags & CQFF_NOGLOBALPAGES))
|
||
|
{
|
||
|
hres = _AddPageToForm(pQueryForm, pQueryFormPage, TRUE);
|
||
|
FailGracefully(hres, "Failed when adding global page to form");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_FreeQueryFormPage(pQueryFormPage);
|
||
|
|
||
|
if (!DSA_DeleteItem(_hdsaPages, iPage))
|
||
|
TraceMsg("**** Failed to remove page from global DSA ****");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Walk the list of forms, rmeoving the ones which have no pages assocaited with
|
||
|
// them, we don't need these around confusing the world around us. Note that
|
||
|
// we walk backwards through the list removing.
|
||
|
//
|
||
|
// Also remove the optional forms we don't want to ehw orld to see
|
||
|
|
||
|
for (iForm = DSA_GetItemCount(_hdsaForms) ; --iForm >= 0 ;)
|
||
|
{
|
||
|
LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
|
||
|
TraceAssert(pQueryForm);
|
||
|
|
||
|
Trace(TEXT("pQueryForm %08x (%s), pQueryForm->hdsaPages %08x (%d)"),
|
||
|
pQueryForm,
|
||
|
pQueryForm->pTitle,
|
||
|
pQueryForm->hdsaPages,
|
||
|
pQueryForm->hdsaPages ? DSA_GetItemCount(pQueryForm->hdsaPages):0);
|
||
|
|
||
|
if (!pQueryForm->hdsaPages
|
||
|
|| !DSA_GetItemCount(pQueryForm->hdsaPages)
|
||
|
|| ((pQueryForm->dwFlags & CQFF_ISOPTIONAL) && !(_pOpenQueryWnd->dwFlags & OQWF_SHOWOPTIONAL)))
|
||
|
{
|
||
|
TraceGUID("Removing form: ", pQueryForm->clsidForm);
|
||
|
_FreeQueryForm(pQueryForm);
|
||
|
DSA_DeleteItem(_hdsaForms, iForm);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!DSA_GetItemCount(_hdsaForms))
|
||
|
ExitGracefully(hres, E_FAIL, "!!!!! No forms registered after page/form fix ups !!!!!");
|
||
|
|
||
|
// The pages have been attached to the forms so we can now attempt to create the
|
||
|
// form/page objects.
|
||
|
|
||
|
_szForm.cx = 0;
|
||
|
_szForm.cy = 0;
|
||
|
|
||
|
tci.mask = TCIF_TEXT;
|
||
|
tci.pszText = TEXT("");
|
||
|
tci.cchTextMax = 0;
|
||
|
TabCtrl_InsertItem(_hwndFrame, 0, &tci); // tabctrl needs at least one item so we can compute sizes
|
||
|
|
||
|
for (iForm = 0 ; iForm < DSA_GetItemCount(_hdsaForms); iForm++)
|
||
|
{
|
||
|
LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
|
||
|
TraceAssert(pQueryForm);
|
||
|
|
||
|
// Create each of the modeless page dialoges that we show to allow the user
|
||
|
// to edit the search criteria. We also grab the size and modify the
|
||
|
// form informaiton we have so that the default size of the dialog can be
|
||
|
// correctly computed.
|
||
|
|
||
|
for (iPage = 0 ; iPage < DSA_GetItemCount(pQueryForm->hdsaPages); iPage++)
|
||
|
{
|
||
|
LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryForm->hdsaPages, iPage);
|
||
|
TraceAssert(pQueryFormPage);
|
||
|
|
||
|
pQueryFormPage->hwndPage = CreateDialogParam(pQueryFormPage->pPage->hInstance,
|
||
|
MAKEINTRESOURCE(pQueryFormPage->pPage->idPageTemplate),
|
||
|
_hwnd,
|
||
|
pQueryFormPage->pPage->pDlgProc,
|
||
|
(LPARAM)pQueryFormPage->pPage);
|
||
|
if (!pQueryFormPage->hwndPage)
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to create query form page");
|
||
|
|
||
|
EnableThemeDialogTexture(pQueryFormPage->hwndPage, ETDT_ENABLETAB);
|
||
|
|
||
|
GetRealWindowInfo(pQueryFormPage->hwndPage, &rect, NULL);
|
||
|
TabCtrl_AdjustRect(_hwndFrame, TRUE, &rect);
|
||
|
|
||
|
_szForm.cx = max(rect.right-rect.left, _szForm.cx);
|
||
|
_szForm.cy = max(rect.bottom-rect.top, _szForm.cy);
|
||
|
|
||
|
// flush the form parameters
|
||
|
|
||
|
_CallPageProc(pQueryFormPage, CQPM_CLEARFORM, 0, 0);
|
||
|
|
||
|
// Call the page with CQPM_SETDEFAULTPARAMETERS with the
|
||
|
// OPENQUERYWINDOW structure. wParam is TRUE/FALSE indiciating if
|
||
|
// the form is the default one, and therefore if the pFormParam is
|
||
|
// valid.
|
||
|
|
||
|
_CallPageProc(pQueryFormPage, CQPM_SETDEFAULTPARAMETERS,
|
||
|
(WPARAM)((_pOpenQueryWnd->dwFlags & OQWF_DEFAULTFORM) &&
|
||
|
IsEqualCLSID(_pOpenQueryWnd->clsidDefaultForm, pQueryFormPage->clsidForm)),
|
||
|
(LPARAM)_pOpenQueryWnd);
|
||
|
}
|
||
|
|
||
|
// If the form has an hIcon then lets ensure that we add that to the form image
|
||
|
// list, any failure here is non-fatal, in that we will just skip that forms
|
||
|
// icon in the list (rather than barfing)
|
||
|
|
||
|
if (pQueryForm->hIcon)
|
||
|
{
|
||
|
if (!_himlForms)
|
||
|
_himlForms = ImageList_Create(COMBOEX_IMAGE_CX, COMBOEX_IMAGE_CY, 0, 4, 1);
|
||
|
|
||
|
if (_himlForms)
|
||
|
{
|
||
|
pQueryForm->iImage = ImageList_AddIcon(_himlForms, pQueryForm->hIcon);
|
||
|
TraceAssert(pQueryForm->iImage >= 0);
|
||
|
}
|
||
|
|
||
|
DestroyIcon(pQueryForm->hIcon);
|
||
|
pQueryForm->hIcon = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hres = S_OK; // success
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
DoRelease(pQueryForm);
|
||
|
|
||
|
if (hKeyForms)
|
||
|
RegCloseKey(hKeyForms);
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::GetForms
|
||
|
/ ---------------------
|
||
|
/ Given a HKEY to the forms list and the value name for the form we want
|
||
|
/ to add, query for the form information add add the form objects
|
||
|
/ to the master list.
|
||
|
/
|
||
|
/ In:
|
||
|
/ hKeyForms = HKEY for the {CLSID provider}\Forms key
|
||
|
/ pName -> key value to query for
|
||
|
/
|
||
|
/ Out:
|
||
|
/ VOID
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::GetForms(HKEY hKeyForms, LPTSTR pName)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
HKEY hKeyForm = NULL;
|
||
|
TCHAR szQueryFormCLSID[GUIDSTR_MAX+1];
|
||
|
DWORD dwFlags;
|
||
|
DWORD dwSize;
|
||
|
IUnknown* pUnknown = NULL;
|
||
|
IQueryForm* pQueryForm = NULL;
|
||
|
CLSID clsidForm;
|
||
|
BOOL fIncludeForms = FALSE;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "CQueryFrame::_GetForms");
|
||
|
Trace(TEXT("pName %s"), pName);
|
||
|
|
||
|
if (ERROR_SUCCESS != RegOpenKeyEx(hKeyForms, pName, NULL, KEY_READ, &hKeyForm))
|
||
|
ExitGracefully(hres, E_UNEXPECTED, "Failed to open the form key");
|
||
|
|
||
|
// Read the flags and try to determine if we should invoke this form object.
|
||
|
|
||
|
dwSize = SIZEOF(dwFlags);
|
||
|
if (ERROR_SUCCESS != RegQueryValueEx(hKeyForm, c_szFlags, NULL, NULL, (LPBYTE)&dwFlags, &dwSize))
|
||
|
{
|
||
|
TraceMsg("No flags, defaulting to something sensible");
|
||
|
dwFlags = QUERYFORM_CHANGESFORMLIST;
|
||
|
}
|
||
|
|
||
|
Trace(TEXT("Forms flag is %08x"), dwFlags);
|
||
|
|
||
|
// should be invoke this form object?
|
||
|
//
|
||
|
// - if dwFlags has QUERYFORM_CHANGESFORMSLIST, or
|
||
|
// - if dwFlags has QUERYFORM_CHANGESOPTFORMLIST and we are showing optional forms, or
|
||
|
// - neither set and the form object supports the requested form
|
||
|
|
||
|
if (!(dwFlags & QUERYFORM_CHANGESFORMLIST))
|
||
|
{
|
||
|
if ((dwFlags & QUERYFORM_CHANGESOPTFORMLIST) &&
|
||
|
(_pOpenQueryWnd->dwFlags & OQWF_SHOWOPTIONAL))
|
||
|
{
|
||
|
TraceMsg("Form is optional, are we are showing optional forms");
|
||
|
fIncludeForms = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// OK, so it either didn't update the form list, or wasn't marked as optional,
|
||
|
// so lets check to see if it supports the form the user has requested, if not
|
||
|
// then don't bother loading this guy.
|
||
|
|
||
|
if (_pOpenQueryWnd->dwFlags & OQWF_DEFAULTFORM)
|
||
|
{
|
||
|
TCHAR szBuffer[GUIDSTR_MAX+32];
|
||
|
HKEY hkFormsSupported;
|
||
|
|
||
|
TraceMsg("Checking for supported form");
|
||
|
|
||
|
if (ERROR_SUCCESS == RegOpenKeyEx(hKeyForm, TEXT("Forms Supported"), NULL, KEY_READ, &hkFormsSupported))
|
||
|
{
|
||
|
TraceMsg("Form has a 'Supported Forms' sub-key");
|
||
|
|
||
|
GetStringFromGUID(_pOpenQueryWnd->clsidDefaultForm, szQueryFormCLSID, ARRAYSIZE(szQueryFormCLSID));
|
||
|
Trace(TEXT("Checking for: %s"), szQueryFormCLSID);
|
||
|
|
||
|
if (ERROR_SUCCESS == RegQueryValueEx(hkFormsSupported, szQueryFormCLSID, NULL, NULL, NULL, NULL))
|
||
|
{
|
||
|
TraceMsg("Query form is in supported list");
|
||
|
fIncludeForms = TRUE;
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hkFormsSupported);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceMsg("No forms supported sub-key, so loading form object anyway");
|
||
|
fIncludeForms = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceMsg("Form updates form list");
|
||
|
fIncludeForms = TRUE;
|
||
|
}
|
||
|
|
||
|
// if fIncludeForms is TRUE, then the checks above succeeded and we are including forms
|
||
|
// from this object (identified by pName), so we must now get the CLSID of the object
|
||
|
// we are invoking and use its IQueryForm interface to add the forms that we want.
|
||
|
|
||
|
if (fIncludeForms)
|
||
|
{
|
||
|
// get the form object CLSID, having parse it, then CoCreate it adding the forms.
|
||
|
|
||
|
dwSize = SIZEOF(szQueryFormCLSID);
|
||
|
if (ERROR_SUCCESS != RegQueryValueEx(hKeyForm, c_szCLSID, NULL, NULL, (LPBYTE)szQueryFormCLSID, &dwSize))
|
||
|
ExitGracefully(hres, E_UNEXPECTED, "Failed to read the CLSID of the form");
|
||
|
|
||
|
Trace(TEXT("szQueryFormCLSID: %s"), szQueryFormCLSID);
|
||
|
|
||
|
if (!GetGUIDFromString(szQueryFormCLSID, &clsidForm))
|
||
|
ExitGracefully(hres, E_UNEXPECTED, "Fialed to parse the string as a GUID");
|
||
|
|
||
|
// we now have the CLISD of the form object, so we must attempt to CoCreate it, we try for
|
||
|
// the current build type (eg UNICODE) and then fall back to ANSI if thats not supported,
|
||
|
// so we can support ANSI query form objects on a UNICODE platform.
|
||
|
|
||
|
hres = CoCreateInstance(clsidForm, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
|
||
|
FailGracefully(hres, "Failed to CoCreate the form object");
|
||
|
|
||
|
if (SUCCEEDED(pUnknown->QueryInterface(IID_IQueryForm, (LPVOID*)&pQueryForm)))
|
||
|
{
|
||
|
hres = AddFromIQueryForm(pQueryForm, hKeyForm);
|
||
|
FailGracefully(hres, "Failed when adding forms from specified IQueryForm iface");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ExitGracefully(hres, E_UNEXPECTED, "Form object doesn't support IQueryForm(A/W)");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
if (hKeyForm)
|
||
|
RegCloseKey(hKeyForm);
|
||
|
|
||
|
DoRelease(pUnknown);
|
||
|
DoRelease(pQueryForm);
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::PopulateFormControl
|
||
|
/ ---------------------------------
|
||
|
/ Enumerate all the query forms for the given query handler and build
|
||
|
/ the DPA containing the list of them. Once we have done this we
|
||
|
/ can then populate the control at some more convientent moment.
|
||
|
/
|
||
|
/ When gathering we first hit the "handler", then the "Forms" sub-key
|
||
|
/ trying to load all the InProc servers that provide forms. We build
|
||
|
/ list of hidden, never shown etc.
|
||
|
/
|
||
|
/ In:
|
||
|
/ fIncludeHidden = list forms marked as hidden in control
|
||
|
/
|
||
|
/ Out:
|
||
|
/ VOID
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::PopulateFormControl(BOOL fIncludeHidden)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
COMBOBOXEXITEM cbi;
|
||
|
LPQUERYFORM pQueryForm;
|
||
|
INT i, iForm;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "CQueryFrame::PopulateFormControl");
|
||
|
Trace(TEXT("fIncludeHidden: %d"), fIncludeHidden);
|
||
|
|
||
|
// list which forms within the control
|
||
|
|
||
|
if (!_hdsaForms)
|
||
|
ExitGracefully(hres, E_FAIL, "No forms to list");
|
||
|
|
||
|
ComboBox_ResetContent(_hwndLookFor); // remove all items from that control
|
||
|
|
||
|
for (i = 0, iForm = 0 ; iForm < DSA_GetItemCount(_hdsaForms); iForm++)
|
||
|
{
|
||
|
LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
|
||
|
TraceAssert(pQueryForm);
|
||
|
|
||
|
// filter out those forms that are not of interest to this instance of the
|
||
|
// dialog.
|
||
|
|
||
|
if (((pQueryForm->dwFlags & CQFF_ISOPTIONAL) && !fIncludeHidden) ||
|
||
|
(pQueryForm->dwFlags & CQFF_ISNEVERLISTED))
|
||
|
{
|
||
|
Trace(TEXT("Hiding form: %s"), pQueryForm->pTitle);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// now add the form to the control, including the image if there is an image
|
||
|
// specified.
|
||
|
|
||
|
cbi.mask = CBEIF_TEXT|CBEIF_LPARAM;
|
||
|
cbi.iItem = i++;
|
||
|
cbi.pszText = pQueryForm->pTitle;
|
||
|
cbi.cchTextMax = lstrlen(pQueryForm->pTitle);
|
||
|
cbi.lParam = iForm;
|
||
|
|
||
|
if (pQueryForm->iImage >= 0)
|
||
|
{
|
||
|
Trace(TEXT("Form has an image %d"), pQueryForm->iImage);
|
||
|
|
||
|
cbi.mask |= CBEIF_IMAGE|CBEIF_SELECTEDIMAGE;
|
||
|
cbi.iImage = pQueryForm->iImage;
|
||
|
cbi.iSelectedImage = pQueryForm->iImage;
|
||
|
}
|
||
|
|
||
|
pQueryForm->iForm = (int)SendMessage(_hwndLookFor, CBEM_INSERTITEM, 0, (LPARAM)&cbi);
|
||
|
|
||
|
if (pQueryForm->iForm < 0)
|
||
|
{
|
||
|
Trace(TEXT("Form name: %s"), pQueryForm->pTitle);
|
||
|
ExitGracefully(hres, E_FAIL, "Failed to add the entry to the combo box");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveValue(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::SelectForm
|
||
|
/ -----------------------
|
||
|
/ Changes the current form to the one specified as an into the DPA.
|
||
|
/
|
||
|
/ In:
|
||
|
/ iForm = form to be selected
|
||
|
/
|
||
|
/ Out:
|
||
|
/ -
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::SelectForm(REFCLSID clsidForm)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
LPQUERYFORM pQueryForm, pOldQueryForm;
|
||
|
LPQUERYFORMPAGE pQueryFormPage;
|
||
|
LPCQPAGE pPage;
|
||
|
INT nCmdShow = SW_SHOW;
|
||
|
TCHAR szBuffer[64], szTitle[MAX_PATH];;
|
||
|
TC_ITEM tci;
|
||
|
INT i;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "CQueryFrame::SelectForm");
|
||
|
|
||
|
pQueryForm = FindQueryForm(clsidForm);
|
||
|
TraceAssert(pQueryForm);
|
||
|
|
||
|
if (!pQueryForm)
|
||
|
ExitGracefully(hres, S_FALSE, "Failed to find the requested form");
|
||
|
|
||
|
// Change the currently displayed form and change the displayed
|
||
|
// tabs to correctly indicate this
|
||
|
|
||
|
if ((pQueryForm != _pCurrentForm))
|
||
|
{
|
||
|
if (!OnNewQuery(FALSE)) // prompt the user
|
||
|
ExitGracefully(hres, S_FALSE, "Failed to select the new form");
|
||
|
|
||
|
TabCtrl_DeleteAllItems(_hwndFrame);
|
||
|
|
||
|
for (i = 0 ; i < DSA_GetItemCount(pQueryForm->hdsaPages) ; i++)
|
||
|
{
|
||
|
pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryForm->hdsaPages, i);
|
||
|
pPage = pQueryFormPage->pPage;
|
||
|
|
||
|
tci.mask = TCIF_TEXT;
|
||
|
tci.pszText = pQueryForm->pTitle;
|
||
|
tci.cchTextMax = MAX_PATH;
|
||
|
|
||
|
if (pPage->idPageName &&
|
||
|
LoadString(pPage->hInstance, pPage->idPageName, szBuffer, ARRAYSIZE(szBuffer)))
|
||
|
{
|
||
|
Trace(TEXT("Loaded page title string %s"), szBuffer);
|
||
|
tci.pszText = szBuffer;
|
||
|
}
|
||
|
|
||
|
TabCtrl_InsertItem(_hwndFrame, i, &tci);
|
||
|
}
|
||
|
|
||
|
ComboBox_SetCurSel(_hwndLookFor, pQueryForm->iForm);
|
||
|
_pCurrentForm = pQueryForm;
|
||
|
|
||
|
SelectFormPage(pQueryForm, pQueryForm->iPage);
|
||
|
|
||
|
// Change the dialog title to reflect the new form
|
||
|
|
||
|
if (LoadString(GLOBAL_HINSTANCE, IDS_FRAMETITLE, szBuffer, ARRAYSIZE(szBuffer)))
|
||
|
{
|
||
|
wsprintf(szTitle, szBuffer, pQueryForm->pTitle);
|
||
|
SetWindowText(_hwnd, szTitle);
|
||
|
}
|
||
|
|
||
|
// Tell the handler that we have changed the form, they can then use this
|
||
|
// new form name to modify their UI.
|
||
|
|
||
|
_pQueryHandler->ActivateView(CQRVA_FORMCHANGED, (WPARAM)lstrlen(pQueryForm->pTitle), (LPARAM)pQueryForm->pTitle);
|
||
|
}
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::SelectFormPage
|
||
|
/ ---------------------------
|
||
|
/ Change the currently active page of a query form to the one specified
|
||
|
/ by the index.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pQueryForm = query form to be changed
|
||
|
/ iForm = form to be selected
|
||
|
/
|
||
|
/ Out:
|
||
|
/ -
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
VOID CQueryFrame::SelectFormPage(LPQUERYFORM pQueryForm, INT iPage)
|
||
|
{
|
||
|
LPQUERYFORMPAGE pQueryFormPage;
|
||
|
RECT rect;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "CQueryFrame::SelectFormPage");
|
||
|
|
||
|
pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryForm->hdsaPages, iPage);
|
||
|
|
||
|
// Have we changed the query form page? If so then display the now dialog
|
||
|
// hiding the previous one. We call the TabCtrl to find out where we should
|
||
|
// be placing this new control.
|
||
|
|
||
|
if (pQueryFormPage != _pCurrentFormPage)
|
||
|
{
|
||
|
// Reflect the change into the tab control
|
||
|
|
||
|
TabCtrl_SetCurSel(_hwndFrame, iPage);
|
||
|
pQueryForm->iPage = iPage;
|
||
|
|
||
|
// Fix the size and visability of the new form
|
||
|
|
||
|
if (_pCurrentFormPage)
|
||
|
ShowWindow(_pCurrentFormPage->hwndPage, SW_HIDE);
|
||
|
|
||
|
GetRealWindowInfo(_hwndFrame, &rect, NULL);
|
||
|
TabCtrl_AdjustRect(_hwndFrame, FALSE, &rect);
|
||
|
|
||
|
SetWindowPos(pQueryFormPage->hwndPage,
|
||
|
HWND_TOP,
|
||
|
rect.left, rect.top,
|
||
|
rect.right - rect.left,
|
||
|
rect.bottom - rect.top,
|
||
|
SWP_SHOWWINDOW);
|
||
|
|
||
|
_pCurrentFormPage = pQueryFormPage;
|
||
|
}
|
||
|
|
||
|
TraceLeave();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::CallFormPages
|
||
|
/ --------------------------
|
||
|
/ Given a query form traverse the array of pages calling each of them
|
||
|
/ with the given message information. If any of the pages return
|
||
|
/ an error code (other than E_NOTIMPL) we bail.
|
||
|
/
|
||
|
/ In:
|
||
|
/ pQueryForm = query form to call
|
||
|
/ uMsg, wParam, lParam = parameters for the page
|
||
|
/
|
||
|
/ Out:
|
||
|
/ HRESULT
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
HRESULT CQueryFrame::CallFormPages(LPQUERYFORM pQueryForm, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
HRESULT hres = S_OK;
|
||
|
INT iPage;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "CQueryFrame::CallFormPages");
|
||
|
|
||
|
if (!pQueryForm || !pQueryForm->hdsaPages)
|
||
|
ExitGracefully(hres, E_FAIL, "No pQueryForm || pQueryForm->hdsaPages == NULL");
|
||
|
|
||
|
Trace(TEXT("pQueryForm %08x"), pQueryForm);
|
||
|
Trace(TEXT("uMsg %08x, wParam %08x, lParam %08x"), uMsg, wParam, lParam);
|
||
|
Trace(TEXT("%d pages to call"), DSA_GetItemCount(pQueryForm->hdsaPages));
|
||
|
|
||
|
// Call each page in turn if it matches the filter we have been given for calling
|
||
|
// down. If a page returns S_FALSE or a FAILURE then we exit the loop. If the
|
||
|
// failure however is E_NOTIMPL then we ignore.
|
||
|
|
||
|
for (iPage = 0 ; iPage < DSA_GetItemCount(pQueryForm->hdsaPages); iPage++)
|
||
|
{
|
||
|
LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryForm->hdsaPages, iPage);
|
||
|
TraceAssert(pQueryFormPage);
|
||
|
|
||
|
hres = _CallPageProc(pQueryFormPage, uMsg, wParam, lParam);
|
||
|
if (FAILED(hres) && (hres != E_NOTIMPL))
|
||
|
{
|
||
|
TraceMsg("PageProc returned a FAILURE");
|
||
|
break;
|
||
|
}
|
||
|
else if (hres == S_FALSE)
|
||
|
{
|
||
|
TraceMsg("PageProc returned S_FALSE, exiting loop");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit_gracefully:
|
||
|
|
||
|
TraceLeaveResult(hres);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
/ CQueryFrame::FindQueryForm
|
||
|
/ --------------------------
|
||
|
/ Given the CLSID for the form return a pointer to its LPQUERYFORM structure,
|
||
|
/ or NULL if not found.
|
||
|
/
|
||
|
/ In:
|
||
|
/ clsidForm = ID of the form
|
||
|
/
|
||
|
/ Out:
|
||
|
/ LPQUERYFORM
|
||
|
/----------------------------------------------------------------------------*/
|
||
|
LPQUERYFORM CQueryFrame::FindQueryForm(REFCLSID clsidForm)
|
||
|
{
|
||
|
LPQUERYFORM pQueryForm = NULL;
|
||
|
INT i;
|
||
|
|
||
|
TraceEnter(TRACE_FORMS, "CQueryFrame::FindQueryForm");
|
||
|
TraceGUID("Form ID", clsidForm);
|
||
|
|
||
|
for (i = 0 ; _hdsaForms && (i < DSA_GetItemCount(_hdsaForms)) ; i++)
|
||
|
{
|
||
|
pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, i);
|
||
|
TraceAssert(pQueryForm);
|
||
|
|
||
|
if (IsEqualCLSID(clsidForm, pQueryForm->clsidForm))
|
||
|
{
|
||
|
Trace(TEXT("Form is index %d (%08x)"), i, pQueryForm);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!_hdsaForms || (i >= DSA_GetItemCount(_hdsaForms)))
|
||
|
pQueryForm = NULL;
|
||
|
|
||
|
TraceLeaveValue(pQueryForm);
|
||
|
}
|