2025-11-28 00:35:46 +09:00

11115 lines
346 KiB
C++

//-----------------------------------------------------------------------------
// Microsoft OLE DB RowsetViewer
// Copyright (C) 1994 - 1999 By Microsoft Corporation.
//
// @doc
//
// @module CMDICHILD.CPP
//
//-----------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////
// Includes
//
//////////////////////////////////////////////////////////////////////////////
#include "Headers.h"
#ifdef MTSTXN
#include <xolehlp.h>
#include <txdtc.h>
#endif //MTSTXN
ULONG CMDIChild::m_iChildWindow = 0; //Static member
///////////////////////////////////////////////////////////////
// CMDIChild::CMDIChild
//
/////////////////////////////////////////////////////////////////
CMDIChild::CMDIChild(CMainWindow* pCMainWindow)
{
//Objects
ASSERT(pCMainWindow);
m_pCMainWindow = pCMainWindow;
//Controls
m_pCDataGrid = new CDataGrid(this);
m_pCQueryBox = new CQueryBox(this);
//Objects
m_pCDataSource = NULL; //Deferred
m_pCSession = NULL; //Deferred
m_pCCommand = NULL; //Deferred
m_pCMultipleResults = NULL; //Deferred
m_pCDataAccess = NULL; //Deferred
//Data
m_lastSizedEdge = 0;
m_iChildWindow++;
m_pwszConfig = NULL;
//Only set these "Default" properties, if requested by the user
if(GetOptions()->m_dwRowsetOpts & ROWSET_SETDEFAULTPROPS)
{
//DBPROP_CANHOLDROWS is required by the OLE DB Spec - Level-0 Conformance
//Since it is also legal to set a ReadOnly property, just blindy set it...
m_CDefPropSets.SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, DBTYPE_BOOL, (void*)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
}
}
////////////////////////////////////////////////////////////////
// CMDIChild::~CMDIChild
//
/////////////////////////////////////////////////////////////////
CMDIChild::~CMDIChild()
{
SAFE_RELEASE(m_pCDataAccess);
SAFE_RELEASE(m_pCMultipleResults);
SAFE_RELEASE(m_pCCommand);
SAFE_RELEASE(m_pCSession);
SAFE_RELEASE(m_pCDataSource);
//Controls
SAFE_DELETE(m_pCDataGrid);
SAFE_DELETE(m_pCQueryBox);
//Data
m_iChildWindow--;
SAFE_FREE(m_pwszConfig);
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetOptions
//
/////////////////////////////////////////////////////////////////
COptionsSheet* CMDIChild::GetOptions()
{
return m_pCMainWindow->GetOptions();
}
////////////////////////////////////////////////////////////////
// CMDIChild::SetConfig
//
/////////////////////////////////////////////////////////////////
void CMDIChild::SetConfig(WCHAR* pwszConfig, BOOL fCopy)
{
SAFE_FREE(m_pwszConfig);
//Optmization: If the caller no longer needs the name,
//no sense in reallocing, copying, freeing, freeing. Just reference it...
m_pwszConfig = fCopy ? wcsDuplicate(pwszConfig) : pwszConfig;
//Obtain the last Saved Query in the Query Box
if(m_pCQueryBox && m_pwszConfig)
{
WCHAR* pwszQuery = NULL;
//Formulate the key
static WCHAR wszKeyName[MAX_NAME_LEN];
StringFormat(wszKeyName, NUMELE(wszKeyName), L"%s\\%s\\Command", wszCONFIG_KEY, m_pwszConfig);
//Save the Query
GetRegEntry(HKEY_ROWSETVIEWER, wszKeyName, L"Query", &pwszQuery);
//Update the Query Box
m_pCQueryBox->SetWindowText(pwszQuery);
SAFE_FREE(pwszQuery);
}
}
////////////////////////////////////////////////////////////////
// CMDIChild::AutoPosition
//
/////////////////////////////////////////////////////////////////
BOOL CMDIChild::AutoPosition(BOOL fDefaultPosition)
{
if(fDefaultPosition || m_wndPlacement.length == 0)
{
//Default setting, upper right corner (3/4 of the client area)...
SIZE sizeClient = GetClientSize(m_pCMainWindow->m_hWndMDIClient);
return MoveWindow(m_hWnd, (INT)((float)sizeClient.cx * 0.25), 0, (INT)((float)sizeClient.cx * 0.75), (INT)((float)sizeClient.cy * 0.75), TRUE);
}
else
{
return SetWindowPlacement();
}
}
////////////////////////////////////////////////////////////////
// CMDIChild::OnCreate
//
/////////////////////////////////////////////////////////////////
BOOL CMDIChild::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// create child windows
// 1. ListView for rowset data
// 2. EditBox for entering SQL Text
// 3. ListBox for notifcations
// 4. ScrollBar for scrolling through the rowset
GetWindowPlacement();
SIZE size = { m_wndPlacement.rcNormalPosition.right - m_wndPlacement.rcNormalPosition.left,
m_wndPlacement.rcNormalPosition.bottom - m_wndPlacement.rcNormalPosition.top };
//Create the SQL Query Box
m_pCQueryBox->Create(m_hWnd, m_pCMainWindow->m_hLibRichEdit20 ? (IsUnicodeOS() ? L"RichEdit20W" : L"RichEdit20A") : L"RICHEDIT", NULL, IDC_EDITBOX,
WS_TABSTOP | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_HSCROLL | WS_VSCROLL | ES_AUTOVSCROLL | ES_MULTILINE /* | ES_DISABLENOSCROLL | ES_SELECTIONBAR*/, 0,
0, 0, size.cx, (INT)((float)size.cy * 0.25));
m_pCQueryBox->OnCreate(NULL);
m_pCQueryBox->SetWordWrap(TRUE);
//By default the RichEdit controls have a HUGE text. Instead of setting it
//to a small size font which is difficult for some international lcids, we will
//set it to the same font as the Tree control...
m_pCQueryBox->SetFont(m_pCMainWindow->m_pCMDIObjects->m_pCObjTree->GetFont());
//Create the DataGrid
m_pCDataGrid->Create(m_hWnd, WC_LISTVIEWW, NULL, IDC_LISTVIEW,
WS_TABSTOP | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | /*LVS_SINGLESEL |*/ LVS_AUTOARRANGE | LVS_REPORT | LVS_EDITLABELS | LVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE,
0, (INT)((float)size.cy * 0.25), size.cx - GetSystemMetrics(SM_CXVSCROLL), (INT)((float)size.cy * 0.75));
m_pCDataGrid->EnableWindow(FALSE);
//Use Extended ListView Styles!
SendMessage(m_pCDataGrid->m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES);
ListView_SetImageList(m_pCDataGrid->m_hWnd, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
m_pCDataGrid->OnCreate(NULL);
m_pCDataGrid->ClearAll(L"No Rowset");
//Set Focus to the Query Box
m_pCQueryBox->SetFocus();
//Setup Splitter Windows...
m_pCQueryBox->SetSplitter(NULL, m_pCDataGrid, NULL, NULL);
m_pCDataGrid->SetSplitter(m_pCQueryBox, NULL, NULL, NULL);
//Load Saved Window Positions
if(m_iChildWindow == 1)
{
memset(&m_wndPlacement, 0, sizeof(m_wndPlacement));
GetRegEntry(HKEY_ROWSETVIEWER, wszMDICHILD_KEY, L"WinPosition", &m_wndPlacement, sizeof(m_wndPlacement), NULL);
//Window Position
AutoPosition(m_wndPlacement.length == 0/*fDefaultPosition*/);
}
return TRUE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::OnInitialUpdate
//
/////////////////////////////////////////////////////////////////
BOOL CMDIChild::OnInitialUpdate()
{
//Update Window Title
UpdateWndTitle();
return TRUE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::UpdateControls
//
/////////////////////////////////////////////////////////////////
BOOL CMDIChild::UpdateControls()
{
CDataAccess* pCDataAccess = m_pCDataAccess && m_pCDataAccess->m_pIUnknown ? m_pCDataAccess : NULL;
//ToolBar Buttons
m_pCMainWindow->UpdateControls();
//Disable ListView window
m_pCDataGrid->EnableWindow(pCDataAccess != NULL);
//Update Window Title (in-case things have changed...)
UpdateWndTitle();
return TRUE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::DisplayDialog
//
/////////////////////////////////////////////////////////////////
INT_PTR CMDIChild::DisplayDialog(UINT uID, HWND hWndParent, DLGPROC lpDialogFunc, CBase* pCObject, UINT idSource)
{
m_idSource = idSource;
m_pCSource = pCObject;
return ::DisplayDialog(uID, hWndParent, lpDialogFunc, (LPARAM)this);
}
/////////////////////////////////////////////////////////////////////////////
// CMDIChild::OnUpdateCommand
//
/////////////////////////////////////////////////////////////////////////////
BOOL CMDIChild::OnUpdateCommand(HMENU hMenu, UINT nID, DWORD* pdwFlags)
{
//Default
switch(nID)
{
//Edit Window
ON_COMMAND_UI_ENABLED(IDM_PASTEEDITWINDOW, m_pCQueryBox->CanPaste())
ON_COMMAND_UI_ENABLED(IDM_CLEAREDITWINDOW, TRUE)
//Cut/Copy is only enabled - if something is selected.
ON_COMMAND_UI_ENABLED(IDM_COPYEDITWINDOW, m_pCQueryBox->GetSel(NULL, NULL))
ON_COMMAND_UI_ENABLED(IDM_CUTEDITWINDOW, m_pCQueryBox->GetSel(NULL, NULL))
//Menu Items that are always on
ON_COMMAND_UI_ENABLED(IDM_PROVIDERINFO, TRUE)
ON_COMMAND_UI_ENABLED(IDM_BROWSE_TABLENAME, TRUE)
};
return FALSE;
}
/////////////////////////////////////////////////////////////////////
// CMDIChild::OnNotify
//
/////////////////////////////////////////////////////////////////////
BOOL CMDIChild::OnNotify(INT idCtrl, NMHDR* pNMHDR)
{
//CDataGrid
if(m_pCDataGrid->OnNotify(idCtrl, pNMHDR))
return TRUE;
//CQueryBox
if(m_pCQueryBox->OnNotify(idCtrl, pNMHDR))
return TRUE;
//Delegate
return CMDIChildLite::OnNotify(idCtrl, pNMHDR);
}
/////////////////////////////////////////////////////////////////////
// CMDIChild::OnSizing
//
/////////////////////////////////////////////////////////////////////
BOOL CMDIChild::OnSizing(WPARAM nSide, REFPOINTS pts)
{
//Record which edge was touched...
m_lastSizedEdge = nSide;
return TRUE;
}
/////////////////////////////////////////////////////////////////////
// CMDIChild::OnSize
//
/////////////////////////////////////////////////////////////////////
BOOL CMDIChild::OnSize(WPARAM nType, REFPOINTS pts)
{
ASSERT(m_pCDataGrid->m_hWnd);
ASSERT(m_pCQueryBox->m_hWnd);
switch(nType)
{
case SIZE_RESTORED:
case SIZE_MAXIMIZED:
{
if(pts.x && pts.y)
{
//Obtain window sizes...
SIZE sizeEditBox = GetWindowSize(m_pCQueryBox->m_hWnd);
SIZE sizeListView = GetWindowSize(m_pCDataGrid->m_hWnd);
//The MainWindow has been resized, we need to readjust all
//Child controls, (ScrollBar, ListBox, ListView...)
//Move Windows with respect to the new
switch(m_lastSizedEdge)
{
//Top was moved, resize the Editbox
case WMSZ_TOP:
case WMSZ_TOPLEFT:
case WMSZ_TOPRIGHT:
sizeEditBox.cy = max(0, pts.y - sizeListView.cy);
break;
}
MoveWindow(m_pCQueryBox->m_hWnd, 0, 0, pts.x, sizeEditBox.cy, TRUE);
MoveWindow(m_pCDataGrid->m_hWnd, 0, sizeEditBox.cy, pts.x, pts.y-sizeEditBox.cy, TRUE);
m_lastSizedEdge = 0;
}
//Call default procedure first,
//to let MDI position the child & then move its children
//We simply do this by returning false, to indicate we didn't handle it...
return FALSE;
}
};
return FALSE;
}
/////////////////////////////////////////////////////////////////////
// CMDIChild::OnClose
//
/////////////////////////////////////////////////////////////////////
BOOL CMDIChild::OnClose()
{
//Send Message to the MainWindow to Close
//Mainly used so the MainWindow updates the ToolBar if there
//Are no more child windows...
SendMessage(m_pCMainWindow->GetWnd(), WM_COMMAND, GET_WM_COMMAND_MPS(IDM_CLOSEWINDOW, m_hWnd, 0));
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CMDIChild::OnDestroy
//
/////////////////////////////////////////////////////////////////////////////
BOOL CMDIChild::OnDestroy()
{
//Save the Query in the Query Box (before exiting)
if(m_pCQueryBox && m_pwszConfig)
{
WCHAR* pwszQuery = m_pCQueryBox->GetWindowText();
//Formulate the key
static WCHAR wszKeyName[MAX_NAME_LEN];
StringFormat(wszKeyName, NUMELE(wszKeyName), L"%s\\%s\\Command", wszCONFIG_KEY, m_pwszConfig);
//Save the Query
SetRegEntry(HKEY_ROWSETVIEWER, wszKeyName, L"Query", pwszQuery);
SAFE_FREE(pwszQuery);
}
//Save Window Positions
if(m_iChildWindow == 1)
{
//Window Positions
if(GetWindowPlacement())
SetRegEntry(HKEY_ROWSETVIEWER, wszMDICHILD_KEY, L"WinPosition", &m_wndPlacement, sizeof(m_wndPlacement));
}
//Delegate
return CMDIChildLite::OnDestroy();
}
/////////////////////////////////////////////////////////////////////
// CMDIChild::OnMDIActivate
//
/////////////////////////////////////////////////////////////////////
BOOL CMDIChild::OnMDIActivate(BOOL bActivate, HWND hWndActivate, HWND hWndDeactivate)
{
//So see if this window is being activated or deactivated
if(hWndActivate == m_hWnd)
{
CObjTree* pCObjTree = m_pCMainWindow->m_pCMDIObjects->m_pCObjTree;
ASSERT(pCObjTree);
//Select the Object in Tree that this Window corresponds to...
//NOTE: If there is already an object selected that belongs to this
//window, then there is no need to switch the objects
CBase* pCObject = pCObjTree->GetSelectedObject();
if(!pCObject || (pCObject->m_pCMDIChild != this))
pCObjTree->SelectObject(GetObject());
//Refresh all Controls
UpdateControls();
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CMDIChild::OnSetFocus
//
/////////////////////////////////////////////////////////////////////////////
BOOL CMDIChild::OnSetFocus(HWND hWndPrevFocus)
{
m_pCQueryBox->SetFocus();
return TRUE;
}
/////////////////////////////////////////////////////////////////////
// CMDIChild::OnCommand
//
/////////////////////////////////////////////////////////////////////
BOOL CMDIChild::OnCommand(UINT iID, HWND hWndCtrl)
{
//Get the "this" pointer
CMainWindow* pCMainWindow = m_pCMainWindow;
HWND hWnd = m_hWnd;
HRESULT hr = S_OK;
//Is there an active object...
CBase* pCObject = m_pCMainWindow->m_pCMDIObjects->m_pCObjTree->GetSelectedObject();
CDataAccess* pCDataAccess = SOURCE_GETOBJECT(pCObject, CDataAccess);
CRowset* pCRowset = SOURCE_GETOBJECT(pCDataAccess, CRowset);
CRow* pCRow = SOURCE_GETOBJECT(pCDataAccess, CRow);
CDataset* pCDataset = SOURCE_GETOBJECT(pCDataAccess, CDataset);
//Object Types
CBinder* pCBinder = SOURCE_GETOBJECT(pCObject, CBinder);
CCommand* pCCommand = m_pCCommand;
CSession* pCSession = m_pCSession;
CDataSource* pCDataSource = m_pCDataSource;
HCHAPTER hChapter = pCRowset ? pCRowset->m_hChapter : NULL;
//Setup the Source info
m_idSource = iID;
m_pCSource = pCObject;
//Most of these commands are "delegates" from CMainWindow, when dealing
//with the ToolBar or Menu for items dealing with MDI children...
switch(iID)
{
case IDM_IDBINFO_GETLITERALINFO:
if(SOURCE_GETINTERFACE(pCObject, IDBInfo))
DisplayDialog(IDD_GETLISTVIEW, hWnd, GetLiteralInfoProc, pCObject, iID);
return TRUE;
case IDM_PROVIDERINFO:
if(pCDataSource)
DisplayDialog(IDD_PROVIDERINFO, hWnd, ProviderInfoProc, pCDataSource, iID);
return TRUE;
case IDM_BROWSE_TABLENAME:
if(m_pCQueryBox->m_hWnd)
{
WCHAR wszBuffer[MAX_QUERY_LEN] = {0};
//Display Common Dialog to obtain TableName...
//This is for providers that use a file for TableName
hr = BrowseOpenFileName(GetAppLite()->m_hInstance, hWnd, L"Browse for TableName", wszBuffer, MAX_QUERY_LEN, NULL, L"DataSource Files (.dsn;.kag;.sav)\0*.dsn;*.kag;*.sav;\0DataBase Files (.mdb;.db;.dbf)\0*.mdb;*.db;*.dbf;\0Program Files (.xls;.clb)\0*.xls;*.clb;\0Text Files (.txt;.csv)\0*.txt;*.csv\0All Files (*.*)\0*.*\0\0");
if(SUCCEEDED(hr))
{
//Now just need to place this name in the EditBox
//Inserted after the current "caret"
m_pCQueryBox->ReplaceAll(wszBuffer);
}
}
return TRUE;
case IDM_IDBINFO_GETKEYWORDS:
if(pCObject)
{
CWaitCursor waitCursor;
WCHAR* pwszKeywords = NULL;
IDBInfo* pIDBInfo = SOURCE_GETINTERFACE(pCObject, IDBInfo);
//IDBInfo::GetKeywords
if(pIDBInfo)
{
XTEST(hr = pIDBInfo->GetKeywords(&pwszKeywords));
TRACE_METHOD(hr, L"IDBInfo::GetKeywords(&\"%s\")", pwszKeywords);
SAFE_FREE(pwszKeywords);
}
}
return TRUE;
//Create a Session...
case IDM_IDBCREATESESSION_CREATESESSION:
if(pCDataSource)
{
CInterfaceDlg interfaceDlg(IDD_AGGREGATION, L"IDBCreateSession::CreateSession", IID_IOpenRowset);
if(interfaceDlg.DoModal(hWnd) == IDOK)
{
CWaitCursor waitCursor;
//Create a new session (in its own window)
XTEST(hr = pCDataSource->CreateSession(interfaceDlg.GetAggregate(), interfaceDlg.GetSelInterface(), interfaceDlg.ppUnknown()));
if(SUCCEEDED(hr))
m_pCMainWindow->HandleObjectType(pCObject, interfaceDlg.pUnknown(), interfaceDlg.GetSelInterface(), eCSession, 0, NULL, CREATE_NEWWINDOW_IFEXISTS);
}
}
return TRUE;
//IDBDataSourceAdmin
case IDM_IDATASOURCEADMIN_CREATEDATASOURCE:
if(pCDataSource && pCDataSource->m_pIDBDataSourceAdmin)
DisplayDialog(IDD_DATASOURCEADMIN_CREATEDATASOURCE, hWnd, AdminCreateDataSourceProc, pCDataSource, iID);
return TRUE;
case IDM_IDATASOURCEADMIN_DESTROYDATASOURCE:
if(pCDataSource && pCDataSource->m_pIDBDataSourceAdmin)
{
CWaitCursor waitCursor;
//IDBDataSourceAdmin::DestroyDataSource
XTEST(hr = pCDataSource->m_pIDBDataSourceAdmin->DestroyDataSource());
TRACE_METHOD(hr, L"IDBDataSourceAdmin::DestroyDataSource()");
}
return TRUE;
case IDM_IDATASOURCEADMIN_GETCREATIONPROPERTIES:
if(pCDataSource && pCDataSource->m_pIDBDataSourceAdmin)
{
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.GetPropertyInfo(hWnd, &DBPROPSET_DBINITALL, IID_IDBDataSourceAdmin, NULL, pCDataSource->m_pIDBDataSourceAdmin);
}
return TRUE;
case IDM_IDATASOURCEADMIN_MODIFYDATASOURCE:
if(pCDataSource && pCDataSource->m_pIDBDataSourceAdmin)
{
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_DBINITALL, IID_IDBDataSourceAdmin, pCDataSource->m_pIDBDataSourceAdmin, NULL, NULL, pCDataSource->m_pIDBDataSourceAdmin);
}
return TRUE;
//IOpenRowset::OpenRowset
case IDM_OPENROWSET:
if(pCSession && pCSession->m_pIOpenRowset)
DisplayDialog(IDD_OPENROWSET, hWnd, OpenRowsetProc, pCSession, iID);
return TRUE;
//IGetDataSource::GetDataSource
case IDM_GETDATASOURCE:
if(pCSession && pCSession->m_pIGetDataSource)
{
CInterfaceDlg interfaceDlg(IDD_INTERFACE, L"IGetDataSource::GetDataSource", IID_IDBInitialize);
if(interfaceDlg.DoModal(hWnd) == IDOK)
{
CWaitCursor waitCursor;
//IGetDataSource::GetDataSource
if(SUCCEEDED(hr = pCSession->GetDataSource(interfaceDlg.GetSelInterface(), interfaceDlg.ppUnknown())))
m_pCMainWindow->HandleObjectType(pCSession, interfaceDlg.pUnknown(), interfaceDlg.GetSelInterface(), eCDataSource, 0, NULL, CREATE_FINDWINDOW);
}
}
return TRUE;
//ICommand
case IDM_EXECUTE:
if(pCCommand && pCCommand->m_pICommand)
DisplayDialog(IDD_EXECUTE, hWnd, ExecuteProc, pCCommand, iID);
return TRUE;
case IDM_COMMANDTEXT_EXECUTE:
if(pCCommand && pCCommand->m_pICommandText)
DisplayDialog(IDD_EXECUTE, hWnd, ExecuteProc, pCCommand, iID);
return TRUE;
case IDM_COMMAND_CANCEL:
if(pCCommand && pCCommand->m_pICommand)
{
CWaitCursor waitCursor;
//ICommand::Cancel
XTEST(hr = pCCommand->m_pICommand->Cancel());
TRACE_METHOD(hr, L"ICommand::Cancel()");
}
return TRUE;
case IDM_COMMAND_GETDBSESSION:
if(pCCommand && pCCommand->m_pICommand)
{
CInterfaceDlg interfaceDlg(IDD_INTERFACE, L"ICommand::GetDBSession", IID_IOpenRowset);
if(interfaceDlg.DoModal(hWnd) == IDOK)
{
CWaitCursor waitCursor;
//ICommand::GetDBSession
CComPtr<IUnknown> spUnknown;
XTEST(hr = pCCommand->m_pICommand->GetDBSession(interfaceDlg.GetSelInterface(), &spUnknown));
TRACE_METHOD(hr, L"ICommand::GetDBSession(%s, &0x%p)", GetInterfaceName(interfaceDlg.GetSelInterface()), spUnknown);
//Update the Session Object
if(SUCCEEDED(hr))
m_pCMainWindow->HandleObjectType(pCCommand, spUnknown, interfaceDlg.GetSelInterface(), eCSession, 0, NULL, CREATE_FINDWINDOW);
}
}
return TRUE;
////////////////////////////////////////////////////////////////////////
// IMDDataset
//
////////////////////////////////////////////////////////////////////////
case IDM_DATASET_GETAXISINFO:
if(pCDataset && pCDataset->m_pIMDDataset)
DisplayDialog(IDD_GETAXISINFO, hWnd, GetAxisInfoProc, pCDataset, iID);
return TRUE;
case IDM_DATASET_GETCELLDATA:
if(pCDataset && pCDataset->m_pIMDDataset)
{
INDEX cRows = 0;
INDEX* rgItems = NULL;
HROW* rghRows = NULL;
//Find all Selected Rows
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
if(cRows == 0)
{
wMessageBox(GetFocus(), MB_TASKMODAL | MB_ICONHAND | MB_OK | MB_DEFBUTTON1,
wsz_ERROR, L"Must first select a row...");
}
CWaitCursor waitCursor;
//Display all rows...
for(INDEX i=0; i<cRows; i++)
{
//Display the Data for this row...
m_pCDataGrid->DisplayData(rghRows[i], rgItems[i], MDPROP_AXES, true/*fAlways*/);
}
SAFE_FREE(rgItems);
SAFE_FREE(rghRows);
}
return TRUE;
case IDM_DATASET_GETAXISROWSET:
if(pCDataset && pCDataset->m_pIMDDataset)
DisplayDialog(IDD_GETAXISROWSET, hWnd, GetAxisRowsetProc, pCDataset, iID);
return TRUE;
case IDM_DATASET_FREEAXISINFO:
if(pCDataset && pCDataset->m_pIMDDataset)
pCDataset->FreeAxisInfo(&pCDataset->m_cAxis, &pCDataset->m_rgAxisInfo);
return TRUE;
case IDM_DATASET_GETSPECIFICATION:
if(pCDataset && pCDataset->m_pIMDDataset)
{
CInterfaceDlg interfaceDlg(IDD_INTERFACE, L"IMDDataset::GetSpecification", IID_ICommand);
if(interfaceDlg.DoModal(hWnd) == IDOK)
{
CWaitCursor waitCursor;
//IMDDataset::GetSpecification
CComPtr<IUnknown> spUnknown;
XTEST(hr = pCDataset->m_pIMDDataset->GetSpecification(interfaceDlg.GetSelInterface(), &spUnknown));
TRACE_METHOD(hr, L"IMDDataset::GetSpecification(%s, &0x%p)", GetInterfaceName(interfaceDlg.GetSelInterface()), spUnknown);
//What type of object, let our helper determine...
//NOTE: Can pontentially return other object types: (ie: CREATE_DETERMINE_TYPE)
if(SUCCEEDED(hr))
m_pCMainWindow->HandleObjectType(pCDataset, spUnknown, interfaceDlg.GetSelInterface(), eCCommand, 0, NULL, CREATE_FINDWINDOW | CREATE_DETERMINE_TYPE);
}
}
return TRUE;
case IDM_IMULTIPLERESULTS_GETRESULT:
{
CMultipleResultsDlg multipleResultsDlg(this);
multipleResultsDlg.DoModal(hWnd);
return TRUE;
}
case IDM_ITRANSACTION_ABORT:
if(SOURCE_GETINTERFACE(pCObject, ITransaction))
DisplayDialog(IDD_TRANSACTION_ABORT, hWnd, AbortTransactionProc, pCObject, iID);
return TRUE;
case IDM_ITRANSACTION_COMMIT:
if(SOURCE_GETINTERFACE(pCObject, ITransaction))
DisplayDialog(IDD_TRANSACTION_COMMIT, hWnd, CommitTransactionProc, pCObject, iID);
return TRUE;
case IDM_ITRANSACTION_GETTRANSACTIONINFO:
if(SOURCE_GETINTERFACE(pCObject, ITransaction))
DisplayDialog(IDD_TRANSACTION_GETINFO, hWnd, GetTransactionInfo, pCObject, iID);
return TRUE;
case IDM_ITRANSACTIONLOCAL_STARTTRANSACTION:
if(SOURCE_GETINTERFACE(pCObject, ITransactionLocal))
DisplayDialog(IDD_TRANSACTION_START, hWnd, StartTransactionProc, pCObject, iID);
return TRUE;
case IDM_ITRANSACTIONLOCAL_GETOPTIONSOBJECT:
{
ITransactionLocal* pITransactionLocal = SOURCE_GETINTERFACE(pCObject, ITransactionLocal);
if(pITransactionLocal)
{
CWaitCursor waitCursor;
CComPtr<ITransactionOptions> spTransactionOptions;
//ITransactionLocal::GetOptionsObject
XTEST(hr = pITransactionLocal->GetOptionsObject(&spTransactionOptions));
TRACE_METHOD(hr, L"ITransactionLocal::GetOptionsObject(&0x%p)", spTransactionOptions);
//Delegate
if(SUCCEEDED(hr))
m_pCMainWindow->HandleObjectType(pCObject, spTransactionOptions, IID_ITransactionOptions, eCTransactionOptions, 0, NULL, CREATE_NEWWINDOW_IFEXISTS);
}
return TRUE;
}
case IDM_ITRANSACTIONOBJECT_GETTRANSACTIONOBJECT:
{
ITransactionObject* pITransactionObject = SOURCE_GETINTERFACE(pCObject, ITransactionObject);
if(pITransactionObject)
{
CWaitCursor waitCursor;
CComPtr<ITransaction> spTransaction;
//ITransactionObject::GetTransactionObject
XTEST(hr = pITransactionObject->GetTransactionObject(1, &spTransaction));
TRACE_METHOD(hr, L"ITransactionObject::GetTransactionObject(1, &0x%p)", spTransaction);
//Delegate
if(SUCCEEDED(hr))
m_pCMainWindow->HandleObjectType(pCObject, spTransaction, IID_ITransaction, eCTransaction, 0, NULL, CREATE_NEWWINDOW_IFEXISTS);
}
return TRUE;
}
case IDM_ITRANSACTIONOPTIONS_GETOPTIONS:
{
ITransactionOptions* pITransactionOptions = SOURCE_GETINTERFACE(pCObject, ITransactionOptions);
if(pITransactionOptions)
{
CWaitCursor waitCursor;
XACTOPT XactOptions = {0};
//ITransactionOptions::GetOptions
XTEST(hr = pITransactionOptions->GetOptions(&XactOptions));
TRACE_METHOD(hr, L"ITransactionOptions::GetOptions(%d, \"%s\")", XactOptions.ulTimeout, XactOptions.szDescription);
}
return TRUE;
}
case IDM_ITRANSACTIONOPTIONS_SETOPTIONS:
{
ITransactionOptions* pITransactionOptions = SOURCE_GETINTERFACE(pCObject, ITransactionOptions);
if(pITransactionOptions)
DisplayDialog(IDD_TRANSACTION_SETOPTIONS, hWnd, SetTransactionOptionsProc, pCObject, iID);
return TRUE;
}
case IDM_ITRANSACTIONJOIN_RELEASETRANSACTION:
DisplayDialog(IDD_TRANSACTION_RELEASE, hWnd, ReleaseTransaction, pCObject, iID);
return TRUE;
case IDM_ITRANSACTIONDISPENSOR_BEGINTRANSACTION:
DisplayDialog(IDD_TRANSACTION_START, hWnd, StartTransactionProc, pCObject, iID);
return TRUE;
case IDM_ITRANSACTIONJOIN_GETOPTIONSOBJECT:
{
ITransactionJoin* pITransactionJoin = SOURCE_GETINTERFACE(pCObject, ITransactionJoin);
if(pITransactionJoin)
{
CWaitCursor waitCursor;
CComPtr<ITransactionOptions> spTransactionOptions;
//ITransactionJoin::GetOptionsObject
XTEST(hr = pITransactionJoin->GetOptionsObject(&spTransactionOptions));
TRACE_METHOD(hr, L"ITransactionJoin::GetOptionsObject(&0x%p)", spTransactionOptions);
//Delegate
if(SUCCEEDED(hr))
m_pCMainWindow->HandleObjectType(pCObject, spTransactionOptions, IID_ITransactionOptions, eCTransactionOptions, 0, NULL, CREATE_NEWWINDOW_IFEXISTS);
}
return TRUE;
}
case IDM_ITRANSACTIONJOIN_JOINTRANSACTION:
{
ITransactionJoin* pITransactionJoin = SOURCE_GETINTERFACE(pCObject, ITransactionJoin);
if(pITransactionJoin)
DisplayDialog(IDD_TRANSACTION_JOIN, hWnd, JoinTransactionProc, pCObject, iID);
return TRUE;
}
case IDM_ICOLUMNSINFO_GETCOLUMNINFO:
if(pCDataAccess && pCDataAccess->m_pIColumnsInfo)
DisplayDialog(IDD_GETLISTVIEW, hWnd, GetColInfoProc, pCDataAccess, iID);
return TRUE;
//ColumnsRowset
case IDM_ICOLUMNSROWSET_GETCOLUMNSROWSET:
if(SOURCE_GETINTERFACE(pCObject, IColumnsRowset))
DisplayDialog(IDD_GETCOLUMNSROWSET, hWnd, GetColumnsRowsetProc, pCObject, iID);
return TRUE;
case IDM_DELETEROWS:
if(pCRowset && pCRowset->m_pIRowsetChange)
{
CWaitCursor waitCursor;
DeleteSelectedRows();
}
return TRUE;
case IDM_SETDATA:
if(pCRowset && pCRowset->m_pIRowsetChange)
ChangeSelectedRow(pCRowset, IDM_SETDATA);
return TRUE;
case IDM_INSERTROW:
if(pCRowset && pCRowset->m_pIRowsetChange)
InsertNewRow();
return TRUE;
case IDM_CLEAREDITWINDOW:
//Select all the Text and Cut it...
//This method allows the text to be undone...
m_pCQueryBox->SetSel(0, -1);
m_pCQueryBox->Cut();
return TRUE;
case IDM_CUTEDITWINDOW:
m_pCQueryBox->Cut();
return TRUE;
case IDM_COPYEDITWINDOW:
m_pCQueryBox->Copy();
return TRUE;
case IDM_PASTEEDITWINDOW:
m_pCQueryBox->Paste();
return TRUE;
case IDM_RESTARTPOSITION:
if(pCRowset && pCRowset->m_pIRowset)
m_pCDataGrid->RestartPosition();
return TRUE;
case IDM_GETNEXTROWS:
if(pCRowset && pCRowset->m_pIRowset)
DisplayDialog(IDD_GETNEXTROWS, hWnd, GetNextRowsProc, pCRowset, iID);
return TRUE;
case IDM_RELEASEROWS:
if(pCRowset && pCRowset->m_pIRowset)
m_pCDataGrid->ReleaseRows(LV_ALLSELITEMS, FALSE/*fOnlyValidRows*/);
return TRUE;
case IDM_ADDREFROWS:
if(pCRowset && pCRowset->m_pIRowset)
m_pCDataGrid->AddRefRows(LV_ALLSELITEMS);
return TRUE;
case IDM_RELEASEALLROWS:
if(pCRowset && pCRowset->m_pIRowset)
m_pCDataGrid->ReleaseRows(LV_ALLITEMS, FALSE/*fOnlyValidRows*/);
return TRUE;
case IDM_GETROWFROMHROW:
if(pCRowset && pCRowset->m_pIGetRow)
{
//Obtain the First selected Row
HROW hRow = NULL;
if(m_pCDataGrid->GetSelectedRow(&hRow) == LVM_ERR)
return TRUE;
CComPtr<IUnknown> spUnknown;
CInterfaceDlg interfaceDlg(IDD_AGGREGATION, L"IGetRow::GetRowFromHROW", IID_IRow);
if(interfaceDlg.DoModal(hWnd) == IDOK)
{
CWaitCursor waitCursor;
//IGetRow::GetRowFromHROW
if(SUCCEEDED(pCRowset->GetRowFromHROW(NULL, hRow, interfaceDlg.GetSelInterface(), &spUnknown)))
{
//Create in new window
CBase* pCObject = m_pCMainWindow->HandleObjectType(pCRowset, spUnknown, interfaceDlg.GetSelInterface(), eCRow, 0, NULL, CREATE_NEWWINDOW | CREATE_NODISPLAY);
if(pCObject)
{
//Fill in which row handle this row was created from...
//Just for display purposes...
CRow* pCRow = SOURCE_GETOBJECT(pCObject, CRow);
if(pCRow)
pCRow->m_hSourceRow = hRow;
pCObject->DisplayObject();
}
}
}
}
return TRUE;
case IDM_GETURLFROMHROW:
if(pCRowset && pCRowset->m_pIGetRow)
{
CWaitCursor waitCursor;
WCHAR* pwszURL = NULL;
//Obtain the First selected Row
HROW hRow = NULL;
if(m_pCDataGrid->GetSelectedRow(&hRow) == LVM_ERR)
return TRUE;
//IGetRow::GetURLFromHROW
XTEST(hr = pCRowset->m_pIGetRow->GetURLFromHROW(hRow, &pwszURL));
TRACE_METHOD(hr, L"IGetRow::GetURLFromHROW(0x%p, \"%s\")", hRow, pwszURL);
//Update our saved Binding...
if(pCBinder)
{
SAFE_FREE(pCBinder->m_pwszURL);
pCBinder->m_pwszURL = pwszURL;
}
}
return TRUE;
//IRow - methods
case IDM_IROW_GETCOLUMNS:
if(SOURCE_GETINTERFACE(pCObject, IRow))
{
CWaitCursor waitCursor;
//Display the Data for this row...
m_pCDataGrid->DisplayData(0, 1, DBPROP_IRow, true/*fAlways*/);
}
return TRUE;
case IDM_IROW_GETSOURCEROWSET:
{
IRow* pIRow = SOURCE_GETINTERFACE(pCObject, IRow);
if(pIRow)
{
CInterfaceDlg interfaceDlg(IDD_INTERFACE, L"IRow::GetSourceRowset", IID_IRowset);
if(interfaceDlg.DoModal(hWnd) == IDOK)
{
CWaitCursor waitCursor;
CComPtr<IUnknown> spUnknown;
HROW hRow = NULL;
//IRow::GetSourceRowset
XTEST(hr = pIRow->GetSourceRowset(interfaceDlg.GetSelInterface(), &spUnknown, &hRow));
TRACE_METHOD(hr, L"IRow::GetSourceRowset(%s, &0x%p, &0x%p)", GetInterfaceName(interfaceDlg.GetSelInterface()), spUnknown, hRow);
//Update the Rowset Object
//NOTE: We don't want to popup a new window if the parent rowset
//is already active in its own window. We will first try to find the
//parent, otherwise activate a new window...
if(SUCCEEDED(hr))
m_pCMainWindow->HandleObjectType(pCObject, spUnknown, interfaceDlg.GetSelInterface(), eCRowset, 0, NULL, CREATE_FINDWINDOW | CREATE_RESTARTPOSITION);
//Release the Row Handle...
CRowset* pCRowset = SOURCE_GETPARENT(pCObject, CRowset);
if(pCRowset)
pCRowset->ReleaseRows(1, &hRow, NULL);
}
}
return TRUE;
}
case IDM_IDBCREATECOMMAND_CREATECOMMAND:
if(SOURCE_GETINTERFACE(pCObject, IDBCreateCommand))
{
CInterfaceDlg interfaceDlg(IDD_AGGREGATION, L"IDBCreateCommand::CreateCommand", IID_ICommandText);
if(interfaceDlg.DoModal(hWnd) == IDOK)
{
CWaitCursor waitCursor;
CSession* pCSession = SOURCE_GETOBJECT(pCObject, CSession);
CRow* pCRow = SOURCE_GETOBJECT(pCObject, CRow);
ASSERT(pCSession || pCRow);
//Create a new Command Object (with default properties)
if(pCSession)
hr = pCSession->CreateCommand(interfaceDlg.GetAggregate(), interfaceDlg.GetSelInterface(), interfaceDlg.ppUnknown());
else
hr = pCRow->CreateCommand(interfaceDlg.GetAggregate(), interfaceDlg.GetSelInterface(), interfaceDlg.ppUnknown());
if(SUCCEEDED(hr))
m_pCMainWindow->HandleObjectType(pCObject, interfaceDlg.pUnknown(), interfaceDlg.GetSelInterface(), eCCommand, 0, NULL, CREATE_NEWWINDOW_IFEXISTS);
}
}
return TRUE;
//IRowChange - methods
case IDM_IROW_SETCOLUMNS:
if(pCRow && pCRow->m_pIRowChange)
ChangeSelectedRow(pCRow, IDM_IROW_SETCOLUMNS);
return TRUE;
//IRowSchemaChange - methods
case IDM_IROW_DELETECOLUMNS:
if(pCRow && pCRow->m_pIRowSchemaChange)
ChangeSelectedRow(pCRow, IDM_IROW_DELETECOLUMNS);
return TRUE;
case IDM_IGETSESSION_GETSESSION:
{
IGetSession* pIGetSession = SOURCE_GETINTERFACE(pCObject, IGetSession);
if(pIGetSession)
{
CInterfaceDlg interfaceDlg(IDD_INTERFACE, L"IGetSession::GetSession", IID_IOpenRowset);
if(interfaceDlg.DoModal(hWnd) == IDOK)
{
CWaitCursor waitCursor;
//IGetSession::GetSession
CComPtr<IUnknown> spUnknown;
XTEST(hr = pIGetSession->GetSession(interfaceDlg.GetSelInterface(), &spUnknown));
TRACE_METHOD(hr, L"IGetSession::GetSession(%s, &0x%p)", GetInterfaceName(interfaceDlg.GetSelInterface()), spUnknown);
//Update the Session
if(SUCCEEDED(hr))
m_pCMainWindow->HandleObjectType(pCObject, spUnknown, interfaceDlg.GetSelInterface(), eCSession, 0, NULL, CREATE_FINDWINDOW);
}
}
return TRUE;
}
case IDM_IROW_OPEN:
if(SOURCE_GETINTERFACE(pCObject, IRow))
DisplayDialog(IDD_ROW_OPEN, hWnd, RowOpenProc, pCObject, iID);
return TRUE;
case IDM_ISCOPEDOPERATIONS_OPENROWSET:
if(SOURCE_GETINTERFACE(pCObject, IScopedOperations))
DisplayDialog(IDD_OPENROWSET, hWnd, OpenRowsetProc, pCObject, iID);
return TRUE;
case IDM_ISCOPEDOPERATIONS_DELETE:
if(SOURCE_GETINTERFACE(pCObject, IScopedOperations))
DisplayDialog(IDD_ISCO_DELETE, hWnd, ISCO_DeleteProc, pCObject, iID);
return TRUE;
case IDM_ISCOPEDOPERATIONS_COPY:
if(SOURCE_GETINTERFACE(pCObject, IScopedOperations))
DisplayDialog(IDD_ISCO_COPY, hWnd, ISCO_Proc, pCObject, iID);
return TRUE;
case IDM_ISCOPEDOPERATIONS_MOVE:
if(SOURCE_GETINTERFACE(pCObject, IScopedOperations))
DisplayDialog(IDD_ISCO_COPY, hWnd, ISCO_Proc, pCObject, iID);
return TRUE;
case IDM_SETCOMMANDTEXT:
if(pCCommand && pCCommand->m_pICommandText)
DisplayDialog(IDD_SETCOMMANDTEXT, hWnd, SetCommandTextProc, pCCommand, iID);
return TRUE;
case IDM_GETCOMMANDTEXT:
if(pCCommand && pCCommand->m_pICommandText)
{
CWaitCursor waitCursor;
GUID guidDialec = GUID_NULL;
WCHAR wszBuffer[MAX_NAME_LEN+1] = {0};
WCHAR* pwszDialect = NULL;
WCHAR* pwszBuffer = NULL;
XTEST(hr = pCCommand->m_pICommandText->GetCommandText(&guidDialec, &pwszBuffer));
//Try to find a string respentation of the guidDialec
if(!(pwszDialect = GetDialectName(guidDialec)))
{
pwszDialect = wszBuffer;
StringFromGUID2(guidDialec, wszBuffer, MAX_NAME_LEN);
}
TRACE_METHOD(hr, L"ICommandText::GetCommandText(&%s, &\"%s\")", pwszDialect, pwszBuffer);
SAFE_FREE(pwszBuffer);
}
return TRUE;
case IDM_SETCOMMANDSTREAM:
if(pCCommand && pCCommand->m_pICommandStream)
DisplayDialog(IDD_SETCOMMANDSTREAM, hWnd, SetCommandTextProc, pCCommand, iID);
return TRUE;
case IDM_GETCOMMANDSTREAM:
if(pCCommand && pCCommand->m_pICommandStream)
{
CWaitCursor waitCursor;
GUID guidDialec = GUID_NULL;
IID iid = IID_NULL;
CComPtr<IUnknown> spUnknown;
WCHAR wszBuffer[MAX_NAME_LEN+1] = {0};
WCHAR* pwszDialect = NULL;
//ICommandStream::GetCommandStream
XTEST(hr = pCCommand->m_pICommandStream->GetCommandStream(&iid, &guidDialec, (IUnknown**)&spUnknown));
//Try to find a string respentation of the guidDialec
if(!(pwszDialect = GetDialectName(guidDialec)))
{
pwszDialect = wszBuffer;
StringFromGUID2(guidDialec, wszBuffer, MAX_NAME_LEN);
}
TRACE_METHOD(hr, L"ICommandStream::GetCommandStream(&%s, &%s, &0x%p)", GetInterfaceName(iid), pwszDialect, spUnknown);
//Stand Alone Object (no window required)
if(SUCCEEDED(hr))
{
CStream* pCStream = new CStream(m_pCMainWindow);
pCStream->CreateObject(pCCommand, iid, spUnknown);
}
}
return TRUE;
case IDM_COMMANDPERSIST_GETCURRENTCOMMAND:
if(pCCommand && pCCommand->m_pICommandPersist)
{
CWaitCursor waitCursor;
DBID* pCommandID = NULL;
//ICommandPersist::GetCurrentCommand
XTEST(pCCommand->GetCurrentCommand(&pCommandID));
DBIDFree(pCommandID);
SAFE_FREE(pCommandID);
}
return TRUE;
case IDM_COMMANDPERSIST_DELETECOMMAND:
case IDM_COMMANDPERSIST_LOADCOMMAND:
case IDM_COMMANDPERSIST_SAVECOMMAND:
if(pCCommand && pCCommand->m_pICommandPersist)
DisplayDialog(IDD_COMMANDPERSIST, hWnd, CommandPersistProc, pCCommand, iID);
return TRUE;
case IDM_COMMANDPREPARE:
if(pCCommand && pCCommand->m_pICommandPrepare)
{
CWaitCursor waitCursor;
//ICommand::Prepare
XTEST(hr = pCCommand->Prepare(0));
}
return TRUE;
case IDM_COMMANDUNPREPARE:
if(pCCommand && pCCommand->m_pICommandPrepare)
{
CWaitCursor waitCursor;
//ICommand::Unprepare
XTEST(hr = pCCommand->m_pICommandPrepare->Unprepare());
TRACE_METHOD(hr, L"ICommandPrepare::Unprepare()");
}
return TRUE;
case IDM_GETSCHEMAS:
case IDM_GETSCHEMAROWSET:
if(pCSession && pCSession->m_pIDBSchemaRowset)
{
CSchemaDlg schemaDlg(this);
schemaDlg.Display();
}
return TRUE;
case IDM_ISESSIONPROPERTIES_GETPROPERTIES:
if(pCSession && pCSession->m_pISessionProperties)
{
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.GetProperties(hWnd, &DBPROPSET_SESSIONALL, IID_ISessionProperties, pCSession->m_pISessionProperties, pCDataSource ? pCDataSource->m_pIDBProperties : NULL);
}
return TRUE;
case IDM_COMMAND_GETPROPERTIES:
if(pCCommand && pCCommand->m_pICommandProperties)
{
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.GetProperties(hWnd, &DBPROPSET_ROWSETALL, IID_ICommandProperties, pCCommand->m_pICommandProperties, pCDataSource ? pCDataSource->m_pIDBProperties : NULL);
}
return TRUE;
case IDM_IROWSET_GETPROPERTIES:
if(pCRowset && pCRowset->m_pIRowsetInfo)
{
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.GetProperties(hWnd, &DBPROPSET_ROWSETALL, IID_IRowsetInfo, pCRowset->m_pIRowsetInfo, pCDataSource ? pCDataSource->m_pIDBProperties : NULL);
}
return TRUE;
//IRowsetInfo
case IDM_GETSPECIFICATION:
if(pCRowset && pCRowset->m_pIRowsetInfo)
{
CInterfaceDlg interfaceDlg(IDD_INTERFACE, L"IRowsetInfo::GetSpecification", IID_IOpenRowset);
if(interfaceDlg.DoModal(hWnd) == IDOK)
{
CWaitCursor waitCursor;
//IRowset::GetSpecification
CComPtr<IUnknown> spUnknown;
XTEST(hr = pCRowset->m_pIRowsetInfo->GetSpecification(interfaceDlg.GetSelInterface(), &spUnknown));
TRACE_METHOD(hr, L"IRowset::GetSpecification(%s, &0x%p)", GetInterfaceName(interfaceDlg.GetSelInterface()), spUnknown);
//What type of object, let our helper determine...
//NOTE: Can pontentially return other object types: (ie: CREATE_DETERMINE_TYPE)
if(SUCCEEDED(hr))
m_pCMainWindow->HandleObjectType(pCRowset, spUnknown, interfaceDlg.GetSelInterface(), eCSession, 0, NULL, CREATE_FINDWINDOW | CREATE_DETERMINE_TYPE);
}
}
return TRUE;
case IDM_GETREFERENCEDROWSET:
if(pCRowset && pCRowset->m_pIRowsetInfo)
DisplayDialog(IDD_GETREFERENCEDROWSET, hWnd, GetReferencedRowsetProc, pCRowset, iID);
return TRUE;
case IDM_ISESSIONPROPERTIES_SETPROPERTIES:
if(pCSession && pCSession->m_pISessionProperties)
{
pCDataSource = SOURCE_GETPARENT(pCSession, CDataSource);
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_SESSIONALL, IID_ISessionProperties, pCSession->m_pISessionProperties, pCDataSource ? pCDataSource->m_pIDBProperties : NULL);
}
return TRUE;
case IDM_COMMAND_SETPROPERTIES:
if(pCCommand && pCCommand->m_pICommandProperties)
{
pCDataSource = SOURCE_GETPARENT(pCCommand, CDataSource);
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_ROWSETALL, IID_ICommandProperties, pCCommand->m_pICommandProperties, pCDataSource ? pCDataSource->m_pIDBProperties : NULL);
}
return TRUE;
case IDM_COMMAND_CLEARCOMMAND:
if(pCCommand && pCSession && pCCommand->m_pIUnknown)
{
CWaitCursor waitCursor;
CComPtr<ICommand> spCommand;
//A little more difficult than ROWSET_CLEARPROPERTIES
//Since any properties set on a command object are set,
//the only way to remove them is to either try and set them
//to the opposite value, or create a new command object...
//Create a new command
//And then re-create our object with the new command (with no properties)...
pCSession->CreateCommand(NULL, IID_ICommand, (IUnknown**)&spCommand);
pCCommand->CreateObject(pCSession, IID_ICommand, spCommand);
}
return TRUE;
///////////////////////////////////////////////////////////////////
// IConvertType
//
///////////////////////////////////////////////////////////////////
case IDM_ICONVERTTYPE_CANCONVERT:
if(pCDataAccess->m_pIConvertType)
DisplayDialog(IDD_CANCONVERT, hWnd, CanConvertProc, pCDataAccess, iID);
return TRUE;
///////////////////////////////////////////////////////////////////
// IAccessor
//
///////////////////////////////////////////////////////////////////
case IDM_IACCESSOR_GETBINDINGS:
if(pCDataAccess && pCDataAccess->m_pIAccessor)
DisplayDialog(IDD_GETLISTVIEW, hWnd, GetBindingsProc, pCDataAccess, iID);
return TRUE;
case IDM_IACCESSOR_ADDREFACCESSOR:
if(pCDataAccess && pCDataAccess->m_pIAccessor)
{
CWaitCursor waitCursor;
//IAccessor::AddRefAccessor
pCDataAccess->AddRefAccessor(pCDataAccess->m_hAccessor);
}
return TRUE;
case IDM_IACCESSOR_CREATEACCESSOR:
if(pCDataAccess && pCDataAccess->m_pIAccessor)
DisplayDialog(IDD_CREATEACCESSOR, hWnd, CreateAccessorProc, pCDataAccess, iID);
return TRUE;
case IDM_IACCESSOR_RELEASEACCESSOR:
if(pCDataAccess && pCDataAccess->m_pIAccessor)
pCDataAccess->ReleaseAccessor(&pCDataAccess->m_hAccessor, TRUE/*fReleaseAlways*/);
return TRUE;
//ITableDefinition
case IDM_TABLE_CREATETABLE:
if(pCSession && pCSession->m_pITableDefinition)
DisplayDialog(IDD_CREATETABLE, hWnd, CreateTableProc, pCSession, iID);
return TRUE;
case IDM_TABLE_ADDCOLUMN:
if(pCSession && pCSession->m_pITableDefinition)
DisplayDialog(IDD_ADDCOLUMN, hWnd, AddColumnProc, pCSession, iID);
return TRUE;
case IDM_TABLE_DROPCOLUMN:
if(pCSession && pCSession->m_pITableDefinition)
DisplayDialog(IDD_DROPCOLUMN, hWnd, DropColumnProc, pCSession, iID);
return TRUE;
case IDM_TABLE_DROPTABLE:
if(pCSession && pCSession->m_pITableDefinition)
DisplayDialog(IDD_DROPTABLE, hWnd, DropTableProc, pCSession, iID);
return TRUE;
//ITableDefinitionWithConstraints
case IDM_TABLE_CREATETABLEWITHCONSTRAINTS:
// if(pCSession && pCSession->m_pITableDefinitionWithConstraints)
// DisplayDialog(IDD_CREATETABLE, hWnd, CreateTableProc, pCSession, iID);
return TRUE;
case IDM_TABLE_ADDCONSTRAINT:
if(pCSession && pCSession->m_pITableDefinitionWithConstraints)
{
CWaitCursor waitCursor;
DBORDINAL cConsDesc = 1;
DBCONSTRAINTDESC ConsDesc;
DBCONSTRAINTDESC* rgConsDesc = &ConsDesc;
DBID TableID;
WCHAR *pwszTableName = NULL;
CConstraintDlg ConsDlg(pCMainWindow);
memset(&ConsDesc, 0, sizeof(DBCONSTRAINTDESC));
if (S_OK == ConsDlg.SetConstraintAndTable(hWnd, &ConsDesc, &pwszTableName))
{
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = pwszTableName;
XTEST(hr = pCSession->m_pITableDefinitionWithConstraints->AddConstraint(&TableID, &ConsDesc));
TRACE_METHOD(hr, L"ITableDefinitionWithConstraints::AddConstraint(&%s, \"%p\")", pwszTableName, &ConsDesc);
}
SAFE_FREE(pwszTableName);
FreeConstraintDesc(&cConsDesc, &rgConsDesc, FALSE);
}
return TRUE;
case IDM_TABLE_DROPCONSTRAINT:
if(pCSession && pCSession->m_pITableDefinitionWithConstraints)
DisplayDialog(IDD_DROPCONSTRAINT, hWnd, DropConstraintProc, pCSession, iID);
return TRUE;
//IIndexDefinition
case IDM_INDEX_CREATEINDEX:
if(pCSession && pCSession->m_pIIndexDefinition)
DisplayDialog(IDD_CREATEINDEX, hWnd, CreateIndexProc, pCSession, iID);
return TRUE;
case IDM_INDEX_DROPINDEX:
if(pCSession && pCSession->m_pIIndexDefinition)
DisplayDialog(IDD_DROPINDEX, hWnd, DropIndexProc, pCSession, iID);
return TRUE;
// IAlterIndex
case IDM_INDEX_ALTERINDEX:
if(pCSession && pCSession->m_pIAlterIndex)
{
CWaitCursor waitCursor;
CAlterIndexDlg AlterIndexDlg(this);
DBID *pTableID = NULL;
DBID *pIndexID = NULL;
DBID *pNewIndexID = NULL;
BOOL fUseIndexProps = FALSE;
ULONG cPropSets = 0;
DBPROPSET* rgPropSets = NULL;
// get index updates
if (S_OK == AlterIndexDlg.AlterIndex(hWnd, &pTableID, &pIndexID, &pNewIndexID,
&fUseIndexProps))
{
//alter the index
if (fUseIndexProps)
{
cPropSets = AlterIndexDlg.m_CPropSets.GetCount();
rgPropSets = AlterIndexDlg.m_CPropSets.GetPropSets();
}
XTEST(hr = pCSession->m_pIAlterIndex->AlterIndex(pTableID, pIndexID,
pNewIndexID, cPropSets, rgPropSets));
TRACE_METHOD(hr, L"IAlterIndex::AlterIndex(&%p, &%p, &%p, %d, %p)",
pTableID, pIndexID, pNewIndexID, cPropSets, rgPropSets);
}
DBIDFree(pTableID);
SAFE_FREE(pTableID);
DBIDFree(pIndexID);
SAFE_FREE(pIndexID);
DBIDFree(pNewIndexID);
SAFE_FREE(pNewIndexID);
}
return TRUE;
// IAlterTable
case IDM_TABLE_ALTERTABLE:
if(pCSession && pCSession->m_pIAlterTable)
{
CWaitCursor waitCursor;
CAlterTableDlg AlterTableDlg(this);
ULONG cPropSets = 0;
DBPROPSET* rgPropSets = NULL;
// get table updates
if (S_OK == AlterTableDlg.AlterTable(hWnd))
{
//alter table
if (AlterTableDlg.m_fUseTableProps)
{
cPropSets = AlterTableDlg.m_CPropSets.GetCount();
rgPropSets = AlterTableDlg.m_CPropSets.GetPropSets();
}
XTEST(hr = pCSession->m_pIAlterTable->AlterTable(
AlterTableDlg.m_pTableID,
AlterTableDlg.m_pNewTableID,
cPropSets,
rgPropSets));
TRACE_METHOD(hr, L"IAlterTable::AlterTable(&%p, &%p, %d, %p)",
AlterTableDlg.m_pTableID, AlterTableDlg.m_pNewTableID, cPropSets, rgPropSets);
}
}
return TRUE;
case IDM_TABLE_ALTERCOLUMN:
if(pCSession && pCSession->m_pIAlterTable)
{
CWaitCursor waitCursor;
CAlterColumnDlg AlterColumnDlg(this);
// get table updates
if (S_OK == AlterColumnDlg.AlterColumn(hWnd))
{
//alter column
XTEST(hr = pCSession->m_pIAlterTable->AlterColumn(
AlterColumnDlg.m_pTableID,
AlterColumnDlg.m_pColumnID,
AlterColumnDlg.m_dwColFlags,
&AlterColumnDlg.m_ColDesc));
TRACE_METHOD(hr, L"IAlterTable::AlterColumn(&%p, &%p, %d, %p)",
AlterColumnDlg.m_pTableID, AlterColumnDlg.m_pColumnID,
AlterColumnDlg.m_dwColFlags, &AlterColumnDlg.m_ColDesc);
}
}
return TRUE;
//IRowsetIdentity
case IDM_IROWSETINDENTITY_ISSAMEROW:
if(pCRowset && pCRowset->m_pIRowsetIdentity)
{
CWaitCursor waitCursor;
//Obtain the First selected Row
INDEX iSelRow = m_pCDataGrid->GetSelectedRow(NULL, FALSE);
HROW hRow1 = m_pCDataGrid->GetItemParam(iSelRow);
//Obtain the Second selected Row
INDEX iSelRow2 = m_pCDataGrid->GetNextItem(iSelRow, LVNI_SELECTED);
HROW hRow2 = m_pCDataGrid->GetItemParam(iSelRow2 != LVM_ERR ? iSelRow2 : iSelRow);
//IRowsetIdentity::IsSameRow
XTEST(hr = pCRowset->m_pIRowsetIdentity->IsSameRow(hRow1, hRow2));
TRACE_METHOD(hr, L"IRowsetIdentity::IsSameRow(0x%p, 0x%p)", hRow1, hRow2);
}
return TRUE;
//IRowsetScroll
case IDM_IROWSETSCROLL_GETAPPROXIMATEPOSITION:
if(pCRowset && pCRowset->m_pIRowsetScroll)
{
CWaitCursor waitCursor;
DBBKMARK cbBookmark = 0;
BYTE* pBookmark = NULL;
DBCOUNTITEM ulPosition = 0;
DBCOUNTITEM cRows = 0;
HROW hRow = NULL;
//Obtain the bookmark for the selected row...
if(m_pCDataGrid->GetSelectedRow(&hRow, FALSE)!=LVM_ERR)
hr = pCRowset->GetBookmark(hRow, &cbBookmark, &pBookmark);
//IRowsetScroll::GetApproximatePosition
XTEST(hr = pCRowset->m_pIRowsetScroll->GetApproximatePosition(hChapter, cbBookmark, pBookmark, &ulPosition, &cRows));
TRACE_METHOD(hr, L"IRowsetScroll::GetApproximatePosition(0x%p, %lu, 0x%p, &%lu, &%lu)", hChapter, cbBookmark, pBookmark, ulPosition, cRows);
//Cleanup
SAFE_FREE(pBookmark);
}
return TRUE;
//IRowsetLocate
case IDM_IROWSETLOCATE_COMPARE:
if(pCRowset && pCRowset->m_pIRowsetLocate)
{
CWaitCursor waitCursor;
HROW rghRows[2] = {NULL, NULL};
DBBKMARK rgcbBookmarks[2] = {0, 0};
const BYTE* rgpBookmarks[2] = {NULL, NULL};
DBCOMPARE dwComparison = 0;
//Obtain the First selected Row
INDEX iSelRow = m_pCDataGrid->GetSelectedRow(NULL, FALSE);
rghRows[0] = m_pCDataGrid->GetItemParam(iSelRow);
//Obtain the Second selected Row
INDEX iSelRow2 = m_pCDataGrid->GetNextItem(iSelRow, LVNI_SELECTED);
rghRows[1] = m_pCDataGrid->GetItemParam(iSelRow2 != LVM_ERR ? iSelRow2 : iSelRow);
//Obtain the bookmark(s) for the selected row(s)...
if(iSelRow!=LVM_ERR)
{
hr = pCRowset->GetBookmark(rghRows[0], &rgcbBookmarks[0], (BYTE**)&rgpBookmarks[0]);
hr = pCRowset->GetBookmark(rghRows[1], &rgcbBookmarks[1], (BYTE**)&rgpBookmarks[1]);
}
//IRowsetLocate::Compare
XTEST(hr = pCRowset->m_pIRowsetLocate->Compare(hChapter, rgcbBookmarks[0], rgpBookmarks[0], rgcbBookmarks[1], rgpBookmarks[1], &dwComparison));
TRACE_METHOD(hr, L"IRowsetLocate::Compare(0x%p, %Iu, 0x%p, %Iu, 0x%p, &%d)", hChapter, rgcbBookmarks[0], rgpBookmarks[0], rgcbBookmarks[1], rgpBookmarks[1], dwComparison);
//Cleanup
CoTaskMemFree((void*)rgpBookmarks[0]);
CoTaskMemFree((void*)rgpBookmarks[1]);
}
return TRUE;
case IDM_IROWSETLOCATE_HASH:
if(pCRowset && pCRowset->m_pIRowsetLocate)
{
CWaitCursor waitCursor;
INDEX cRows = 0;
HROW* rghRows = NULL;
DBBKMARK rgcbBookmarks[MAX_OPENROWS+1];
const BYTE* rgpBookmarks[MAX_OPENROWS+1];
DBHASHVALUE rgHashedValues[MAX_OPENROWS+1];
DBROWSTATUS rgBookmarkStatus[MAX_OPENROWS+1];
//Obtain all Selected Rows
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cRows, NULL, (LPARAM**)&rghRows);
cRows = min(cRows, MAX_OPENROWS);
INDEX i;
//Obtain the bookmark(s) for the selected row(s)...
for(i=0; i<cRows; i++)
{
hr = pCRowset->GetBookmark(rghRows[i], &rgcbBookmarks[i], (BYTE**)&rgpBookmarks[i]);
}
//IRowsetLocate::Hash
XTEST(hr = pCRowset->m_pIRowsetLocate->Hash(hChapter, cRows, rgcbBookmarks, rgpBookmarks, rgHashedValues, rgBookmarkStatus));
TRACE_METHOD(hr, L"IRowsetLocate::Hash(0x%p, %Iu, 0x%p, 0x%p, 0x%p, 0x%p)", hChapter, cRows, rgcbBookmarks, rgpBookmarks, rgHashedValues, rgBookmarkStatus);
//Cleanup
SAFE_FREE(rghRows);
for(i=0; i<cRows; i++)
CoTaskMemFree((void*)rgpBookmarks[i]);
}
return TRUE;
case IDM_IROWSETLOCATE_GETROWSBYBOOKMARK:
if(pCRowset && pCRowset->m_pIRowsetLocate)
{
CWaitCursor waitCursor;
INDEX cSelItems = 0;
INDEX* rgSelItems = 0;
HROW* rghRows = NULL;
DBBKMARK rgcbBookmarks[MAX_OPENROWS+1];
const BYTE* rgpBookmarks[MAX_OPENROWS+1];
DBROWSTATUS rgRowStatus[MAX_OPENROWS+1];
//Obtain all Selected Rows
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cSelItems, &rgSelItems, (LPARAM**)&rghRows);
cSelItems = min(cSelItems, MAX_OPENROWS);
INDEX i;
//Obtain the bookmark(s) for the selected row(s)...
for(i=0; i<cSelItems; i++)
hr = pCRowset->GetBookmark(rghRows[i], &rgcbBookmarks[i], (BYTE**)&rgpBookmarks[i]);
//Release previously fetched rows, (if user requested)
hr = m_pCDataGrid->ReleaseHeldRows();
//IRowsetLocate::GetRowsByBookmark
XTEST(hr = pCRowset->m_pIRowsetLocate->GetRowsByBookmark(hChapter, cSelItems, rgcbBookmarks, rgpBookmarks, rghRows, rgRowStatus));
TRACE_METHOD(hr, L"IRowsetLocate::GetRowsByBookmark(0x%p, %Iu, 0x%p, 0x%p, 0x%p, 0x%p)", hChapter, cSelItems, rgcbBookmarks, rgpBookmarks, rghRows, rgRowStatus);
//Display the data rows retrieved...
for(i=0; i<cSelItems; i++)
{
//Some rows might have not been successfully retrived,
//According to the spec, this is denoted with a NULL hRow
if(rghRows[i])
m_pCDataGrid->DisplayData(rghRows[i], rgSelItems[i]);
}
//Cleanup
for(i=0; i<cSelItems; i++)
CoTaskMemFree((void*)rgpBookmarks[i]);
SAFE_FREE(rghRows);
SAFE_FREE(rgSelItems);
}
return TRUE;
case IDM_IROWSETBOOKMARK_POSITIONONBOOKMARK:
if(pCRowset && pCRowset->m_pIRowsetBookmark)
{
CWaitCursor waitCursor;
HROW hRow = NULL;
DBBKMARK cbBookmark = 0;
const BYTE* pBookmark = NULL;
//Obtain the first selected row...
INDEX iSelRow = m_pCDataGrid->GetSelectedRow(&hRow, FALSE);
if(iSelRow != LVM_ERR && hRow)
{
//Obtain the bookmark
if(SUCCEEDED(hr = pCRowset->GetBookmark(hRow, &cbBookmark, (BYTE**)&pBookmark)))
{
//IRowsetBookmark::PositionOnBookmark
XTEST(hr = pCRowset->m_pIRowsetBookmark->PositionOnBookmark(hChapter, cbBookmark, pBookmark));
TRACE_METHOD(hr, L"IRowsetBookmark::PositionOnBookmark(0x%p, %Iu, 0x%p)", hChapter, cbBookmark, pBookmark);
//Move the NFP indicator...
if(SUCCEEDED(hr))
{
//Display the new Fetch Position indicator...
m_pCDataGrid->DisplayFetchPosition(iSelRow, TRUE/*fLastFetchForward*/);
}
}
}
//Cleanup
SAFE_FREE(pBookmark);
}
return TRUE;
case IDM_IROWSETLOCATE_GETROWSAT:
if(pCRowset && pCRowset->m_pIRowsetLocate)
DisplayDialog(IDD_GETNEXTROWS, hWnd, GetNextRowsProc, pCRowset, iID);
return TRUE;
//IRowsetFind
case IDM_IROWSETFIND_FINDNEXTROW:
if(pCRowset && pCRowset->m_pIRowsetFind)
DisplayDialog(IDD_FINDNEXTROW, hWnd, FindNextRowProc, pCRowset, iID);
return TRUE;
//CommandWithParameters
case IDM_MAPPARAMETERNAMES:
return TRUE;
case IDM_SETPARAMETERINFO:
if(pCCommand && pCCommand->m_pICommandWithParameters)
DisplayDialog(IDD_SETPARAMETERINFO, hWnd, SetParameterInfoProc, pCCommand, iID);
return TRUE;
case IDM_GETPARAMETERINFO:
if(pCCommand && pCCommand->m_pICommandWithParameters)
DisplayDialog(IDD_GETLISTVIEW, hWnd, GetParameterInfoProc, pCCommand, iID);
return TRUE;
case IDM_IPERSIST_GETCLASSID:
if(pCDataSource && pCDataSource->m_pIPersist)
{
CLSID clsid;
pCDataSource->GetClassID(&clsid);
}
return TRUE;
case IDM_IPERSISTFILE_LOAD:
if(pCDataSource && pCDataSource->m_pIPersistFile)
{
WCHAR wszBuffer[MAX_QUERY_LEN] = {0};
//Display Common Dialog to obtain File To Load...
hr = BrowseOpenFileName(GetAppLite()->m_hInstance, hWnd, L"IPersistFile::Load", wszBuffer, MAX_QUERY_LEN, NULL, L"DataSource Files (.dsn;.kag;.sav)\0*.dsn;*.kag;*.sav;\0DataBase Files (.mdb;.db;.dbf)\0*.mdb;*.db;*.dbf;\0Program Files (.xls;.clb)\0*.xls;*.clb;\0Text Files (.txt;.csv)\0*.txt;*.csv\0All Files (*.*)\0*.*\0\0");
if(SUCCEEDED(hr))
{
CWaitCursor waitCursor;
//IPersistFile::Load
XTEST(hr = pCDataSource->m_pIPersistFile->Load(wszBuffer, STGM_READ));
TRACE_METHOD(hr, L"IPersistFile::Load(\"%s\", STGM_READ)", wszBuffer);
}
}
return TRUE;
case IDM_IPERSISTFILE_SAVE:
if(pCDataSource && pCDataSource->m_pIPersistFile)
{
WCHAR wszBuffer[MAX_QUERY_LEN] = {0};
//Display Common Dialog to obtain File To Save...
hr = BrowseSaveFileName(GetAppLite()->m_hInstance, hWnd, L"IPersistFile::Save", wszBuffer, MAX_QUERY_LEN, NULL, L"DataSource Files (.dsn;.kag;.sav)\0*.dsn;*.kag;*.sav;\0DataBase Files (.mdb;.db;.dbf)\0*.mdb;*.db;*.dbf;\0Program Files (.xls;.clb)\0*.xls;*.clb;\0Text Files (.txt;.csv)\0*.txt;*.csv\0All Files (*.*)\0*.*\0\0");
if(SUCCEEDED(hr))
{
CWaitCursor waitCursor;
//IPersistFile::Save
XTEST(hr = pCDataSource->m_pIPersistFile->Save(wszBuffer, TRUE));
TRACE_METHOD(hr, L"IPersistFile::Save(\"%s\", TRUE)", wszBuffer);
}
}
return TRUE;
case IDM_IPERSISTFILE_SAVECOMPLETED:
if(pCDataSource && pCDataSource->m_pIPersistFile)
{
WCHAR wszBuffer[MAX_QUERY_LEN] = {0};
//Display Common Dialog to obtain File To Save...
hr = BrowseSaveFileName(GetAppLite()->m_hInstance, hWnd, L"IPersistFile::SaveCompleted", wszBuffer, MAX_QUERY_LEN, NULL, L"DataSource Files (.dsn;.kag;.sav)\0*.dsn;*.kag;*.sav;\0DataBase Files (.mdb;.db;.dbf)\0*.mdb;*.db;*.dbf;\0Program Files (.xls;.clb)\0*.xls;*.clb;\0Text Files (.txt;.csv)\0*.txt;*.csv\0All Files (*.*)\0*.*\0\0");
if(SUCCEEDED(hr))
{
CWaitCursor waitCursor;
//IPersistFile::Save
XTEST(hr = pCDataSource->m_pIPersistFile->SaveCompleted(wszBuffer));
TRACE_METHOD(hr, L"IPersistFile::SaveCompleted(\"%s\")", wszBuffer);
}
}
return TRUE;
case IDM_IPERSISTFILE_GETCURFILE:
if(pCDataSource && pCDataSource->m_pIPersistFile)
{
CWaitCursor waitCursor;
WCHAR* pwszFileName = NULL;
//IPersistFile::GetCurFile
XTEST(hr = pCDataSource->m_pIPersistFile->GetCurFile(&pwszFileName));
TRACE_METHOD(hr, L"IPersistFile::GetCurFile(\"%s\")", pwszFileName);
}
return TRUE;
case IDM_IPERSISTFILE_ISDIRTY:
if(pCDataSource && pCDataSource->m_pIPersistFile)
{
CWaitCursor waitCursor;
//IPersistFile::IsDirty
XTEST(hr = pCDataSource->m_pIPersistFile->IsDirty());
TRACE_METHOD(hr, L"IPersistFile::IsDirty()");
}
return TRUE;
case IDM_GETDATA:
case IDM_IROWSETLOCATE_GETDATA:
case IDM_IROWSETSCROLL_GETDATA:
if(pCRowset && pCRowset->m_pIRowset)
{
INDEX cRows = 0;
INDEX* rgItems = NULL;
HROW* rghRows = NULL;
//Find all Selected Rows
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
if(cRows == 0)
{
wMessageBox(GetFocus(), MB_TASKMODAL | MB_ICONHAND | MB_OK | MB_DEFBUTTON1,
wsz_ERROR, L"Must first select a row...");
}
DBPROPID dwSourceID = DBPROP_IRowset;
if(iID == IDM_IROWSETLOCATE_GETDATA)
dwSourceID = DBPROP_IRowsetLocate;
if(iID == IDM_IROWSETSCROLL_GETDATA)
dwSourceID = DBPROP_IRowsetScroll;
CWaitCursor waitCursor;
//Display all rows...
for(INDEX i=0; i<cRows; i++)
{
//Display the Data for this row...
m_pCDataGrid->DisplayData(rghRows[i], rgItems[i], dwSourceID, true/*fAlways*/);
}
SAFE_FREE(rgItems);
SAFE_FREE(rghRows);
}
return TRUE;
case IDM_REFRESH:
if(pCRowset && pCRowset->m_pIRowset)
{
CWaitCursor waitCursor;
//Similar to GetData except for all rows
if(SUCCEEDED(m_pCDataGrid->RestartPosition()))
m_pCDataGrid->RefreshData();
}
return TRUE;
case IDM_GETVISIBLEDATA:
if(pCRowset && pCRowset->m_pIRowsetResynch)
{
INDEX cRows = 0;
INDEX* rgItems = NULL;
HROW* rghRows = NULL;
//Find all Selected Rows
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
if(cRows == 0)
{
wMessageBox(GetFocus(), MB_TASKMODAL | MB_ICONHAND | MB_OK | MB_DEFBUTTON1,
wsz_ERROR, L"Must first select a row...");
}
CWaitCursor waitCursor;
for(INDEX i=0; i<cRows; i++)
{
//Display the Data for this row...
m_pCDataGrid->DisplayData(rghRows[i], rgItems[i], DBPROP_IRowsetResynch, true/*fAlways*/);
}
SAFE_FREE(rgItems);
SAFE_FREE(rghRows);
}
return TRUE;
case IDM_RESYNCHROWS:
if(pCRowset && pCRowset->m_pIRowsetResynch)
{
CWaitCursor waitCursor;
INDEX cRows = 0;
HROW* rghRows = NULL;
DBCOUNTITEM cRowsResynched = 0;
HROW* rghRowsResynched = 0;
DBROWSTATUS* rgRowStatus = NULL;
INDEX* rgItems = NULL;
//Get all selected Rows
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
//IRowsetResynch::ResynchRows
XTEST(hr = pCRowset->m_pIRowsetResynch->ResynchRows(cRows, rghRows, &cRowsResynched, &rghRowsResynched, &rgRowStatus));
DisplayRowErrors(hr, cRowsResynched, rghRowsResynched, rgRowStatus);
TRACE_METHOD(hr, L"IRowsetResynch::ResynchRows(%Iu, 0x%p, &%Iu, &0x%p, &0x%p)", cRows, rghRows, cRowsResynched, rghRowsResynched, rgRowStatus);
//Now GetData for all SelectedRows (a nice helper)
//We won't worry about updating the case for (0,NULL), its not worth
//trying to match the rhgRows returned to the correct hRows. Worse case
//is the user has to call GetData for one or all rows...
for(INDEX i=0; i<cRows; i++)
{
//Display the Data for this row...
m_pCDataGrid->DisplayData(rghRows[i], rgItems[i]);
}
//Cleanup
SAFE_FREE(rghRows);
SAFE_FREE(rghRowsResynched);
SAFE_FREE(rgRowStatus);
SAFE_FREE(rgItems);
}
return TRUE;
case IDM_GETLASTVISIBLEDATA:
if(pCRowset && pCRowset->m_pIRowsetRefresh)
{
CWaitCursor waitCursor;
INDEX cRows = 0;
INDEX* rgItems = NULL;
HROW* rghRows = NULL;
//Find all Selected Rows
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
if(cRows == 0)
{
wMessageBox(GetFocus(), MB_TASKMODAL | MB_ICONHAND | MB_OK | MB_DEFBUTTON1,
wsz_ERROR, L"Must first select a row...");
}
for(INDEX i=0; i<cRows; i++)
{
//Display the Data for this row...
m_pCDataGrid->DisplayData(rghRows[i], rgItems[i], DBPROP_IRowsetRefresh, true/*fAlways*/);
}
SAFE_FREE(rgItems);
SAFE_FREE(rghRows);
}
return TRUE;
case IDM_REFRESHVISIBLEDATA:
if(pCRowset && pCRowset->m_pIRowsetRefresh)
{
CWaitCursor waitCursor;
INDEX i,cRows = 0;
HROW* rghRows = NULL;
BOOL fOverWrite = FALSE;
DBCOUNTITEM cRowsRefreshed = 0;
HROW* rghRowsRefreshed = 0;
DBROWSTATUS* rgRowStatus = NULL;
INDEX* rgItems = NULL;
//Get all selected Rows
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
//IRowsetRefresh::RefreshVisibleData
XTEST(hr = pCRowset->m_pIRowsetRefresh->RefreshVisibleData(hChapter, cRows, rghRows, fOverWrite, &cRowsRefreshed, &rghRowsRefreshed, &rgRowStatus));
DisplayRowErrors(hr, cRowsRefreshed, rghRowsRefreshed, rgRowStatus);
TRACE_METHOD(hr, L"IRowsetRefresh::RefreshVisibleData(0x%p, %Iu, 0x%p, %d, &%Iu, &0x%p, &0x%p)", hChapter, cRows, rghRows, fOverWrite, cRowsRefreshed, rghRowsRefreshed, rgRowStatus);
//Now GetData for all SelectedRows (a nice helper)
//We won't worry about updating the case for (0,NULL), its not worth
//trying to match the rhgRows returned to the correct hRows. Worse case
//is the user has to call GetData for one or all rows...
for(i=0; i<cRows; i++)
{
//Display the Data for this row...
m_pCDataGrid->DisplayData(rghRows[i], rgItems[i]);
}
//Cleanup
SAFE_FREE(rghRows);
SAFE_FREE(rghRowsRefreshed);
SAFE_FREE(rgRowStatus);
SAFE_FREE(rgItems);
}
return TRUE;
case IDM_GETORIGINALDATA:
if(pCRowset && pCRowset->m_pIRowsetUpdate)
{
CWaitCursor waitCursor;
INDEX cRows = 0;
INDEX* rgItems = NULL;
HROW* rghRows = NULL;
//Find all Selected Rows
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
if(cRows == 0)
{
wMessageBox(GetFocus(), MB_TASKMODAL | MB_ICONHAND | MB_OK | MB_DEFBUTTON1,
wsz_ERROR, L"Must first select a row...");
}
for(INDEX i=0; i<cRows; i++)
{
//Display the Data for this row...
m_pCDataGrid->DisplayData(rghRows[i], rgItems[i], DBPROP_IRowsetUpdate, true/*fAlways*/);
}
SAFE_FREE(rgItems);
SAFE_FREE(rghRows);
}
return TRUE;
case IDM_GETPENDINGROWS:
if(pCRowset && pCRowset->m_pIRowsetUpdate)
{
CWaitCursor waitCursor;
DBCOUNTITEM cPendingRows = 0;
HROW* rgPendingRows = 0;
DBPENDINGSTATUS* rgPendingStatus = NULL;
//IRowsetUpdate::GetPendingStatus
XTEST(hr = pCRowset->m_pIRowsetUpdate->GetPendingRows(hChapter, DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_CHANGED | DBPENDINGSTATUS_DELETED, &cPendingRows, &rgPendingRows, &rgPendingStatus));
TRACE_METHOD(hr, L"IRowsetUpdate::GetPendingRows(0x%p, DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_CHANGED | DBPENDINGSTATUS_DELETED, &%lu, &0x%p, &0x%p)", hChapter, cPendingRows, rgPendingRows, rgPendingStatus);
//Cleanup
SAFE_FREE(rgPendingRows);
SAFE_FREE(rgPendingStatus);
}
return TRUE;
case IDM_GETROWSTATUS:
if(pCRowset && pCRowset->m_pIRowsetUpdate)
{
CWaitCursor waitCursor;
//Find the SelectedRow
HROW hRow;
if(m_pCDataGrid->GetSelectedRow(&hRow, FALSE) != LVM_ERR)
{
DBPENDINGSTATUS dwPendingStatus = 0;
//IRowsetUpdate::GetRowStatus
XTEST(hr = pCRowset->m_pIRowsetUpdate->GetRowStatus(hChapter, 1, &hRow, &dwPendingStatus));
TRACE_METHOD(hr, L"IRowsetUpdate::GetRowStatus(0x%p, %lu, &0x%p, &0x%p)", hChapter, 1, hRow, dwPendingStatus);
}
}
return TRUE;
case IDM_UNDO: //Cancel the chagnes that were made.
if(pCRowset && pCRowset->m_pIRowsetUpdate)
{
CWaitCursor waitCursor;
UndoChanges();
}
return TRUE;
case IDM_UPDATE: //Update the changes that were made.
if(pCRowset && pCRowset->m_pIRowsetUpdate)
{
CWaitCursor waitCursor;
UpdateChanges();
}
return TRUE;
//IServiceProvider
case IDM_ISERVICEPROVIDER:
if(pCDataSource && pCDataSource->m_pIServiceProvider)
{
//Display the Generic interface list...
CInterfaceDlg interfaceDlg(IDD_INTERFACE, L"IServiceProvider::QueryService", IID_ISpecifyPropertyPages);
if(interfaceDlg.DoModal(hWnd) == IDOK)
{
CWaitCursor waitCursor;
CComPtr<IUnknown> spUnknown;
XTEST(hr = pCDataSource->m_pIServiceProvider->QueryService(OLEDB_SVC_DSLPropertyPages, interfaceDlg.GetSelInterface(), (void**)&spUnknown));
TRACE_METHOD(hr, L"IServiceProvider::QueryService(OLEDB_SVC_DSLPropertyPages, %s, &0x%p)", GetInterfaceName(interfaceDlg.GetSelInterface()), spUnknown);
}
}
return TRUE;
};
return FALSE;
}
/////////////////////////////////////////////////////////////////
// CMDIChild::UpdateWndTitle
//
/////////////////////////////////////////////////////////////////
HRESULT CMDIChild::UpdateWndTitle()
{
//Default Info
CBase* pCBase = GetObject();
CDataSource* pCDataSource = (CDataSource*)GetObject(eCDataSource);
WCHAR* pwszProvider = NULL;
WCHAR* pwszDesc = NULL;
if(pCDataSource)
{
pwszProvider = pCDataSource->m_cstrProviderDesc && pCDataSource->m_cstrProviderDesc[0] ? pCDataSource->m_cstrProviderDesc : pCDataSource->m_cstrProviderName;
pwszDesc = pCDataSource->m_cstrDataSource && pCDataSource->m_cstrDataSource[0] ? pCDataSource->m_cstrDataSource : pCDataSource->m_cstrDBMS;
}
//Format text and output to window
wSendMessageFmt(
m_hWnd, WM_SETTEXT, 0, L"%s: %s %s%s%s",
pCBase ? pCBase->GetObjectName() : L"Unknown",
pwszProvider ? pwszProvider : L"",
pwszDesc && pwszDesc[0] ? L"(" : L"",
pwszDesc ? pwszDesc : L"",
pwszDesc && pwszDesc[0] ? L")" : L""
);
return S_OK;
}
////////////////////////////////////////////////////////////////
// CMDIChild::CreateEnumChild()
//
/////////////////////////////////////////////////////////////////
HRESULT CMDIChild::CreateEnumChild()
{
HRESULT hr = S_OK;
INDEX iSelRow = 0;
WCHAR wszBuffer[MAX_NAME_LEN+1];
CRowset* pCRowset = (CRowset*)GetObject(eCRowset);
CEnumerator* pCEnumerator = SOURCE_GETPARENT(pCRowset, CEnumerator);
if(pCRowset && pCEnumerator)
{
//If enumertor rowset, double-clicking on a row
//brings up the ParseName object in another window
ULONG iColumn = 1; //Skip RowHandle column
//Skip bookmark column...
if(pCRowset->m_Bindings.GetCount() && pCRowset->m_Bindings[0].iOrdinal==0)
iColumn = 2;
//Obtain SelectedRow
iSelRow = m_pCDataGrid->GetSelectedRow();
ASSERT(iSelRow != LVM_ERR);
//Obtain SourcesName and description from SelectedRow
ENUMINFO EnumInfo;
//SOURCES_NAME
m_pCDataGrid->GetItemText(iSelRow, iColumn+0, EnumInfo.wszName, MAX_NAME_LEN);
//SOURCES_PARSENAME
m_pCDataGrid->GetItemText(iSelRow, iColumn+1, EnumInfo.wszParseName, MAX_NAME_LEN);
//SOURCES_DESCRIPTION
m_pCDataGrid->GetItemText(iSelRow, iColumn+2, EnumInfo.wszDescription, MAX_NAME_LEN);
//SOURCES_TYPE
m_pCDataGrid->GetItemText(iSelRow, iColumn+3, wszBuffer, MAX_NAME_LEN);
EnumInfo.eType = (DBTYPE)wcstoul(wszBuffer, NULL, 10);
//SOURCES_ISPARENT
m_pCDataGrid->GetItemText(iSelRow, iColumn+4, wszBuffer, MAX_NAME_LEN);
EnumInfo.fIsParent = StringCompare(wszBuffer, L"True") ? TRUE : FALSE;
//Now Connect using the Connect Dialog
ASSERT(m_pCMainWindow);
ASSERT(m_pCMainWindow->m_pCFullConnect);
m_pCMainWindow->m_pCFullConnect->Display(m_hWnd, pCEnumerator, &EnumInfo);
}
return hr;
}
////////////////////////////////////////////////////////////////
// CMDIChild::DeleteSelectedRows
//
/////////////////////////////////////////////////////////////////
HRESULT CMDIChild::DeleteSelectedRows()
{
//Delete the Selected row in the ListView...
HRESULT hr = E_FAIL;
INDEX cRows = 0;
INDEX* rgItems = NULL;
HROW* rghRows = NULL;
DBROWSTATUS* rgRowStatus = NULL;
LONG dwSelection = IDYES;
CRowset* pCRowset = (CRowset*)GetObject(eCRowset);
//Is editing the Rowset allowed?
if(!pCRowset || !pCRowset->m_pIRowsetChange)
return E_FAIL;
//Find the Selected Items in the ListView
HCHAPTER hChapter = pCRowset->m_hChapter;
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
SAFE_ALLOC(rgRowStatus, DBROWSTATUS, cRows);
//Popup a MessageBox, Asking user if really wants to DeleteRow
if(cRows)
{
dwSelection = wMessageBox(GetFocus(), MB_TASKMODAL | MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1,
L"IRowsetChange::DeleteRows", L"Do you wish to delete the selected row(s)?");
}
if(dwSelection == IDYES)
{
//DeleteRows from Rowset
XTEST(hr = pCRowset->m_pIRowsetChange->DeleteRows(hChapter, cRows, rghRows, rgRowStatus));
DisplayRowErrors(hr, cRows, rghRows, rgRowStatus);
TESTC(TRACE_METHOD(hr, L"IRowsetChange::DeleteRows(0x%p, %Iu, 0x%p, 0x%p)", hChapter, cRows, rghRows, rgRowStatus));
//Loop over the deleted rows...
for(INDEX i=0; i<cRows; i++)
{
//We are "lazy" about updating the ListView. Since we are not
//sure wither the provider compacts or not after deleted rows,
//its easier and more correct to just display a "deleted" icon form
//of the row, rather than guessing...
//NOTE: We can go off the property DBPROP_REMOVEDELETED, but then we
//need to adjust the "cursor" position we store, forward/backward fetch, etc.
//Probably more useful and useable if its the same for all providers, rather
//than have it just "disappear" on some providers and others it remains...
//NOTE: Also this way allows you to call operations for deleted rows,
//otherwise you can't since its removed from the view...
// if(pCRowset->m_fRemoveDeleted)
// {
// //Remove the row from the listview - since the provider compacts
// m_pCDataGrid->DeleteItem(rgItems[i]);
// }
// else
// {
//Need to indicate row was deleted, but not compacted, (use "deleted" icon)
m_pCDataGrid->SetItemImage(rgItems[i], 0, IMAGE_DELETE);
// }
}
}
CLEANUP:
SAFE_FREE(rgRowStatus);
SAFE_FREE(rgItems);
SAFE_FREE(rghRows);
return hr;
}
/////////////////////////////////////////////////////////////////
// CMDIChild::ChangeSelectedRow
//
/////////////////////////////////////////////////////////////////
HRESULT CMDIChild::ChangeSelectedRow(CBase* pCSource, UINT idSource)
{
//If this is a row object - theres only 1 row...
if(SOURCE_GETOBJECT(pCSource, CRow))
{
m_pCDataGrid->m_iSelRow = 0;
}
else
{
//Otherwise find the Selected row
m_pCDataGrid->m_iSelRow = m_pCDataGrid->GetSelectedRow(NULL, TRUE);
if(m_pCDataGrid->m_iSelRow == LVM_ERR)
return E_INVALIDARG;
}
//Create Dialog box, passing the "this" pointer
//NOTE: m_pCSource and m_idSource are already setup...
DisplayDialog(IDD_ROWCHANGE, m_hWnd, RowChangeProc, pCSource, idSource);
return S_OK;
}
////////////////////////////////////////////////////////////////
// CMDIChild::InsertNewRow
//
/////////////////////////////////////////////////////////////////
HRESULT CMDIChild::InsertNewRow()
{
//Insert a new row into the ListView...
HRESULT hr = E_FAIL;
CRowset* pCRowset = (CRowset*)GetObject(eCRowset);
//Find the Selected Item in the ListView
m_pCDataGrid->m_iSelRow = m_pCDataGrid->GetSelectedRow(NULL, FALSE);
//Is editing the Rowset allowed?
if(!pCRowset || !pCRowset->m_pIRowsetChange)
return E_FAIL;
//Bring up the Insert Dialog box...
DisplayDialog(IDD_ROWCHANGE, m_hWnd, RowChangeProc, pCRowset, IDM_INSERTROW);
return hr;
}
////////////////////////////////////////////////////////////////
// CMDIChild::UndoChanges
//
/////////////////////////////////////////////////////////////////
HRESULT CMDIChild::UndoChanges()
{
//Undo all pending changes, (if in buffered mode)...
HRESULT hr = E_FAIL;
CRowset* pCRowset = (CRowset*)GetObject(eCRowset);
INDEX i,cRows = 0;
HROW* rghRows = NULL;
DBCOUNTITEM cRowsUndone = 0;
HROW* rghRowsUndone = NULL;
INDEX* rgItems = NULL;
DBROWSTATUS* rgRowStatus = NULL;
if(pCRowset && pCRowset->m_pIRowsetUpdate)
{
HCHAPTER hChapter = pCRowset->m_hChapter;
//Get all selected Rows
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
//IRowsetUpdate::Undo
XTEST(hr = pCRowset->m_pIRowsetUpdate->Undo(hChapter,cRows,rghRows,&cRowsUndone,&rghRowsUndone, &rgRowStatus));
DisplayRowErrors(hr, cRowsUndone, rghRowsUndone, rgRowStatus);
TESTC(TRACE_METHOD(hr, L"IRowsetUpdate::Undo(0x%p, %lu, 0x%p, &%lu, &0x%p, &0x%p)", hChapter, cRows, rghRows, cRowsUndone, rghRowsUndone, rgRowStatus));
//Now GetData for all SelectedRows (a nice helper)
//We won't worry about updating the case for (0,NULL), its not worth
//trying to match the rhgRows returned to the correct hRows. Worse case
//is the user has to call GetData for one or all rows...
for(i=0; i<cRows; i++)
{
//Need to indicate row was updated, use normal icon
m_pCDataGrid->SetItemImage(rgItems[i], 0, IMAGE_NORMAL);
//Display the Data...
hr = m_pCDataGrid->DisplayData(rghRows[i], rgItems[i]);
}
}
CLEANUP:
SAFE_FREE(rghRows);
SAFE_FREE(rghRowsUndone);
SAFE_FREE(rgRowStatus);
SAFE_FREE(rgItems);
return hr;
}
////////////////////////////////////////////////////////////////
// CMDIChild::UpdateChanges
//
/////////////////////////////////////////////////////////////////
HRESULT CMDIChild::UpdateChanges()
{
//Update all pending changes, (if in buffered mode)...
HRESULT hr = E_FAIL;
INDEX i,cRows = 0;
HROW* rghRows = NULL;
DBCOUNTITEM cRowsUpdated = 0;
HROW* rghRowsUpdated = NULL;
DBROWSTATUS* rgRowStatus = NULL;
INDEX* rgItems = NULL;
CRowset* pCRowset = (CRowset*)GetObject(eCRowset);
if(pCRowset && pCRowset->m_pIRowsetUpdate)
{
HCHAPTER hChapter = pCRowset->m_hChapter;
//Get all selected Rows
LV_GetSelItems(m_pCDataGrid->m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
//IRowsetUpdate::Update
XTEST(hr = pCRowset->m_pIRowsetUpdate->Update(hChapter,cRows,rghRows,&cRowsUpdated,&rghRowsUpdated,&rgRowStatus));
DisplayRowErrors(hr, cRowsUpdated, rghRowsUpdated, rgRowStatus);
TESTC(TRACE_METHOD(hr, L"IRowsetUpdate::Update(0x%p, %lu, 0x%p, &%lu, &0x%p, &0x%p)", hChapter, cRows, rghRows, cRowsUpdated, rghRowsUpdated, rgRowStatus));
//Now GetData for all SelectedRows (a nice helper)
//We won't worry about updating the case for (0,NULL), its not worth
//trying to match the rhgRows returned to the correct hRows. Worse case
//is the user has to call GetData for one or all rows...
for(i=0; i<cRows; i++)
{
//Need to indicate row was updated, use normal icon
m_pCDataGrid->SetItemImage(rgItems[i], 0, IMAGE_NORMAL);
//Display the Data...
hr = m_pCDataGrid->DisplayData(rghRows[i], rgItems[i]);
}
}
CLEANUP:
SAFE_FREE(rghRows);
SAFE_FREE(rghRowsUpdated);
SAFE_FREE(rgRowStatus);
SAFE_FREE(rgItems);
return hr;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetListViewValues
//
/////////////////////////////////////////////////////////////////
HRESULT CMDIChild::GetListViewValues(HWND hWndNames, HWND hWndValues, CDataAccess* pCDataAccess, CBindings& rBindings, void* pData)
{
ASSERT(hWndNames);
ASSERT(hWndValues);
ASSERT(pCDataAccess);
HRESULT hr = S_OK;
//Obtain the values from a specified ListView
//And place them into our pData structure according to our bindings...
//this method is mainly used for InsertRow and SetData operations...
WCHAR wszBuffer[MAX_COL_SIZE+1] = {0};
DBSTATUS dbStatus = DBSTATUS_S_OK;
DBTYPE wBackendType = DBTYPE_EMPTY;
//Loop through all Columns
for(ULONG i=0; i<rBindings.GetCount(); i++)
{
//Get the Status from the 'insert' ListView
LV_GetItemText(hWndNames, i, 2, wszBuffer, MAX_COL_SIZE);
dbStatus = GetStatusValue(wszBuffer);
//Get the Backend Type (sotred as the item data of the value)
wBackendType = (DBTYPE)LV_GetItemParam(hWndValues, i, 0);
//Get the Item from the 'insert' ListView
LV_GetItemText(hWndValues, i, 0, wszBuffer, MAX_COL_SIZE);
//Get the Image and Param
BOOL bChecked = LV_GetItemState(hWndNames, i, LVIS_STATEIMAGEMASK) & INDEXTOSTATEIMAGEMASK(STATE_CHECKED);
if(bChecked)
{
//Set the ColumnData in our pData buffer
TESTC(hr = pCDataAccess->SetColumnData(&rBindings[i], pData, dbStatus, wcslen(wszBuffer), wszBuffer, CONV_NONE, wBackendType));
//Reset the Item in the ListView in case it got truncated
LV_SetItemText(hWndValues, i, 0, wszBuffer);
}
else
{
//Mark this status as skipped (ignore)
//This allows us to not have to realloc a smaller subset of selected
//columns, and also allows us to be able to reuse the hAccessor
if(STATUS_IS_BOUND(rBindings[i]))
BINDING_STATUS(rBindings[i], pData) = DBSTATUS_S_IGNORE;
}
}
CLEANUP:
return hr;
}
////////////////////////////////////////////////////////////////
// CMDIChild::RowChangeProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::RowChangeProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL bBeginEdit = FALSE;
static BOOL s_bClearAll = TRUE;
static CListViewLite s_listNames;
static CListViewLite s_listValue;
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
bBeginEdit = FALSE;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
DWORD dwConvFlags = pThis->GetOptions()->m_dwConvFlags;
HRESULT hr = S_OK;
WCHAR wszBuffer[MAX_COL_SIZE+1];
DBCOUNTITEM iBind = 0;
DBLENGTH dbLength = 0;
DBSTATUS dbStatus = DBSTATUS_S_OK;//DBSTATUS_S_ISNULL;
DBTYPE wSubType = 0;
//We need to bring up a 2 ListViews.
//left - has column names,
//right - is blank for entering data for the corrsponding column
//Setup column headers
s_listNames.CreateIndirect(hWnd, IDL_NAMES);
s_listValue.CreateIndirect(hWnd, IDL_VALUES);
s_bClearAll = TRUE;
//SubClass the ListViews.
SynchSubProc(s_listNames.m_hWnd, WM_INITDIALOG, 0, (LPARAM)s_listValue.m_hWnd);
SynchSubProc(s_listValue.m_hWnd, WM_INITDIALOG, 0, (LPARAM)s_listNames.m_hWnd);
//Use Extended ListView Styles!
SendMessage(s_listNames.m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_CHECKBOXES, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_CHECKBOXES);
SendMessage(s_listValue.m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE);
//Set image list to the ListView
ListView_SetImageList(s_listNames.m_hWnd, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
ListView_SetImageList(s_listNames.m_hWnd, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_STATE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_STATE);
ListView_SetImageList(s_listValue.m_hWnd, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
//Insert Column Headers
s_listNames.InsertColumn(0, L"Column");
s_listNames.InsertColumn(1, L"Length");
s_listNames.InsertColumn(2, L"Status");
s_listNames.InsertColumn(3, L"Type");
s_listNames.InsertColumn(4, L"SubType");
s_listValue.InsertColumn(0, L"Data");
//Obtain the data for the selected row
HROW hRow = NULL;
//Determine the object type
CRow* pCRow = SOURCE_GETOBJECT(pThis->m_pCSource, CRow);
CRowset* pCRowset = SOURCE_GETOBJECT(pThis->m_pCSource, CRowset);
CDataset* pCDataset = SOURCE_GETOBJECT(pThis->m_pCSource, CDataset);
CDataAccess* pCDataAccess = SOURCE_GETOBJECT(pThis->m_pCSource, CDataAccess);
CDataGrid* pCDataGrid = pThis->m_pCDataGrid;
void* pData = NULL;
//Determine how to get the data...
if(pCRow)
{
//Row Object (extra columns)
hr = pCRow->GetColumns(pCRow->m_cColAccess, pCRow->m_rgColAccess);
pData = pCDataAccess->m_pData;
}
else if(pCDataset)
{
//Dataset Object
hr = pCDataset->GetCellData(pCDataGrid->m_iSelRow, pCDataGrid->m_iSelRow);
pData = pCDataAccess->m_pData;
}
else if(pCRowset)
{
//Rowset
//Obtain the selected row...
if(pCDataGrid->m_iSelRow != LVM_ERR)
hRow = pCDataGrid->GetItemParam(pCDataGrid->m_iSelRow);
//NOTE: If the user has released the row handle, and then called
//insert row, selecting this row handle, since of erroring out we will just not
//provide the default row of data to insert...
if(hRow || pThis->m_idSource != IDM_INSERTROW)
{
hr = pCRowset->GetData(hRow);
pData = pCDataAccess->m_pData;
}
}
//Relax the errors here. With Get*Data both DB_S/DB_E will return a bad
//status for 1 or more columns. Or DataGrid will just display the column
//status if not S_OK. So for these errors just display the data anyway...
if(FAILED(hr) && hr!= DB_E_ERRORSOCCURRED)
goto CLEANUP2;
hr = S_OK; //Otherwise dialog is not displayed
//Display ColumnNames in LeftPane, and data in the right pane
for(iBind=0; iBind<pCDataAccess->m_Bindings.GetCount(); iBind++)
{
//Get the Length, Status, Data for this Column
const DBBINDING* pBinding = &pCDataAccess->m_Bindings[iBind];
const DBCOLUMNINFO* pColInfo = pCDataAccess->m_ColumnInfo.GetOrdinal(pBinding->iOrdinal);
wszBuffer[0] = wEOL;
//Obtain the Data...
if(pData)
pCDataAccess->GetColumnData(pBinding, pData, &dbStatus, &dbLength, &wSubType, wszBuffer, MAX_COL_SIZE, dwConvFlags, pColInfo->wType);
//Insert the Data into the list (make an "easy" edit)
s_listValue.InsertItem(iBind, 0, wszBuffer, (LPARAM)pColInfo->wType, pCDataAccess->GetColumnImage(pColInfo, dbStatus));
//Insert the ColumnName
s_listNames.InsertItem(iBind, 0, GetColName(pColInfo));
//Insert the Length into the List
if(LENGTH_IS_BOUND(*pBinding))
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", dbLength);
else
StringCopy(wszBuffer, L"Not Bound", MAX_COL_SIZE);
s_listNames.InsertItem(iBind, 1, wszBuffer);
//Insert the Status into the List
s_listNames.InsertItem(iBind, 2, STATUS_IS_BOUND(*pBinding) ? GetStatusName(dbStatus) : L"Not Bound");
//Insert the Type into the List
s_listNames.InsertItem(iBind, 3, GetDBTypeName(pColInfo->wType));
//Insert the SubType into the List
if(wSubType || pColInfo->wType == VT_VARIANT)
s_listNames.InsertItem(iBind, 4, GetVariantTypeName(wSubType));
//Set Item State to Checked/Unchecked
s_listNames.SetItemState(iBind, 0, INDEXTOSTATEIMAGEMASK(pColInfo->dwFlags & (DBCOLUMNFLAGS_WRITE|DBCOLUMNFLAGS_WRITEUNKNOWN) ? STATE_CHECKED : STATE_UNCHECKED), LVIS_STATEIMAGEMASK);
}
//Update Controls
::EnableWindow(::GetDlgItem(hWnd, IDB_CLEARALL), (pCRowset && pCRowset->m_pIRowsetChange) || (pCRow && pCRow->m_pIRowChange));
//Update Title and Status
switch(pThis->m_idSource)
{
case IDM_IROW_DELETECOLUMNS:
if(pCRow && pCRow->m_pIRowSchemaChange)
{
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"IRowSchemaChange::DeleteColumns");
SendMessage(::GetDlgItem(hWnd, IDT_HELPMSG), WM_SETTEXT, 0, (LPARAM)"Deletes the desired columns from the row object");
SendMessage(::GetDlgItem(hWnd, IDOK), WM_SETTEXT, 0, (LPARAM)"Delete");
::EnableWindow(::GetDlgItem(hWnd, IDB_CLEARALL), TRUE);
}
break;
case IDM_IROW_SETCOLUMNS:
if(pCRow && pCRow->m_pIRowChange)
{
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"IRowChange::SetColumns");
SendMessage(::GetDlgItem(hWnd, IDT_HELPMSG), WM_SETTEXT, 0, (LPARAM)"Modifies the row object columns");
SendMessage(::GetDlgItem(hWnd, IDOK), WM_SETTEXT, 0, (LPARAM)"SetColumns");
::EnableWindow(::GetDlgItem(hWnd, IDB_CLEARALL), TRUE);
}
break;
case IDM_INSERTROW:
if(pCRowset && pCRowset->m_pIRowsetChange)
{
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"IRowsetChange::InsertRow");
SendMessage(::GetDlgItem(hWnd, IDT_HELPMSG), WM_SETTEXT, 0, (LPARAM)"Inserts the desired row of data into the Rowset");
SendMessage(::GetDlgItem(hWnd, IDOK), WM_SETTEXT, 0, (LPARAM)"InsertRow");
::EnableWindow(::GetDlgItem(hWnd, IDB_CLEARALL), TRUE);
}
break;
case IDM_SETDATA:
if(pCRowset && pCRowset->m_pIRowsetChange)
{
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"IRowsetChange::SetData");
SendMessage(::GetDlgItem(hWnd, IDT_HELPMSG), WM_SETTEXT, 0, (LPARAM)"Modifies the row data in the Rowset");
SendMessage(::GetDlgItem(hWnd, IDOK), WM_SETTEXT, 0, (LPARAM)"SetData");
::EnableWindow(::GetDlgItem(hWnd, IDB_CLEARALL), TRUE);
}
break;
default:
//NOTE: The Dialog is already setup with the default window text:
//"Detailed Row Information"
::EnableWindow(::GetDlgItem(hWnd, IDB_CLEARALL), FALSE);
break;
};
//Free outofline data
//TODO - need to free in the case of errors as well. But have to be careful
//since the pData may not have been setup yet, or other errors where its undefined...
if(pData)
pCDataAccess->m_Bindings.FreeData(pData);
CLEANUP2:
//AutoSize Columns
for(iBind=0; iBind<=4; iBind++)
s_listNames.SetColumnWidth(iBind, LVSCW_AUTOSIZE_USEHEADER);
s_listValue.SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
CenterDialog(hWnd);
if(FAILED(hr))
EndDialog(hWnd, FALSE);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
break;
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_CLEARALL:
{
//Get the "this" pointer
CWaitCursor waitCursor;
//Now that the user has selected to clear all columns, we need to loop through
//all the checked columns and just uncheck them...
INDEX cItems = s_listNames.GetItemCount();
for(INDEX i=0; i<cItems; i++)
{
//Check the property state
s_listNames.SetItemState(i, 0, INDEXTOSTATEIMAGEMASK(s_bClearAll ? STATE_UNCHECKED : STATE_CHECKED), LVIS_STATEIMAGEMASK);
}
//Clear All is a toggle...
if(s_bClearAll)
{
s_bClearAll = FALSE;
::SetWindowText(::GetDlgItem(hWnd, IDB_CLEARALL), "SelectAll");
}
else
{
s_bClearAll = TRUE;
::SetWindowText(::GetDlgItem(hWnd, IDB_CLEARALL), "ClearAll");
}
return 0;
}
case IDM_DBSTATUS_S_OK:
{
//Insert the Status into the List
INDEX iSelRow = s_listNames.GetNextItem(-1, LVNI_SELECTED);
if(iSelRow == LVM_ERR)
return 0;
s_listNames.InsertItem(iSelRow, 2, L"DBSTATUS_S_OK");
return 0;
}
case IDM_DBSTATUS_S_ISNULL:
{
//Insert the Status into the List
INDEX iSelRow = s_listNames.GetNextItem(-1, LVNI_SELECTED);
if(iSelRow == LVM_ERR)
return 0;
s_listNames.InsertItem(iSelRow, 2, L"DBSTATUS_S_ISNULL");
return 0;
}
case IDM_DBSTATUS_S_DEFAULT:
{
//Insert the Status into the List
INDEX iSelRow = s_listNames.GetNextItem(-1, LVNI_SELECTED);
if(iSelRow == LVM_ERR)
return 0;
s_listNames.InsertItem(iSelRow, 2, L"DBSTATUS_S_DEFAULT");
return 0;
}
case IDM_DBSTATUS_S_IGNORE:
{
//Insert the Status into the List
INDEX iSelRow = s_listNames.GetNextItem(-1, LVNI_SELECTED);
if(iSelRow == LVM_ERR)
return 0;
s_listNames.InsertItem(iSelRow, 2, L"DBSTATUS_S_IGNORE");
return 0;
}
case IDM_DISPLAY_HEX:
{
WCHAR wszBuffer[MAX_COL_SIZE+1]={0};
//Find the Selected Row
INDEX iSelRow = s_listValue.GetNextItem(-1, LVNI_SELECTED);
if(iSelRow == LVM_ERR)
return 0;
//Get the Text from the Row
s_listValue.GetItemText(iSelRow, 0, wszBuffer, MAX_COL_SIZE);
//Convert using the Requested converions
if(SUCCEEDED(PostProcessString(wszBuffer, MAX_COL_SIZE, CONV_HEX)))
{
//Insert the Data into the list (make an "easy" edit)
s_listValue.SetItemText(iSelRow, 0, wszBuffer);
}
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
HRESULT hr = S_OK;
ULONG i=0;
HROW hRow = NULL;
INDEX iSelItems = 0;
ULONG cColumnIDs = 0;
DBID* rgColumnIDs = NULL;
DBSTATUS* rgStatus = NULL;
//Determine the object type
CRow* pCRow = SOURCE_GETOBJECT(pThis->m_pCSource, CRow);
CRowset* pCRowset = SOURCE_GETOBJECT(pThis->m_pCSource, CRowset);
CDataAccess* pCDataAccess = SOURCE_GETOBJECT(pThis->m_pCSource, CDataAccess);
CDataGrid* pCDataGrid = pThis->m_pCDataGrid;
CBindings& rBindings = pCDataAccess->m_Bindings;
void* pData = pCDataAccess->m_pData;
//The ListView will produce IDOK if hitting return after entering
//a value. The easist way arround this is to just exit if
//we haven't yet received the ENDEDIT message
if(bBeginEdit || (!SOURCE_GETINTERFACE(pCRow, IRowChange) && !SOURCE_GETINTERFACE(pCRowset, IRowsetChange)))
goto CLEANUP;
//Create Accessor binding all selected columns...
iSelItems = s_listNames.GetItemCount();
ASSERT(iSelItems != LVM_ERR);
if(pThis->m_idSource == IDM_IROW_DELETECOLUMNS)
{
SAFE_ALLOC(rgColumnIDs, DBID, iSelItems);
SAFE_ALLOC(rgStatus, DBSTATUS, iSelItems);
}
//Obtain the ListView Values into our pData buffer
//NOTE: We do this before we filter the selected columns, since the dialog
//contains all columns, and needs to be indexed in the same order,
//without missing columns in the middle...
TESTC(hr = pThis->GetListViewValues(s_listNames.m_hWnd, s_listValue.m_hWnd, pCDataAccess, rBindings, pData));
//Loop through selected bindings
for(i=0; i<rBindings.GetCount(); i++)
{
//Create compacted array of ColumnIDs for IRowSchemaChange::DeleteColumns
if(pThis->m_idSource == IDM_IROW_DELETECOLUMNS)
{
//Get the Image and Param
BOOL bChecked = s_listNames.GetItemState(i, LVIS_STATEIMAGEMASK) & INDEXTOSTATEIMAGEMASK(STATE_CHECKED);
if(bChecked)
{
memcpy(&rgColumnIDs[cColumnIDs], &pCRow->m_rgColAccess[i].columnid, sizeof(DBID));
rgStatus[cColumnIDs] = DBSTATUS_S_OK;
cColumnIDs++;
}
}
}
switch(pThis->m_idSource)
{
case IDM_INSERTROW:
if(pCRowset && pCRowset->m_pIRowsetChange)
{
HCHAPTER hChapter = pCRowset->m_hChapter;
//Release previously fetched rows, (if user requested)
hr = pCDataGrid->ReleaseHeldRows();
//Now that we have setup the buffer, Insert the data into the rowset
XTEST(hr = pCRowset->m_pIRowsetChange->InsertRow(hChapter, pCRowset->m_hAccessor, pData, &hRow));
TRACE_METHOD(hr, L"IRowsetChange::InsertRow(0x%p, 0x%p, 0x%p, &0x%p)", hChapter, pCRowset->m_hAccessor, pData, hRow);
//Display Data Errors
TESTC(hr = DisplayBindingErrors(hr, rBindings.GetCount(), rBindings.GetElements(), pData));
//Release the Retreived Row handle...
//We could have just passed phRow = NULL, since we don't save the row handle,
//but its nice for output/trace purposes so the user knows a handle
//was received...
//NOTE: We don't insert the returned row handle into the ListView
//since we are not sure where the row was inserted. Inserting it blindly
//at the end would appear as if the cursor positioning was oof with
//GetNextRows if it was not truely inserted at the end.
if(SUCCEEDED(hr))
pCRowset->ReleaseRows(1, &hRow);
}
break;
case IDM_IROW_DELETECOLUMNS:
if(pCRow && pCRow->m_pIRowSchemaChange)
{
//DeleteColumns
XTEST(hr = pCRow->m_pIRowSchemaChange->DeleteColumns(cColumnIDs, rgColumnIDs, rgStatus));
TRACE_METHOD(hr, L"IRowSchemaChange::DeleteColumns(%lu, 0x%p, 0x%p)", cColumnIDs, rgColumnIDs, rgStatus);
//Display Data Errors
TESTC(hr = DisplayColumnErrors(hr, cColumnIDs, rgColumnIDs, rgStatus));
}
break;
case IDM_IROW_SETCOLUMNS:
if(pCRow && pCRow->m_pIRowChange)
{
//Have to call SetColumns for extra columns
XTEST(hr = pCRow->m_pIRowChange->SetColumns(pCRow->m_cColAccess, pCRow->m_rgColAccess));
TRACE_METHOD(hr, L"IRowChange::SetColumns(%lu, 0x%p)", pCRow->m_cColAccess, pCRow->m_rgColAccess);
//Display Data Errors
TESTC(hr = DisplayColAccessErrors(hr, pCRow->m_cColAccess, pCRow->m_rgColAccess));
}
break;
case IDM_SETDATA:
if(pCRowset && pCRowset->m_pIRowsetChange)
{
//Need to obtain the Current hRow value (lParam)
hRow = pCDataGrid->GetItemParam(pCDataGrid->m_iSelRow);
//Now that we have setup the buffer, SetData into the rowset
XTEST(hr = pCRowset->m_pIRowsetChange->SetData(hRow, pCRowset->m_hAccessor, pData));
TRACE_METHOD(hr, L"IRowsetChange::SetData(0x%p, 0x%p, 0x%p)", hRow, pCRowset->m_hAccessor, pData);
//Display Data Errors
TESTC(hr = DisplayBindingErrors(hr, rBindings.GetCount(), rBindings.GetElements(), pData));
}
break;
};
//Its our responsiblity to free the allocated (outofline) data...
//TODO - need to free in the case of errors as well. But have to be careful
//since the pData may not have been setup yet, or other errors where its undefined...
TESTC(rBindings.FreeData(pData, TRUE/*fSetData*/));
if(pThis->m_idSource != IDM_INSERTROW)
{
//Need to indicate row was modified, use "changed" icon
pCDataGrid->SetItemImage(pCDataGrid->m_iSelRow, 0, IMAGE_CHANGE);
//Display the Data for this Row
TESTC(hr = pCDataGrid->DisplayData(hRow, pCDataGrid->m_iSelRow, pCRow ? DBPROP_IRow : DBPROP_IRowset));
}
CLEANUP:
SAFE_FREE(rgColumnIDs);
SAFE_FREE(rgStatus);
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
bBeginEdit = FALSE;
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
case WM_CONTEXTMENU:
{
HWND hWndSelected = (HWND)wParam;
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
//Must have selected a row to change status
INDEX iSel = s_listNames.GetNextItem(-1, LVNI_SELECTED);
if(iSel == LVM_ERR)
return FALSE;
//IDL_NAMES
if(hWndSelected == s_listNames.m_hWnd)
{
//Don't need to change the status if readonly
if(!SOURCE_GETINTERFACE(pThis->m_pCSource, IRowChange) && !SOURCE_GETINTERFACE(pThis->m_pCSource, IRowsetChange))
return FALSE;
//Display Menu
DisplayContextMenu(
hWnd,
IDM_CHANGESTATUS,
MAKEPOINTS(lParam),
hWnd
);
}
//IDL_VALUES
if(hWndSelected == s_listValue.m_hWnd)
{
//Display Menu
DisplayContextMenu(
hWnd,
IDM_CHANGEVALUE,
MAKEPOINTS(lParam),
hWnd
);
}
return FALSE;
}
case WM_NOTIFY:
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)lParam;
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lParam;
switch(pDispInfo->hdr.code)
{
//Since we have "TwoClickActive" on this will get sent
//Whenever a row is clicked on twice!
//This functionality used to be done with NM_DBCLK
case LVN_ITEMACTIVATE:
{
//Obtain the SelectedRow
INDEX iSel = (INDEX)SendMessage(::GetDlgItem(hWnd, IDL_VALUES), LVM_GETNEXTITEM, (WPARAM)-1, (LPARAM)LVNI_SELECTED);
if(iSel == LVM_ERR)
return 0;
//Need to Send LVM_EDITLABEL
SendMessage(::GetDlgItem(hWnd, IDL_VALUES), LVM_EDITLABEL, iSel, 0);
return 0;
}
case LVN_BEGINLABELEDIT:
bBeginEdit = TRUE;
return FALSE;//allow the user to change the value of the item.
case LVN_ENDLABELEDIT:
{
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
bBeginEdit = FALSE;
//Now update the ListView with the new value
//If IRowsetChange is supported...
if(pDispInfo->item.pszText && (SOURCE_GETINTERFACE(pThis->m_pCSource, IRowChange) || SOURCE_GETINTERFACE(pThis->m_pCSource, IRowsetChange)))
{
WCHAR wszBuffer[MAX_NAME_LEN]={0};
ConvertToWCHAR(pDispInfo->item.pszText, wszBuffer, MAX_NAME_LEN);
s_listValue.SetItemText(pDispInfo->item.iItem, 0, wszBuffer);
}
return TRUE; //Allow the edited change
}
case LVN_ITEMCHANGED:
{
bBeginEdit = FALSE;
if(pNMListView->uNewState & LVNI_FOCUSED &&
pNMListView->uNewState & LVNI_SELECTED)
{
if(wParam == IDL_VALUES)
{
SyncSibling(s_listNames.m_hWnd, s_listValue.m_hWnd);
return HANDLED_MSG;
}
if(wParam == IDL_NAMES)
{
SyncSibling(s_listValue.m_hWnd, s_listNames.m_hWnd);
return HANDLED_MSG;
}
return UNHANDLED_MSG; //No return Value
}
}
}
}//WM_NOTIFY
}//switch(message);
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::ColumnChangeProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::ColumnChangeProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL bBeginEdit = FALSE;
static HACCESSOR hAccessor = NULL;
static CListViewLite s_listNames;
static CListViewLite s_listValue;
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
bBeginEdit = FALSE;
WCHAR wszBuffer[MAX_COL_SIZE+1];
DBLENGTH dbLength = 0;
DBSTATUS dbStatus = 0;
DBTYPE wSubType = 0;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
DWORD dwConvFlags = pThis->GetOptions()->m_dwConvFlags;
INDEX i,iItemCount = 0;
HRESULT hr = S_OK;
//We need to bring up a 2 ListViews.
//left - has column names,
//right - is blank for entering data for the corrsponding column
//Setup column headers
s_listNames.CreateIndirect(hWnd, IDL_NAMES);
s_listValue.CreateIndirect(hWnd, IDL_VALUES);
//Use Extended ListView Styles!
SendMessage(s_listNames.m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE , LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE);
SendMessage(s_listValue.m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE , LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE);
//Set image list to the ListView
ListView_SetImageList(s_listValue.m_hWnd, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
ListView_SetImageList(s_listNames.m_hWnd, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
//Update Controls
::EnableWindow(::GetDlgItem(hWnd, IDB_CLEARALL), FALSE);
//Determine the object type
CRow* pCRow = SOURCE_GETOBJECT(pThis->m_pCSource, CRow);
CRowset* pCRowset = SOURCE_GETOBJECT(pThis->m_pCSource, CRowset);
CDataset* pCDataset = SOURCE_GETOBJECT(pThis->m_pCSource, CDataset);
CDataAccess* pCDataAccess = SOURCE_GETOBJECT(pThis->m_pCSource, CDataAccess);
CDataGrid* pCDataGrid = pThis->m_pCDataGrid;
//Update Title and Status
switch(pThis->m_idSource)
{
case IDM_IROW_SETCOLUMNS:
if(pCRow && pCRow->m_pIRowChange)
{
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"IRowChange::SetColumns");
SendMessage(::GetDlgItem(hWnd, IDT_HELPMSG), WM_SETTEXT, 0, (LPARAM)"Modifies the row object columns");
SendMessage(::GetDlgItem(hWnd, IDOK), WM_SETTEXT, 0, (LPARAM)"SetColumns");
}
break;
case IDM_SETDATA:
if(pCRowset && pCRowset->m_pIRowsetChange)
{
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"IRowsetChange::SetData");
SendMessage(::GetDlgItem(hWnd, IDT_HELPMSG), WM_SETTEXT, 0, (LPARAM)"Modifies the row data in the Rowset");
SendMessage(::GetDlgItem(hWnd, IDOK), WM_SETTEXT, 0, (LPARAM)"SetData");
}
break;
};
//Insert Column Headers
s_listNames.InsertColumn(0, pCDataAccess->GetObjectType() == eCDataset ? L" Cell Ordinal " : L" Row Handle ");
s_listNames.InsertColumn(1, L"Length");
s_listNames.InsertColumn(2, L"Status");
s_listNames.InsertColumn(3, L"Type");
s_listNames.InsertColumn(4, L"SubType");
const DBBINDING* pBinding = &pCDataAccess->m_Bindings[pCDataGrid->m_iSelCol];
const DBCOLUMNINFO* pColInfo = pCDataAccess->m_ColumnInfo.GetOrdinal(pBinding->iOrdinal);
void* pData = pCDataAccess->m_pData;
if(!pCRow)
{
//Create An Accessor binding only this column
//Much quicker to get and set using only the column we need.
hr = pCDataAccess->CreateAccessor(DBACCESSOR_ROWDATA, 1, pBinding, 0, &hAccessor);
if(FAILED(hr))
goto CLEANUP2;
}
//Column header is the ColumnName
s_listValue.InsertColumn(0, GetColName(pColInfo), pCDataAccess->GetColumnImage(pColInfo));
//Display Data in the ListView
iItemCount = pCDataGrid->GetItemCount();
for(i=0; i<iItemCount; i++)
{
//Get row handle for the selected row
HROW hRow = pCDataGrid->GetItemParam(i);
if(pCRow)
{
ULONG cColAccess = 1;
DBCOLUMNACCESS* rgColAccess = &pCRow->m_rgColAccess[pCDataGrid->m_iSelCol];
//GetColumn for this row object
//Much quicker to get and set using only the column we need.
hr = pCRow->GetColumns(cColAccess, rgColAccess);
}
else if(pCDataset)
{
//GetCellData
//Note: the "hRow" stored in the listview is the index
hr = pCDataset->GetCellData(hRow, hRow);
}
else if(pCRowset)
{
//GetData for this row from the rowset
//Much quicker to get and set using only the column we need.
hr = pCRowset->GetData(hRow, hAccessor, pData);
}
//Relax the errors here. With Get*Data both DB_S/DB_E will return a bad
//status for 1 or more columns. Or DataGrid will just display the column
//status if not S_OK. So for these errors just display the data anyway...
if(FAILED(hr) && hr!= DB_E_ERRORSOCCURRED)
goto CLEANUP2;
hr = S_OK; //Otherwise dialog is not displayed
//Get the Length, Status, Data for this Column
pCDataAccess->GetColumnData(pBinding, pData, &dbStatus, &dbLength, &wSubType, wszBuffer, MAX_COL_SIZE, dwConvFlags, pColInfo->wType);
//Insert the Data into the list (make an "easy" edit)
s_listValue.InsertItem(i, 0, wszBuffer, (LPARAM)pColInfo->wType, pCDataAccess->GetColumnImage(pColInfo, dbStatus));
//Display the hRow in the ListView
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", hRow);
s_listNames.InsertItem(i, 0, wszBuffer, 0, 0);
//Insert the Length into the List
if(LENGTH_IS_BOUND(*pBinding))
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", dbLength);
else
StringCopy(wszBuffer, L"Not Bound", MAX_COL_SIZE);
s_listNames.InsertItem(i, 1, wszBuffer);
//Insert the Status into the List
s_listNames.InsertItem(i, 2, STATUS_IS_BOUND(*pBinding) ? GetStatusName(dbStatus) : L"Not Bound");
//Insert the Type into the List
s_listNames.InsertItem(i, 3, GetDBTypeName(pColInfo->wType));
//Insert the SubType into the List
if(pBinding->wType == DBTYPE_VARIANT)
s_listNames.InsertItem(i, 4, GetVariantTypeName(wSubType));
}
//Free any outofline data
//TODO - need to free in the case of errors as well. But have to be careful
//since the pData may not have been setup yet, or other errors where its undefined...
if(SUCCEEDED(hr))
FreeBindingData(1, pBinding, pData);
//AutoSize Columns
for(i=0; i<=4; i++)
s_listNames.SetColumnWidth(i, LVSCW_AUTOSIZE_USEHEADER);
s_listValue.SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
CLEANUP2:
CenterDialog(hWnd);
if(FAILED(hr))
{
pCDataAccess->ReleaseAccessor(&hAccessor);
EndDialog(hWnd, FALSE);
}
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDM_DBSTATUS_S_OK:
{
//Insert the Status into the List
INDEX iSelRow = s_listNames.GetNextItem(-1, LVNI_SELECTED);
if(iSelRow == LVM_ERR)
return 0;
s_listNames.InsertItem(iSelRow, 2, L"DBSTATUS_S_OK");
return 0;
}
case IDM_DBSTATUS_S_ISNULL:
{
//Insert the Status into the List
INDEX iSelRow = s_listNames.GetNextItem(-1, LVNI_SELECTED);
if(iSelRow == LVM_ERR)
return 0;
s_listNames.InsertItem(iSelRow, 2, L"DBSTATUS_S_ISNULL");
return 0;
}
case IDM_DBSTATUS_S_DEFAULT:
{
//Insert the Status into the List
INDEX iSelRow = s_listNames.GetNextItem(-1, LVNI_SELECTED);
if(iSelRow == LVM_ERR)
return 0;
s_listNames.InsertItem(iSelRow, 2, L"DBSTATUS_S_DEFAULT");
return 0;
}
case IDM_DBSTATUS_S_IGNORE:
{
//Insert the Status into the List
INDEX iSelRow = s_listNames.GetNextItem(-1, LVNI_SELECTED);
if(iSelRow == LVM_ERR)
return 0;
s_listNames.InsertItem(iSelRow, 2, L"DBSTATUS_S_IGNORE");
return 0;
}
case IDM_DISPLAY_HEX:
{
WCHAR wszBuffer[MAX_COL_SIZE+1] = {0};
//Find the Selected Row
INDEX iSelRow = s_listValue.GetNextItem(-1, LVNI_SELECTED);
if(iSelRow == LVM_ERR)
return 0;
//Get the Text from the Row
s_listValue.GetItemText(iSelRow, 0, wszBuffer, MAX_COL_SIZE);
//Convert using the Requested converions
if(SUCCEEDED(PostProcessString(wszBuffer, MAX_COL_SIZE, CONV_HEX)))
{
//Insert the Data into the list (make an "easy" edit)
s_listValue.SetItemText(iSelRow, 0, wszBuffer);
}
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
WCHAR wszBuffer[MAX_COL_SIZE+1];
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
INDEX i,iItemCount = 0;
HRESULT hr = S_OK;
//Determine the object type
CRow* pCRow = SOURCE_GETOBJECT(pThis->m_pCSource, CRow);
CRowset* pCRowset = SOURCE_GETOBJECT(pThis->m_pCSource, CRowset);
CDataAccess* pCDataAccess = SOURCE_GETOBJECT(pThis->m_pCSource, CDataAccess);
CDataGrid* pCDataGrid = pThis->m_pCDataGrid;
const DBBINDING* pBinding = &pCDataAccess->m_Bindings[pCDataGrid->m_iSelCol];
const DBCOLUMNINFO* pColInfo = pCDataAccess->m_ColumnInfo.GetOrdinal(pBinding->iOrdinal);
void* pData = pCDataAccess->m_pData;
//The ListView will produce IDOK if hitting return after entering
//a value. The easist way arround this is to just exit if
//we haven't yet received the ENDEDIT message
if(bBeginEdit)
goto CLEANUP;
if(!SOURCE_GETINTERFACE(pCRow, IRowChange) && !SOURCE_GETINTERFACE(pCRowset, IRowsetChange))
goto CLEANUP;
//This dialog is a little more complex since were allowing
//the user to change an entire column so every row must be set
//To make our lives a little easier, we will first Get the Data
//for the row, and then Set only the affected column...
iItemCount = s_listValue.GetItemCount();
for(i=0; i<iItemCount; i++)
{
//Get row handle
HROW hRow = pCDataGrid->GetItemParam(i);
//Get the ColumnStatus
s_listNames.GetItemText(i, 2, wszBuffer, MAX_COL_SIZE);
DBSTATUS dbStatus = GetStatusValue(wszBuffer);
//Set the ColumnData in our pData buffer
s_listValue.GetItemText(i, 0, wszBuffer, MAX_COL_SIZE);
TESTC(hr = pCDataAccess->SetColumnData(pBinding, pData, dbStatus, wcslen(wszBuffer), wszBuffer, CONV_NONE, pColInfo->wType));
if(pCRow)
{
ULONG cColAccess = 1;
DBCOLUMNACCESS* rgColAccess = &pCRow->m_rgColAccess[pCDataGrid->m_iSelCol];
//Have to call SetColumns for extra columns
XTEST(hr = pCRow->m_pIRowChange->SetColumns(cColAccess, rgColAccess));
TRACE_METHOD(hr, L"IRowChange::SetColumns(%lu, 0x%p)", cColAccess, rgColAccess);
//Display Data Errors...
TESTC(hr = DisplayColAccessErrors(hr, cColAccess, rgColAccess));
}
else if(pCRowset)
{
//Now that we have setup the buffer, SetData into the rowset
XTEST(hr = pCRowset->m_pIRowsetChange->SetData(hRow, hAccessor, pData));
TRACE_METHOD(hr, L"IRowsetChange::SetData(0x%p, 0x%p, 0x%p)", hRow, hAccessor, pData);
//Display Data Errors...
TESTC(hr = DisplayBindingErrors(hr, 1, pBinding, pData));
}
//Need to indicate row was modified, use "changed" icon
pCDataGrid->SetItemImage(pCDataGrid->m_iSelRow, 0, IMAGE_CHANGE);
//Display the Data for this Row
TESTC(hr = pCDataGrid->DisplayData(hRow, i, pCRow ? DBPROP_IRow : DBPROP_IRowset));
}
//Free outofline data
//TODO - need to free in the case of errors as well. But have to be careful
//since the pData may not have been setup yet, or other errors where its undefined...
FreeBindingData(1, pBinding, pData, TRUE/*fSetData*/);
CLEANUP:
if(SUCCEEDED(hr))
{
pCDataAccess->ReleaseAccessor(&hAccessor);
EndDialog(hWnd, TRUE);
}
return 0;
}
case IDCANCEL:
{
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CDataAccess* pCDataAccess = SOURCE_GETOBJECT(pThis->m_pCSource, CDataAccess);
bBeginEdit = FALSE;
pCDataAccess->ReleaseAccessor(&hAccessor);
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
case WM_CONTEXTMENU:
{
HWND hWndSelected = (HWND)wParam;
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
//Must have selected a row to change status
INDEX iSel = s_listNames.GetNextItem(-1, LVNI_SELECTED);
if(iSel == LVM_ERR)
return FALSE;
//IDL_NAMES
if(hWndSelected == s_listNames.m_hWnd)
{
//Don't need to change the status if readonly
if(SOURCE_GETINTERFACE(pThis->m_pCSource, IRowChange) && SOURCE_GETINTERFACE(pThis->m_pCSource, IRowsetChange))
return FALSE;
//Display Menu
DisplayContextMenu(
hWnd,
IDM_CHANGESTATUS,
MAKEPOINTS(lParam),
hWnd
);
}
//IDL_VALUES
if(hWndSelected == s_listValue.m_hWnd)
{
//Display Menu
DisplayContextMenu(
hWnd,
IDM_CHANGEVALUE,
MAKEPOINTS(lParam),
hWnd
);
}
return FALSE;
}
case WM_NOTIFY:
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)lParam;
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lParam;
switch(pDispInfo->hdr.code)
{
//Since we have "TwoClickActive" on this will get sent
//Whenever a row is clicked on twice!
//This functionality used to be done with NM_DBCLK
case LVN_ITEMACTIVATE:
{
//Save the SelectedRow so the new dialog box knows which row were concerned with...
INDEX iSel = (INDEX)SendMessage(::GetDlgItem(hWnd, IDL_VALUES), LVM_GETNEXTITEM, (WPARAM)-1, (LPARAM)LVNI_SELECTED);
if(iSel == LVM_ERR)
return 0;
//Need to Send LVM_EDITLABEL
SendMessage(::GetDlgItem(hWnd, IDL_VALUES), LVM_EDITLABEL, iSel, 0);
return FALSE;
}
case LVN_BEGINLABELEDIT:
bBeginEdit = TRUE;
return FALSE;//allow the user to change the value of the item.
case LVN_ENDLABELEDIT:
{
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
bBeginEdit = FALSE;
//Now update the ListView with the new value
if(pDispInfo->item.pszText && (SOURCE_GETINTERFACE(pThis->m_pCSource, IRowChange) || SOURCE_GETINTERFACE(pThis->m_pCSource, IRowsetChange)))
{
WCHAR wszBuffer[MAX_NAME_LEN]={0};
ConvertToWCHAR(pDispInfo->item.pszText, wszBuffer, MAX_NAME_LEN);
s_listValue.SetItemText(pDispInfo->item.iItem, 0, wszBuffer);
}
return TRUE; //Allow the edited change
}
case LVN_ITEMCHANGED:
{
if(pNMListView->uNewState & LVNI_FOCUSED &&
pNMListView->uNewState & LVNI_SELECTED)
{
if(wParam == IDL_VALUES)
{
SyncSibling(s_listNames.m_hWnd, s_listValue.m_hWnd);
return HANDLED_MSG;
}
if(wParam == IDL_NAMES)
{
SyncSibling(s_listValue.m_hWnd, s_listNames.m_hWnd);
return HANDLED_MSG;
}
return UNHANDLED_MSG; //No return Value
}
}
}
}//WM_NOTIFY
}//switch(message);
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetAxisInfoProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::GetAxisInfoProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL bBeginEdit = FALSE;
static CListViewLite s_listAxisInfo;
static CComboBoxLite s_comboAxis;
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
bBeginEdit = FALSE;
HRESULT hr = S_OK;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CDataset* pCDataset = SOURCE_GETOBJECT(pThis->m_pCDataAccess, CDataset);
DBCOUNTITEM cAxis;
MDAXISINFO *rgAxisInfo;
WCHAR wszBuffer[MAX_NAME_LEN];
//Setup the ListView
s_listAxisInfo.CreateIndirect(hWnd, IDL_AXISINFO);
s_comboAxis.CreateIndirect(hWnd, IDCOMBO_AXIS);
//Use Extended ListView Styles!
SendMessage(s_listAxisInfo.m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE , LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE);
//Insert Column Headers
s_listAxisInfo.InsertColumn(0, L"Dimension Names");
s_listAxisInfo.InsertColumn(1, L"Columns");
// get the axis info from the dataset
ASSERT(pCDataset);
hr = pCDataset->GetAxisInfo(&cAxis, &rgAxisInfo);
if (SUCCEEDED(hr) && cAxis != 0)
{
// fill in the axis selection combo
for (ULONG iAxis=0; iAxis<cAxis-1; iAxis++)
{
switch (iAxis)
{
case 0:
s_comboAxis.AddString(L"Columns");
break;
case 1:
s_comboAxis.AddString(L"Rows");
break;
default:
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%lu", iAxis);
s_comboAxis.AddString(wszBuffer);
break;
};
}
s_comboAxis.AddString(L"Slicer");
s_comboAxis.SetCurSel(0);
wSendMessageFmt(::GetDlgItem(hWnd, IDC_DIMENSIONS), WM_SETTEXT, 0, L"%Iu", rgAxisInfo->cDimensions);
wSendMessageFmt(::GetDlgItem(hWnd, IDC_COORDINATES), WM_SETTEXT, 0, L"%Iu", rgAxisInfo->cCoordinates);
//Display Dimension Names in LeftPane, and Column Count in right pane
for(ULONG iDim=0; iDim<rgAxisInfo->cDimensions; iDim++)
{
s_listAxisInfo.InsertItem(iDim, 0, rgAxisInfo->rgpwszDimensionNames[iDim]);
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%lu", rgAxisInfo->rgcColumns[iDim]);
s_listAxisInfo.InsertItem(iDim, 1, wszBuffer);
}
}
//AutoSize Columns
s_listAxisInfo.SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
s_listAxisInfo.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);
CenterDialog(hWnd);
//Cleanup
pCDataset->FreeAxisInfo(&cAxis, &rgAxisInfo);
return TRUE;
}
case WM_COMMAND:
{
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//The ListView will produce IDOK if hitting return after
//entering a value. The easist way arround this is to just exit if
//we haven't yet received the ENDEDIT message
if(bBeginEdit)
return FALSE;
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, TRUE);
return 0;
}
case IDCOMBO_AXIS:
{
switch(GET_WM_COMMAND_CMD(wParam, lParam))
{
//Selection change in axis combo box
case CBN_SELCHANGE:
{
HRESULT hr = S_OK;
DBCOUNTITEM cAxis;
MDAXISINFO *rgAxisInfo;
WCHAR wszBuffer[MAX_NAME_LEN];
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CDataset* pCDataset = SOURCE_GETOBJECT(pThis->m_pCDataAccess, CDataset);
INDEX iAxis = s_comboAxis.GetCurSel();
s_listAxisInfo.DeleteAllItems();
// get the axis info from the dataset
ASSERT(pCDataset);
hr = pCDataset->GetAxisInfo(&cAxis, &rgAxisInfo);
if (SUCCEEDED(hr) && cAxis >= (DBCOUNTITEM)iAxis)
{
wSendMessageFmt(::GetDlgItem(hWnd, IDC_DIMENSIONS), WM_SETTEXT, 0, L"%Iu", rgAxisInfo[iAxis].cDimensions);
wSendMessageFmt(::GetDlgItem(hWnd, IDC_COORDINATES), WM_SETTEXT, 0, L"%Iu", rgAxisInfo[iAxis].cCoordinates);
//Display Dimension Names in LeftPane, and Column Count in right pane
for(ULONG iDim=0; iDim<rgAxisInfo[iAxis].cDimensions; iDim++)
{
s_listAxisInfo.InsertItem(iDim, 0, rgAxisInfo[iAxis].rgpwszDimensionNames[iDim]);
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", rgAxisInfo[iAxis].rgcColumns[iDim]);
s_listAxisInfo.InsertItem(iDim, 1, wszBuffer);
}
}
//Cleanup
pCDataset->FreeAxisInfo(&cAxis, &rgAxisInfo);
return 0;
}
}
}
}
break;
}//WM_COMMAND
}//switch(message);
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetAxisRowsetProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::GetAxisRowsetProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static CComboBoxGuid s_CComboInterface;
static CComboBoxLite s_comboAxis;
static BOOL fUseProps = TRUE; //Default
static BOOL fAggregation = FALSE; //Default
static BOOL fOutput = TRUE; //Default
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
HRESULT hr = S_OK;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CDataset* pCDataset = SOURCE_GETOBJECT(pThis->m_pCDataAccess, CDataset);
DBCOUNTITEM cAxis;
MDAXISINFO *rgAxisInfo;
WCHAR wszBuffer[MAX_NAME_LEN];
//Setup the Combo
s_comboAxis.CreateIndirect(hWnd, IDCOMBO_AXIS);
// get the axis info from the dataset
ASSERT(pCDataset);
hr = pCDataset->GetAxisInfo(&cAxis, &rgAxisInfo);
if(SUCCEEDED(hr) && cAxis)
{
// fill in the axis selection combo
for (ULONG iAxis=0; iAxis<cAxis-1; iAxis++)
{
switch (iAxis)
{
case 0:
s_comboAxis.AddString(L"Columns");
break;
case 1:
s_comboAxis.AddString(L"Rows");
break;
default:
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%lu", iAxis);
s_comboAxis.AddString(wszBuffer);
break;
};
}
s_comboAxis.AddString(L"Slicer");
s_comboAxis.SetCurSel(0);
}
//Use Properties
::CheckDlgButton(hWnd, IDB_USEPROPERTIES, BST2STATE(fUseProps));
//Aggregation
::CheckDlgButton(hWnd, IDB_AGGREGATION, BST2STATE(fAggregation));
//Output (ppIUnknown)
::CheckDlgButton(hWnd, IDB_OUTPUT, BST2STATE(fOutput));
//Interface List...
s_CComboInterface.CreateIndirect(hWnd, IDC_INTERFACE);
s_CComboInterface.Populate(g_cInterfaceMaps, g_rgInterfaceMaps);
if(s_CComboInterface.RestoreSelection() == CB_ERR)
s_CComboInterface.SetGuid(IID_IRowset);
//Cleanup
pCDataset->FreeAxisInfo(&cAxis, &rgAxisInfo);
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_SETPROPERTIES:
{
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CMainWindow* pCMainWindow = pThis->m_pCMainWindow;
CDataSource* pCDataSource = SOURCE_GETPARENT(pThis->m_pCSource, CDataSource);
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_ROWSETALL, IID_IRowsetInfo, NULL, pCDataSource ? pCDataSource->m_pIDBProperties : NULL, &pThis->m_CDefPropSets);
return 0;
}
case IDB_AGGREGATION:
{
//Aggregation Combo Selection has changed...
//If we are now using Aggregation, automatically change the requested
//riid to IID_IUnknown, since its an error otherwise...
if(::IsDlgButtonChecked(hWnd, IDB_AGGREGATION))
s_CComboInterface.SetGuid(IID_IUnknown);
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CDataset* pCDataset = SOURCE_GETOBJECT(pThis->m_pCDataAccess, CDataset);
CComPtr<IUnknown> spUnknown;
HRESULT hr = S_OK;
ULONG cPropSets = 0;
DBPROPSET* rgPropSets = NULL;
//Obtain the Aggregation argument
CAggregate* pCAggregate = NULL;
fAggregation = ::IsDlgButtonChecked(hWnd, IDB_AGGREGATION);
if(fAggregation)
pCAggregate = new CAggregate();
//Obtain the Output (ppIUnknown) argument
fOutput = ::IsDlgButtonChecked(hWnd, IDB_OUTPUT);
//Interface
REFIID riid = s_CComboInterface.GetGuid();
//Use Properties
fUseProps = ::IsDlgButtonChecked(hWnd, IDB_USEPROPERTIES);
if(fUseProps)
{
cPropSets = pThis->m_CDefPropSets.GetCount();
rgPropSets = pThis->m_CDefPropSets.GetPropSets();
}
//Obtain the selected Axis
ASSERT(pCDataset);
DBCOUNTITEM iAxis = s_comboAxis.GetCurSel();
//GetAxisRowset
if(SUCCEEDED(hr = pCDataset->GetAxisRowset(pCAggregate, iAxis, riid, cPropSets, rgPropSets, fOutput ? &spUnknown : NULL)))
{
//Now that we have the rowset, display it...
//NOTE: Can pontentially return other object types: (ie: CREATE_DETERMINE_TYPE)
if(!pThis->m_pCMainWindow->HandleObjectType(pCDataset, spUnknown, riid, eCRowset, 0, NULL, CREATE_NEWWINDOW | CREATE_DETERMINE_TYPE))
TESTC(hr = E_FAIL);
}
CLEANUP:
SAFE_RELEASE(pCAggregate);
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, TRUE);
return 0;
}
}
break;
}//WM_COMMAND
}//switch(message);
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetColInfoProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::GetColInfoProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
WCHAR wszBuffer[MAX_NAME_LEN+1];
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CDataAccess* pCDataAccess = NULL;
HRESULT hr = S_OK;
ULONG i=0;
DBORDINAL cColumns = 0;
DBCOLUMNINFO* rgColInfo = NULL;
WCHAR* pStringBuffer = NULL;
DBORDINAL cHiddenColumns = 0;
CColumnInfo rColumnInfo;
//Setup column headers
//We have 2 listviews.
// 1. Left - ColInfo types...
// 2. Right - All ColInfo for all columns
HWND hWndName = ::GetDlgItem(hWnd, IDL_NAMES);
HWND hWndCol = ::GetDlgItem(hWnd, IDL_VALUES);
HWND hWndHelp = ::GetDlgItem(hWnd, IDT_HELPMSG);
//Set Window Titles
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"IColumnsInfo::GetColumnInfo");
SendMessage(hWndHelp, WM_SETTEXT, 0, (LPARAM)"Displays the (meta-data) Column Information");
//Use Extended ListView Styles!
SendMessage(hWndName, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES);
SendMessage(hWndCol, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES);
//Set image list to the Table Window
ListView_SetImageList(hWndCol, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
ListView_SetImageList(hWndName, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
//Ensure this is a CDataAccess derived class...
pCDataAccess = SOURCE_GETOBJECT(pThis->m_pCSource, CDataAccess);
ASSERT(pCDataAccess);
//Now Obtain ColumnsInfo
TESTC(hr = pCDataAccess->GetColInfo(&cColumns, &rgColInfo, &pStringBuffer, &cHiddenColumns));
rColumnInfo.Attach(cColumns, rgColInfo, pStringBuffer, cHiddenColumns);
//We need to the ListView
//Headers/Columns contain ColInfo information
//Rows are per columns
//ListView NAMES
LV_InsertColumn(hWndName, 0, L"ColName");
LV_InsertItem(hWndName, 1, 0, L"Ordinal");
LV_InsertItem(hWndName, 2, 0, L"Type");
LV_InsertItem(hWndName, 3, 0, L"ColumnSize");
LV_InsertItem(hWndName, 4, 0, L"Precision");
LV_InsertItem(hWndName, 5, 0, L"Scale");
LV_InsertItem(hWndName, 6, 0, L"TypeInfo");
LV_InsertItem(hWndName, 7, 0, L"ColumnID");
LV_InsertItem(hWndName, 8, 0, L"dwFlags");
//Loop through the ColumnFlags
for(i=0; i<g_cColFlagsMaps; i++)
LV_InsertItem(hWndName, 9+i, 0, g_rgColFlagsMaps[i].pwszName);
//AutoSize column
SendMessage(hWndName, LVM_SETCOLUMNWIDTH, 0, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
for(i=0; i<cColumns; i++)
{
ASSERT(rgColInfo);
const DBCOLUMNINFO* pColInfo = &rColumnInfo[i];
//Column Header
LV_InsertColumn(hWndCol, i, GetColName(pColInfo), pCDataAccess->GetColumnImage(pColInfo)==IMAGE_LOCK ? IMAGE_LOCK : IMAGE_NONE);
//Ordinal (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Id", pColInfo->iOrdinal);
LV_InsertItem(hWndCol, 0, i, wszBuffer);
//TYPE (subitem)
LV_InsertItem(hWndCol, 1, i, GetDBTypeName(pColInfo->wType));
//ColumnSize (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", pColInfo->ulColumnSize);
LV_InsertItem(hWndCol, 2, i, wszBuffer);
//Precision (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pColInfo->bPrecision);
LV_InsertItem(hWndCol, 3, i, wszBuffer);
//Scale (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pColInfo->bScale);
LV_InsertItem(hWndCol, 4, i, wszBuffer);
//TypeInfo (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pColInfo->pTypeInfo);
LV_InsertItem(hWndCol, 5, i, wszBuffer);
//ColumnID (SubItem) DBID
DBIDToString(&pColInfo->columnid, wszBuffer, MAX_NAME_LEN);
LV_InsertItem(hWndCol, 6, i, wszBuffer);
//dwFlags
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%08x", pColInfo->dwFlags);
LV_InsertItem(hWndCol, 7, i, wszBuffer);
//FLAGS (SubItem)
for(ULONG iFlag=0; iFlag<g_cColFlagsMaps; iFlag++)
LV_InsertItem(hWndCol, 8+iFlag, i, NULL, PARAM_NONE, pColInfo->dwFlags & g_rgColFlagsMaps[iFlag].lItem ? IMAGE_CHECKED : IMAGE_UNCHECKED);
}
//AutoSize all columns
for(i=0; i<cColumns; i++)
SendMessage(hWndCol, LVM_SETCOLUMNWIDTH, (WPARAM)i, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
CLEANUP:
CenterDialog(hWnd);
if(FAILED(hr))
EndDialog(hWnd, FALSE);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
case WM_NOTIFY:
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)lParam;
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lParam;
//ListView
switch(pDispInfo->hdr.code)
{
//Since we have "TwoClickActive" on this will get sent
//Whenever a row is clicked on twice!
//This functionality used to be done with NM_DBCLK
case LVN_ITEMACTIVATE:
return 0;
case LVN_ITEMCHANGED:
{
HWND hWndName = ::GetDlgItem(hWnd, IDL_NAMES);
HWND hWndCol = ::GetDlgItem(hWnd, IDL_VALUES);
if(pNMListView->uNewState & LVNI_FOCUSED &&
pNMListView->uNewState & LVNI_SELECTED)
{
if(wParam == IDL_VALUES)
{
SyncSibling(hWndName, hWndCol);
return FALSE;
}
if(wParam == IDL_NAMES)
{
SyncSibling(hWndCol, hWndName);
return FALSE;
}
return UNHANDLED_MSG; //No return Value
}
}
}
}//WM_NOTIFY
}//switch message
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetNextRowsProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::GetNextRowsProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static LONG s_lOffset = 0; //Default to lOffset==0
static LONG s_cRows = 1; //Default to cRows==1
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
//Setup Window Handles
HWND hWndOffset = ::GetDlgItem(hWnd, IDE_OFFSET);
HWND hWndcRows = ::GetDlgItem(hWnd, IDE_COUNT);
//SetWindowTitle (default is Rowset::GetNextRows)
if(pThis->m_idSource == IDM_IROWSETLOCATE_GETROWSAT)
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"IRowsetLocate::GetRowsAt");
//Supply Defaults to the lOffset and cRows
wSendMessageFmt(hWndOffset, WM_SETTEXT, 0, L"%ld", s_lOffset);
wSendMessageFmt(hWndcRows, WM_SETTEXT, 0, L"%ld", s_cRows);
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CRowset* pCRowset = SOURCE_GETOBJECT(pThis->m_pCSource, CRowset);
CDataGrid* pCDataGrid = pThis->m_pCDataGrid;
HRESULT hr = S_OK;
//Setup Window Handles
HWND hWndOffset = ::GetDlgItem(hWnd, IDE_OFFSET);
HWND hWndcRows = ::GetDlgItem(hWnd, IDE_COUNT);
//Obtain Defaults to the lOffset and cRows
GetEditBoxValue(hWndOffset, &s_lOffset);
GetEditBoxValue(hWndcRows, &s_cRows);
switch(pThis->m_idSource)
{
case IDM_GETNEXTROWS:
{
//Display the indicated rows
TESTC(hr = pCDataGrid->GetNextRows(s_lOffset, s_cRows));
break;
}
case IDM_IROWSETLOCATE_GETROWSAT:
{
INDEX cSelItems = 0;
INDEX* rgSelItems = 0;
HROW* rghRowsSel = NULL;
DBBKMARK cbBookmark = 0;
BYTE* pBookmark = NULL;
DBCOUNTITEM cRowsObtained = 0;
HROW* rghRows = NULL;
//Obtain all Selected Rows
LV_GetSelItems(pCDataGrid->m_hWnd, &cSelItems, &rgSelItems, (LPARAM**)&rghRowsSel);
//Obtain the bookmark for the first row selected...
if(cSelItems)
hr = pCRowset->GetBookmark(rghRowsSel[0], &cbBookmark, &pBookmark);
//Release previously fetched rows, (if user requested)
hr = pCDataGrid->ReleaseHeldRows();
//IRowsetLocate::GetRowsAt
XTEST(hr = pCRowset->m_pIRowsetLocate->GetRowsAt(pCRowset->m_hChapter, NULL, cbBookmark, pBookmark, s_lOffset, s_cRows, &cRowsObtained, &rghRows));
TRACE_METHOD(hr, L"IRowsetLocate::GetRowsAt(0x%p, NULL, %Iu, 0x%p, %ld, %ld, &%Iu, &0x%p)", pCRowset->m_hChapter, cbBookmark, pBookmark, s_lOffset, s_cRows, cRowsObtained, rghRows);
//Display the rows retrieved...
//NOTE: GetRowsAt has a much simplier starting for than GetNextRows. Its basically
//the bookmark + offset = starting row. Whereas GetNextRows also depends upon
//what the last fetch direction was, forward or backward.
pCDataGrid->DisplayRows(rgSelItems[0] + s_lOffset, s_cRows, cRowsObtained, rghRows, FALSE/*fAdjustFetchPosition*/);
//Cleanup
SAFE_FREE(rgSelItems);
SAFE_FREE(rghRowsSel);
SAFE_FREE(rghRows);
SAFE_FREE(pBookmark);
break;
}
};
CLEANUP:
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
case WM_NOTIFY:
{
NM_UPDOWN* pUpDown = (NM_UPDOWN*)lParam;
//lOffset
if(pUpDown->hdr.idFrom == IDC_SPIN_OFFSET)
{
s_lOffset += pUpDown->iDelta;
wSendMessageFmt(::GetDlgItem(hWnd, IDE_OFFSET), WM_SETTEXT, 0, L"%ld", s_lOffset);
}
//cRows
if(pUpDown->hdr.idFrom == IDC_SPIN_COUNT)
{
s_cRows += pUpDown->iDelta;
wSendMessageFmt(::GetDlgItem(hWnd, IDE_COUNT), WM_SETTEXT, 0, L"%ld", s_cRows);
}
break;
}//WM_NOTIFY
}//switch message
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetBindingsProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::GetBindingsProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
WCHAR wszBuffer[MAX_NAME_LEN+1];
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
HRESULT hr = S_OK;
//Determine which object this is called from
CDataAccess* pCDataAccess = SOURCE_GETOBJECT(pThis->m_pCSource, CDataAccess);
ASSERT(pCDataAccess);
ULONG i = 0;
DBCOUNTITEM cBindings = 0;
DBBINDING* rgBindings = NULL;
DBACCESSORFLAGS dwAccessorFlags = 0;
//Setup column headers
HWND hWndName = ::GetDlgItem(hWnd, IDL_NAMES);
HWND hWndValue = ::GetDlgItem(hWnd, IDL_VALUES);
HWND hWndHelp = ::GetDlgItem(hWnd, IDT_HELPMSG);
//Set Window Titles
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"IAccessor::GetBindings");
SendMessage(hWndHelp, WM_SETTEXT, 0, (LPARAM)"Displays the rgBindings from the Accessor");
//Use Extended ListView Styles!
SendMessage(hWndName, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE);
SendMessage(hWndValue, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE);
//Set image list to the Window
ListView_SetImageList(hWndName, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
ListView_SetImageList(hWndValue, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
//Now IAccessor::GetBindings
ASSERT(pCDataAccess->m_pIAccessor);
XTEST(hr = pCDataAccess->m_pIAccessor->GetBindings(pCDataAccess->m_hAccessor, &dwAccessorFlags, &cBindings, &rgBindings));
TESTC(TRACE_METHOD(hr, L"IAccessor::GetBindings(0x%p, &0x%08x, &%lu, &0x%p)", pCDataAccess->m_hAccessor, dwAccessorFlags, cBindings, rgBindings));
//We need to the ListView
//Headers/Columns contain ColInfo information
//Rows are per columns
//ListView Columns
LV_InsertColumn(hWndName, 0, L"ColName");
LV_InsertItem(hWndName, 0, 0, L"Ordinal");
LV_InsertItem(hWndName, 1, 0, L"obValue");
LV_InsertItem(hWndName, 2, 0, L"obLength");
LV_InsertItem(hWndName, 3, 0, L"obStatus");
LV_InsertItem(hWndName, 4, 0, L"pTypeInfo");
LV_InsertItem(hWndName, 5, 0, L"pObject");
LV_InsertItem(hWndName, 6, 0, L"pBindExt");
LV_InsertItem(hWndName, 7, 0, L"dwPart");
LV_InsertItem(hWndName, 8, 0, L"dwMemOwner");
LV_InsertItem(hWndName, 9, 0, L"eParamIO");
LV_InsertItem(hWndName, 10, 0, L"cbMaxLen");
LV_InsertItem(hWndName, 11, 0, L"dwFlags");
LV_InsertItem(hWndName, 12, 0, L"wType");
LV_InsertItem(hWndName, 13, 0, L"bPrecision");
LV_InsertItem(hWndName, 14, 0, L"bScale");
//AutoSize column
SendMessage(hWndName, LVM_SETCOLUMNWIDTH, 0, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
for(i=0; i<cBindings; i++)
{
ASSERT(rgBindings);
const DBBINDING* pBinding = &rgBindings[i];
const DBCOLUMNINFO* pColInfo = pCDataAccess->m_ColumnInfo.GetOrdinal(pBinding->iOrdinal);
//Column Header
LV_InsertColumn(hWndValue, i, GetColName(pColInfo), pCDataAccess->GetColumnImage(pColInfo)==IMAGE_LOCK ? IMAGE_LOCK : IMAGE_NONE);
//Ordinal (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Id", pBinding->iOrdinal);
LV_InsertItem(hWndValue, 0, i, wszBuffer);
//obValue (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->obValue);
LV_InsertItem(hWndValue, 1, i, wszBuffer);
//obLength (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->obLength);
LV_InsertItem(hWndValue, 2, i, wszBuffer);
//obStatus (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->obStatus);
LV_InsertItem(hWndValue, 3, i, wszBuffer);
//pTypeInfo (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->pTypeInfo);
LV_InsertItem(hWndValue, 4, i, wszBuffer);
//pObject (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->pObject);
LV_InsertItem(hWndValue, 5, i, wszBuffer);
//pBindExt (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->pBindExt);
LV_InsertItem(hWndValue, 6, i, wszBuffer);
//dwPart (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%08x", pBinding->dwPart);
LV_InsertItem(hWndValue, 7, i, wszBuffer);
//dwMemOwner (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%08x", pBinding->dwMemOwner);
LV_InsertItem(hWndValue, 8, i, wszBuffer);
//eParamIO (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pBinding->eParamIO);
LV_InsertItem(hWndValue, 9, i, wszBuffer);
//cbMaxLen (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", pBinding->cbMaxLen);
LV_InsertItem(hWndValue, 10, i, wszBuffer);
//dwFlags (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%08x", pBinding->dwFlags);
LV_InsertItem(hWndValue, 11, i, wszBuffer);
//TYPE (subitem)
LV_InsertItem(hWndValue, 12, i, GetDBTypeName(pBinding->wType));
//Precision (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pBinding->bPrecision);
LV_InsertItem(hWndValue, 13, i, wszBuffer);
//Scale (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pBinding->bScale);
LV_InsertItem(hWndValue, 14, i, wszBuffer);
}
//AutoSize all columns
for(i=0; i<cBindings; i++)
SendMessage(hWndValue, LVM_SETCOLUMNWIDTH, (WPARAM)i, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
CLEANUP:
CenterDialog(hWnd);
FreeBindings(&cBindings, &rgBindings);
if(FAILED(hr))
EndDialog(hWnd, FALSE);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
case WM_NOTIFY:
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)lParam;
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lParam;
//ListView
switch(pDispInfo->hdr.code)
{
//Since we have "TwoClickActive" on this will get sent
//Whenever a row is clicked on twice!
//This functionality used to be done with NM_DBCLK
case LVN_ITEMACTIVATE:
return 0;
case LVN_ITEMCHANGED:
{
HWND hWndName = ::GetDlgItem(hWnd, IDL_NAMES);
HWND hWndValue = ::GetDlgItem(hWnd, IDL_VALUES);
if(pNMListView->uNewState & LVNI_FOCUSED &&
pNMListView->uNewState & LVNI_SELECTED)
{
if(wParam == IDL_VALUES)
{
SyncSibling(hWndName, hWndValue);
return FALSE;
}
if(wParam == IDL_NAMES)
{
SyncSibling(hWndValue, hWndName);
return FALSE;
}
return UNHANDLED_MSG; //No return Value
}
}
}
}//WM_NOTIFY
}//switch message
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::CreateAccessorProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::CreateAccessorProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//Bindings
static DBCOUNTITEM cBindings = 0;
static DBBINDING* rgBindings = NULL;
static DBLENGTH cbRowSize = 0;
static BOOL s_bClearAll = TRUE;
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
WCHAR wszBuffer[MAX_NAME_LEN+1];
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
//Which object are we calling this from
CDataAccess* pCDataAccess = SOURCE_GETOBJECT(pThis->m_pCSource, CDataAccess);
ASSERT(pCDataAccess);
HRESULT hr = S_OK;
//Setup column headers
HWND hWndValue = ::GetDlgItem(hWnd, IDL_COLUMNS);
s_bClearAll = TRUE;
//Use Extended ListView Styles!
SendMessage(hWndValue, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_CHECKBOXES, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_CHECKBOXES);
//Set image list to the Window
ListView_SetImageList(hWndValue, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
ListView_SetImageList(hWndValue, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_STATE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_STATE);
//Setup Bindings
pCDataAccess->GetColInfo();
pCDataAccess->SetupBindings(BIND_ALLCOLS, &cBindings, &rgBindings, &cbRowSize);
//We need to the ListView
//Headers/Columns contain ColInfo information
//Rows are per columns
//ListView Columns
LV_InsertColumn(hWndValue, 0, L"ColName");
LV_InsertColumn(hWndValue, 1, L"Ordinal");
LV_InsertColumn(hWndValue, 2, L"obValue");
LV_InsertColumn(hWndValue, 3, L"obLength");
LV_InsertColumn(hWndValue, 4, L"obStatus");
LV_InsertColumn(hWndValue, 5, L"pTypeInfo");
LV_InsertColumn(hWndValue, 6, L"pObject");
LV_InsertColumn(hWndValue, 7, L"pBindExt");
LV_InsertColumn(hWndValue, 8, L"dwPart");
LV_InsertColumn(hWndValue, 9, L"dwMemOwner");
LV_InsertColumn(hWndValue, 10, L"eParamIO");
LV_InsertColumn(hWndValue, 11, L"cbMaxLen");
LV_InsertColumn(hWndValue, 12, L"dwFlags");
LV_InsertColumn(hWndValue, 13, L"wType");
LV_InsertColumn(hWndValue, 14, L"bPrecision");
LV_InsertColumn(hWndValue, 15, L"bScale");
ULONG i;
for(i=0; i<cBindings; i++)
{
ASSERT(rgBindings);
const DBBINDING* pBinding = &rgBindings[i];
const DBCOLUMNINFO* pColInfo = pCDataAccess->m_ColumnInfo.GetOrdinal(pBinding->iOrdinal);
//Column Header
LV_InsertItem(hWndValue, i, 0, GetColName(pColInfo), PARAM_NONE, pCDataAccess->GetColumnImage(pColInfo)==IMAGE_LOCK ? IMAGE_LOCK : IMAGE_NONE);
//Ordinal (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Id", pBinding->iOrdinal);
LV_InsertItem(hWndValue, i, 1, wszBuffer);
//obValue (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->obValue);
LV_InsertItem(hWndValue, i, 2, wszBuffer);
//obLength (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->obLength);
LV_InsertItem(hWndValue, i, 3, wszBuffer);
//obStatus (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->obStatus);
LV_InsertItem(hWndValue, i, 4, wszBuffer);
//pTypeInfo (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->pTypeInfo);
LV_InsertItem(hWndValue, i, 5, wszBuffer);
//pObject (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->pObject);
LV_InsertItem(hWndValue, i, 6, wszBuffer);
//pBindExt (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pBinding->pBindExt);
LV_InsertItem(hWndValue, i, 7, wszBuffer);
//dwPart (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%08x", pBinding->dwPart);
LV_InsertItem(hWndValue, i, 8, wszBuffer);
//dwMemOwner (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%08x", pBinding->dwMemOwner);
LV_InsertItem(hWndValue, i, 9, wszBuffer);
//eParamIO (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pBinding->eParamIO);
LV_InsertItem(hWndValue, i, 10, wszBuffer);
//cbMaxLen (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", pBinding->cbMaxLen);
LV_InsertItem(hWndValue, i, 11, wszBuffer);
//dwFlags (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%08x", pBinding->dwFlags);
LV_InsertItem(hWndValue, i, 12, wszBuffer);
//TYPE (subitem)
LV_InsertItem(hWndValue, i, 13, GetDBTypeName(pBinding->wType));
//Precision (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pBinding->bPrecision);
LV_InsertItem(hWndValue, i, 14, wszBuffer);
//Scale (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pBinding->bScale);
LV_InsertItem(hWndValue, i, 15, wszBuffer);
//Default to unchecked
LV_SetItemState(hWndValue, i, 0, INDEXTOSTATEIMAGEMASK(STATE_UNCHECKED), LVIS_STATEIMAGEMASK);
}
//Go through and check the existing columns, that are in our current bindings
for(i=0; i<pCDataAccess->m_Bindings.GetCount(); i++)
{
DBORDINAL iOrdinal = pCDataAccess->m_Bindings[i].iOrdinal;
DBORDINAL iIndex = (iOrdinal && !pCDataAccess->m_ColumnInfo[0].iOrdinal==0) ? iOrdinal-1 : iOrdinal;
LV_SetItemState(hWndValue, (INDEX)iIndex, 0, INDEXTOSTATEIMAGEMASK(STATE_CHECKED), LVIS_STATEIMAGEMASK);
}
//AutoSize columns (column headers);
for(i=0; i<=15; i++)
SendMessage(hWndValue, LVM_SETCOLUMNWIDTH, i, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
CenterDialog(hWnd);
if(FAILED(hr))
{
//Free Bindings
FreeBindings(&cBindings, &rgBindings);
EndDialog(hWnd, FALSE);
}
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
//Which object are we calling this from
CDataAccess* pCDataAccess = SOURCE_GETOBJECT(pThis->m_pCSource, CDataAccess);
ASSERT(pCDataAccess);
DBCOUNTITEM cSelBindings = 0;
DBBINDING* rgSelBindings = NULL;
HWND hWndValue = ::GetDlgItem(hWnd, IDL_COLUMNS);
HACCESSOR hAccessor = NULL;
DBACCESSORFLAGS dwAccessorFlags = DBACCESSOR_ROWDATA;
INDEX i=0;
HRESULT hr = S_OK;
//Now that the user has selected all the columns they wish to
//have in the Accessor, we need to loop through all the
//checked columns and add them to our list...
INDEX cItems = (INDEX)SendMessage(hWndValue, LVM_GETITEMCOUNT, 0, 0);
SAFE_ALLOC(rgSelBindings, DBBINDING, cItems);
for(i=0; i<cItems; i++)
{
//Get the Image
BOOL bChecked = LV_GetItemState(hWndValue, i, LVIS_STATEIMAGEMASK) & INDEXTOSTATEIMAGEMASK(STATE_CHECKED);
//Only interested in checked items
if(!bChecked)
continue;
ASSERT(cBindings);
ASSERT(rgBindings);
//Mark this Ordinal as checked
CopyBinding(&rgSelBindings[cSelBindings], &rgBindings[i]);
cSelBindings++;
}
//Now that we have the columns, Create the Accessor
hr = pCDataAccess->CreateAccessor(dwAccessorFlags, cSelBindings, rgSelBindings, 0, &hAccessor);
//Free Bindings
FreeBindings(&cBindings, &rgBindings);
if(SUCCEEDED(hr))
{
//Release Previous Accessor
pCDataAccess->ReleaseAccessor(&pCDataAccess->m_hAccessor);
//Use the new Bindings
pCDataAccess->m_hAccessor = hAccessor;
pCDataAccess->m_cbRowSize = cbRowSize;
pCDataAccess->m_Bindings.Attach(cSelBindings, rgSelBindings);
//The new bindings may not be the same size as our original
//Or might not have existined original if AutiQI was off...
SAFE_REALLOC(pCDataAccess->m_pData, BYTE, cbRowSize);
//Now actually refetch the Data with the new Accessor
if(SUCCEEDED(hr = pThis->m_pCDataGrid->RestartPosition()))
hr = pThis->m_pCDataGrid->RefreshData();
EndDialog(hWnd, TRUE);
return 0;
}
CLEANUP:
//Free Bindings
FreeBindings(&cBindings, &rgBindings);
FreeBindings(&cSelBindings, &rgSelBindings);
return 0;
}
case IDCANCEL:
{
//Free Bindings
FreeBindings(&cBindings, &rgBindings);
EndDialog(hWnd, FALSE);
return 0;
}
case IDB_CLEARALL:
{
HWND hWndValue = ::GetDlgItem(hWnd, IDL_COLUMNS);
//Now that the user has selected to select all columns
//We need to loop through all the unchecked and check them...
INDEX cItems = (INDEX)SendMessage(hWndValue, LVM_GETITEMCOUNT, 0, 0);
for(INDEX i=0; i<cItems; i++)
{
//Check the property state
LV_SetItemState(hWndValue, i, 0, INDEXTOSTATEIMAGEMASK(s_bClearAll ? STATE_UNCHECKED : STATE_CHECKED), LVIS_STATEIMAGEMASK);
}
//Clear All is a toggle...
if(s_bClearAll)
{
s_bClearAll = FALSE;
::SetWindowText(::GetDlgItem(hWnd, IDB_CLEARALL), "SelectAll");
}
else
{
s_bClearAll = TRUE;
::SetWindowText(::GetDlgItem(hWnd, IDB_CLEARALL), "ClearAll");
}
return 0;
}
}
break;
}//WM_COMMAND
}//switch message
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::SetParameterInfoProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::SetParameterInfoProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static DWORD dwSavedFlags = 0;
static INDEX iSavedName = CB_ERR;
static CComboBoxLite s_CComboTypes;
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
INDEX iSel = 0;
HRESULT hr = S_OK;
//Controls
HWND hWndOrdinal = ::GetDlgItem(hWnd, IDE_ORDINAL);
HWND hWndParamName = ::GetDlgItem(hWnd, IDC_NAME);
HWND hWndFlags = ::GetDlgItem(hWnd, IDL_FLAGS);
//Set Ordinal
SendMessage(hWndOrdinal, WM_SETTEXT, 0, (LPARAM)"1");
//Set Parameter Name
SendMessage(hWndParamName, CB_ADDSTRING, 0, (LPARAM)"<NULL>");
iSel = (INDEX)SendMessage(hWndParamName, CB_ADDSTRING, 0, (LPARAM)"Parameter1");
iSavedName = (INDEX)SendMessage(hWndParamName, CB_SETCURSEL, iSavedName!=CB_ERR ? iSavedName : iSel, 0);
//Add support for indicating NULL
s_CComboTypes.CreateIndirect(hWnd, IDC_TYPE);
s_CComboTypes.AddString(L"<NULL>");
//Fill in Combo with "Standard" Defined Type Names (defined in SetParameterInfo)
//NOTE: We could just use the DBTYPE list (g_rgDBTypes), but that gives many
//confusing types (DBTYPE_STR) which people are apt to use but are not standard
//so currently no provider supports them. So just list all those defined by the spec
//and the combo box allows the user to enter other (not in the list)
s_CComboTypes.AddString(L"DBTYPE_I1");
s_CComboTypes.AddString(L"DBTYPE_I2");
s_CComboTypes.AddString(L"DBTYPE_I4");
s_CComboTypes.AddString(L"DBTYPE_I8");
s_CComboTypes.AddString(L"DBTYPE_UI1");
s_CComboTypes.AddString(L"DBTYPE_UI2");
s_CComboTypes.AddString(L"DBTYPE_UI4");
s_CComboTypes.AddString(L"DBTYPE_UI8");
s_CComboTypes.AddString(L"DBTYPE_R4");
s_CComboTypes.AddString(L"DBTYPE_R8");
s_CComboTypes.AddString(L"DBTYPE_CY");
s_CComboTypes.AddString(L"DBTYPE_DECIMAL");
s_CComboTypes.AddString(L"DBTYPE_NUMERIC");
s_CComboTypes.AddString(L"DBTYPE_BOOL");
s_CComboTypes.AddString(L"DBTYPE_ERROR");
s_CComboTypes.AddString(L"DBTYPE_UDT");
s_CComboTypes.AddString(L"DBTYPE_VARIANT");
s_CComboTypes.AddString(L"DBTYPE_IDISPATCH");
s_CComboTypes.AddString(L"DBTYPE_IUNKNOWN");
s_CComboTypes.AddString(L"DBTYPE_GUID");
s_CComboTypes.AddString(L"DBTYPE_DATE");
s_CComboTypes.AddString(L"DBTYPE_DBDATE");
s_CComboTypes.AddString(L"DBTYPE_DBTIME");
s_CComboTypes.AddString(L"DBTYPE_DBTIMESTAMP");
s_CComboTypes.AddString(L"DBTYPE_BSTR");
s_CComboTypes.AddString(L"DBTYPE_CHAR");
iSel = s_CComboTypes.AddString(L"DBTYPE_VARCHAR");
s_CComboTypes.AddString(L"DBTYPE_LONGVARCHAR");
s_CComboTypes.AddString(L"DBTYPE_WCHAR");
s_CComboTypes.AddString(L"DBTYPE_WVARCHAR");
s_CComboTypes.AddString(L"DBTYPE_WLONGVARCHAR");
s_CComboTypes.AddString(L"DBTYPE_BINARY");
s_CComboTypes.AddString(L"DBTYPE_VARBINARY");
s_CComboTypes.AddString(L"DBTYPE_LONGVARBINARY");
s_CComboTypes.AddString(L"DBTYPE_FILENAME");
s_CComboTypes.AddString(L"DBTYPE_VARNUMERIC");
s_CComboTypes.AddString(L"DBTYPE_PROPVARIANT");
//Set current Selection
if(s_CComboTypes.RestoreSelection() == CB_ERR)
s_CComboTypes.SetCurSel(iSel);
const static WIDENAMEMAP g_rgParamFlags[] =
{
VALUE_WCHAR(DBPARAMFLAGS_ISINPUT),
VALUE_WCHAR(DBPARAMFLAGS_ISOUTPUT),
VALUE_WCHAR(DBPARAMFLAGS_ISSIGNED),
VALUE_WCHAR(DBPARAMFLAGS_ISNULLABLE),
VALUE_WCHAR(DBPARAMFLAGS_ISLONG),
VALUE_WCHAR(DBPARAMFLAGS_SCALEISNEGATIVE),
};
//Populate the Flags ListBox
SendMessage(hWndFlags, LB_RESETCONTENT, 0, 0);
for(ULONG i=0; i<NUMELE(g_rgParamFlags); i++)
{
INDEX iSel = (INDEX)wSendMessage(hWndFlags, LB_ADDSTRING, 0, g_rgParamFlags[i].pwszName);
SendMessage(hWndFlags, LB_SETITEMDATA, iSel, (LPARAM)g_rgParamFlags[i].lItem);
//Reselect all previously selected items...
SendMessage(hWndFlags, LB_SETSEL, (dwSavedFlags & g_rgParamFlags[i].lItem) == (DWORD)g_rgParamFlags[i].lItem, i);
}
//Send a selection change to the ComboBox so it updates everything
//Size, Precision, and Scale
SendMessage(hWnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDC_TYPE, hWnd, CBN_SELCHANGE));
CenterDialog(hWnd);
if(FAILED(hr))
EndDialog(hWnd, FALSE);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
//CBN_SELCHANGE
switch(GET_WM_COMMAND_CMD(wParam, lParam))
{
//Selection change in a combo box occurred
case CBN_SELCHANGE:
{
//See which combo box has changed
switch(GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_TYPE:
{
WCHAR wszBuffer[MAX_NAME_LEN+1];
HWND hWndSize = ::GetDlgItem(hWnd, IDE_SIZE);
HWND hWndPrecision = ::GetDlgItem(hWnd, IDE_PRECISION);
HWND hWndScale = ::GetDlgItem(hWnd, IDE_SCALE);
//Get the Selected Type
s_CComboTypes.GetSelText(wszBuffer, MAX_NAME_LEN);
DBTYPE wType = GetDBType(wszBuffer);
s_CComboTypes.SaveSelection();
//Get Default Size,Prec,Scale for this type...
DBLENGTH ulMaxSize = 0;
BYTE bPrecision, bScale;
GetDBTypeMaxSize(wType, &ulMaxSize, &bPrecision, &bScale);
//Set Size
wSendMessageFmt(hWndSize, WM_SETTEXT, 0, L"%lu", ulMaxSize!=0 ? ulMaxSize : 255);
//Set Precision
wSendMessageFmt(hWndPrecision, WM_SETTEXT, 0, L"%d", bPrecision);
//Set Scale
wSendMessageFmt(hWndScale, WM_SETTEXT, 0, L"%d", bScale);
return 0;
}
}
break;
}
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CCommand* pCCommand = SOURCE_GETOBJECT(pThis->m_pCSource, CCommand);
WCHAR wszNameBuffer[MAX_NAME_LEN];
WCHAR wszTypeBuffer[MAX_NAME_LEN];
HRESULT hr = S_OK;
//Controls
HWND hWndOrdinal = ::GetDlgItem(hWnd, IDE_ORDINAL);
HWND hWndFlags = ::GetDlgItem(hWnd, IDL_FLAGS);
HWND hWndSize = ::GetDlgItem(hWnd, IDE_SIZE);
HWND hWndPrecision = ::GetDlgItem(hWnd, IDE_PRECISION);
HWND hWndScale = ::GetDlgItem(hWnd, IDE_SCALE);
LONG lValue = 0;
ULONG cParams = 0;
//Alloc Params
cParams = 1;
DB_UPARAMS ulParamOrdinal = 0;
DBPARAMBINDINFO dbParamBindInfo;
//Setup ParamBindInfo
CComboBoxLite comboParamName(hWnd, IDC_NAME);
iSavedName = comboParamName.GetSelText(wszNameBuffer, MAX_NAME_LEN);
dbParamBindInfo.pwszName = iSavedName == 0 ? NULL : wszNameBuffer;
GetEditBoxValue(hWndOrdinal, &lValue, 0/*Min*/);
ulParamOrdinal = lValue;
GetEditBoxValue(hWndSize, &lValue, 0/*Min*/);
dbParamBindInfo.ulParamSize = lValue;
GetEditBoxValue(hWndPrecision, &lValue, 0, UCHAR_MAX);
dbParamBindInfo.bPrecision = (BYTE)lValue;
GetEditBoxValue(hWndScale, &lValue, 0, UCHAR_MAX);
dbParamBindInfo.bScale = (BYTE)lValue;
//Get TypeName
INDEX iSel = s_CComboTypes.GetSelText(wszTypeBuffer, MAX_NAME_LEN);
dbParamBindInfo.pwszDataSourceType = iSel == 0 ? NULL : wszTypeBuffer;
//Obtain all Flags Selected Items...
INDEX iSelCount = (INDEX)SendMessage(hWndFlags, LB_GETSELCOUNT, 0, 0);
ASSERT(iSelCount < 20);
LONG rgSelItems[20];
SendMessage(hWndFlags, LB_GETSELITEMS, (WPARAM)20, (LPARAM)rgSelItems);
dwSavedFlags = 0;
for(LONG i=0; i<iSelCount; i++)
dwSavedFlags |= SendMessage(hWndFlags, LB_GETITEMDATA, rgSelItems[i], 0);
dbParamBindInfo.dwFlags = dwSavedFlags;
//SetParameterInfo
ASSERT(pCCommand->m_pICommandWithParameters);
XTEST(hr = pCCommand->m_pICommandWithParameters->SetParameterInfo(cParams, &ulParamOrdinal, &dbParamBindInfo));
TESTC(TRACE_METHOD(hr, L"ICommandWithParameters::SetParameterInfo(%lu, &%Id, 0x%p)", cParams, ulParamOrdinal, &dbParamBindInfo));
CLEANUP:
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
case IDB_RESET:
{
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CCommand* pCCommand = SOURCE_GETOBJECT(pThis->m_pCSource, CCommand);
HRESULT hr = S_OK;
//SetParameterInfo
ASSERT(pCCommand->m_pICommandWithParameters);
XTEST(hr = pCCommand->m_pICommandWithParameters->SetParameterInfo(0, NULL, NULL));
TRACE_METHOD(hr, L"ICommandWithParameters::SetParameterInfo(0, NULL, NULL)");
return 0;
}
}
break;
}//WM_COMMAND
}//switch message
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetParameterInfoProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::GetParameterInfoProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
WCHAR wszBuffer[MAX_NAME_LEN+1];
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CCommand* pCCommand = SOURCE_GETOBJECT(pThis->m_pCSource, CCommand);
HRESULT hr = S_OK;
ULONG i = 0;
DB_UPARAMS cParams = 0;
DBPARAMINFO* rgParamInfo = NULL;
WCHAR* pwszNamesBuffer = NULL;
//Setup column headers
HWND hWndName = ::GetDlgItem(hWnd, IDL_NAMES);
HWND hWndValue = ::GetDlgItem(hWnd, IDL_VALUES);
HWND hWndHelp = ::GetDlgItem(hWnd, IDT_HELPMSG);
//Set Window Titles
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"ICommandWithParameters::GetParameterInfo");
SendMessage(hWndHelp, WM_SETTEXT, 0, (LPARAM)"ParameterInfo");
//Use Extended ListView Styles!
SendMessage(hWndName, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE);
SendMessage(hWndValue, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE);
//Set image list to the Window
ListView_SetImageList(hWndValue, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
ListView_SetImageList(hWndName, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
//Now ICommandWithParameters::GetParameterInfo
XTESTC(hr = pCCommand->GetParameterInfo(&cParams, &rgParamInfo, &pwszNamesBuffer));
//We need to the ListView
//Headers/Columns contain ColInfo information
//Rows are per columns
//ListView Columns
LV_InsertColumn(hWndName, 0, L"ParamName");
LV_InsertItem(hWndName, 0, 0, L"Ordinal");
LV_InsertItem(hWndName, 1, 0, L"dwFlags");
LV_InsertItem(hWndName, 2, 0, L"pTypeInfo");
LV_InsertItem(hWndName, 3, 0, L"wType");
LV_InsertItem(hWndName, 4, 0, L"ulParamSize");
LV_InsertItem(hWndName, 5, 0, L"bPrecision");
LV_InsertItem(hWndName, 6, 0, L"bScale");
//AutoSize column
SendMessage(hWndName, LVM_SETCOLUMNWIDTH, 0, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
for(i=0; i<cParams; i++)
{
ASSERT(rgParamInfo);
DBPARAMINFO* pParamInfo = &rgParamInfo[i];
//Column Header
LV_InsertColumn(hWndValue, i, pParamInfo->pwszName, IMAGE_NONE);
//Ordinal (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Id", pParamInfo->iOrdinal);
LV_InsertItem(hWndValue, 0, i, wszBuffer);
//dwFlags (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%08x", pParamInfo->dwFlags);
LV_InsertItem(hWndValue, 1, i, wszBuffer);
//pTypeInfo (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", pParamInfo->pTypeInfo);
LV_InsertItem(hWndValue, 2, i, wszBuffer);
//TYPE (subitem)
LV_InsertItem(hWndValue, 3, i, GetDBTypeName(pParamInfo->wType));
//ulParamSize (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", pParamInfo->ulParamSize);
LV_InsertItem(hWndValue, 4, i, wszBuffer);
//Precision (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pParamInfo->bPrecision);
LV_InsertItem(hWndValue, 5, i, wszBuffer);
//Scale (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pParamInfo->bScale);
LV_InsertItem(hWndValue, 6, i, wszBuffer);
}
//AutoSize all columns
for(i=0; i<cParams; i++)
SendMessage(hWndValue, LVM_SETCOLUMNWIDTH, (WPARAM)i, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
CLEANUP:
CenterDialog(hWnd);
SAFE_FREE(rgParamInfo);
SAFE_FREE(pwszNamesBuffer);
if(FAILED(hr))
EndDialog(hWnd, FALSE);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
case WM_NOTIFY:
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)lParam;
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lParam;
//ListView
switch(pDispInfo->hdr.code)
{
//Since we have "TwoClickActive" on this will get sent
//Whenever a row is clicked on twice!
//This functionality used to be done with NM_DBCLK
case LVN_ITEMACTIVATE:
return 0;
case LVN_ITEMCHANGED:
{
HWND hWndName = ::GetDlgItem(hWnd, IDL_NAMES);
HWND hWndValue = ::GetDlgItem(hWnd, IDL_VALUES);
if(pNMListView->uNewState & LVNI_FOCUSED &&
pNMListView->uNewState & LVNI_SELECTED)
{
if(wParam == IDL_VALUES)
{
SyncSibling(hWndName, hWndValue);
return FALSE;
}
if(wParam == IDL_NAMES)
{
SyncSibling(hWndValue, hWndName);
return FALSE;
}
return UNHANDLED_MSG; //No return Value
}
}
}
}//WM_NOTIFY
}//switch message
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetLiteralInfoProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::GetLiteralInfoProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
WCHAR wszBuffer[MAX_NAME_LEN+1];
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
IDBInfo* pIDBInfo = SOURCE_GETINTERFACE(pThis->m_pCSource, IDBInfo);
HRESULT hr = S_OK;
ULONG i,cLiteralInfo = 0;
DBLITERALINFO* rgLiteralInfo = NULL;
WCHAR* pStringBuffer = NULL;
//Setup column headers
HWND hWndLiterals = ::GetDlgItem(hWnd, IDL_VALUES);
HWND hWndNames = ::GetDlgItem(hWnd, IDL_NAMES);
HWND hWndHelp = ::GetDlgItem(hWnd, IDT_HELPMSG);
//Set Window Titles
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"IDBInfo::GetLiteralInfo");
SendMessage(hWndHelp, WM_SETTEXT, 0, (LPARAM)"Information about literals used in text DDL");
const static WIDENAMEMAP rgLiterals[] =
{
VALUE_WCHAR(DBLITERAL_INVALID ),
VALUE_WCHAR(DBLITERAL_BINARY_LITERAL ),
VALUE_WCHAR(DBLITERAL_CATALOG_NAME ),
VALUE_WCHAR(DBLITERAL_CATALOG_SEPARATOR ),
VALUE_WCHAR(DBLITERAL_CHAR_LITERAL ),
VALUE_WCHAR(DBLITERAL_COLUMN_ALIAS ),
VALUE_WCHAR(DBLITERAL_COLUMN_NAME ),
VALUE_WCHAR(DBLITERAL_CORRELATION_NAME ),
VALUE_WCHAR(DBLITERAL_CURSOR_NAME ),
VALUE_WCHAR(DBLITERAL_ESCAPE_PERCENT_PREFIX ),
VALUE_WCHAR(DBLITERAL_ESCAPE_PERCENT_SUFFIX ),
VALUE_WCHAR(DBLITERAL_ESCAPE_UNDERSCORE_PREFIX ),
VALUE_WCHAR(DBLITERAL_ESCAPE_UNDERSCORE_SUFFIX ),
VALUE_WCHAR(DBLITERAL_INDEX_NAME ),
VALUE_WCHAR(DBLITERAL_LIKE_PERCENT ),
VALUE_WCHAR(DBLITERAL_LIKE_UNDERSCORE ),
VALUE_WCHAR(DBLITERAL_PROCEDURE_NAME ),
VALUE_WCHAR(DBLITERAL_QUOTE_PREFIX ),
VALUE_WCHAR(DBLITERAL_SCHEMA_NAME ),
VALUE_WCHAR(DBLITERAL_TABLE_NAME ),
VALUE_WCHAR(DBLITERAL_TEXT_COMMAND ),
VALUE_WCHAR(DBLITERAL_USER_NAME ),
VALUE_WCHAR(DBLITERAL_VIEW_NAME ),
VALUE_WCHAR(DBLITERAL_CUBE_NAME ),
VALUE_WCHAR(DBLITERAL_DIMENSION_NAME ),
VALUE_WCHAR(DBLITERAL_HIERARCHY_NAME ),
VALUE_WCHAR(DBLITERAL_LEVEL_NAME ),
VALUE_WCHAR(DBLITERAL_MEMBER_NAME ),
VALUE_WCHAR(DBLITERAL_PROPERTY_NAME ),
//2.0
VALUE_WCHAR(DBLITERAL_SCHEMA_SEPARATOR ),
VALUE_WCHAR(DBLITERAL_QUOTE_SUFFIX ),
};
//Use Extended ListView Styles!
SendMessage(hWndLiterals, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES);
SendMessage(hWndNames, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES);
//Set image list to the Table Window
ListView_SetImageList(hWndLiterals, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
ListView_SetImageList(hWndNames, ImageList_LoadImage(GetAppLite()->m_hInstance, MAKEINTRESOURCE(IDB_IMAGE), 16, 16, CLR_DEFAULT , IMAGE_BITMAP, LR_DEFAULTCOLOR), LVSIL_SMALL);
//Obtain GetLiteralInfo (for all supported literals)
ASSERT(pIDBInfo);
XTEST(hr = pIDBInfo->GetLiteralInfo(0, NULL, &cLiteralInfo, &rgLiteralInfo, &pStringBuffer));
TESTC(TRACE_METHOD(hr, L"IDBInfo::GetLiteralInfo(&%lu, &0x%p, &0x%p)", cLiteralInfo, rgLiteralInfo, pStringBuffer));
//We need to the ListView
//Headers/Columns contain ColInfo information
//Rows are per columns
//ListView NAMES
LV_InsertColumn(hWndNames, 0, L"DBLITERAL");
LV_InsertItem(hWndNames, 0, 0, L"LiteralValue");
LV_InsertItem(hWndNames, 1, 0, L"InvalidChars");
LV_InsertItem(hWndNames, 2, 0, L"InvalidStartingChars");
LV_InsertItem(hWndNames, 3, 0, L"Supported");
LV_InsertItem(hWndNames, 4, 0, L"MaxLen");
//AutoSize column
SendMessage(hWndNames, LVM_SETCOLUMNWIDTH, 0, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
for(i=0; i<cLiteralInfo; i++)
{
ASSERT(rgLiteralInfo);
DBLITERALINFO* pLiteralInfo = &rgLiteralInfo[i];
//Try to find the Actual "DBLITERAL" name...
WCHAR* pwszLiteralName = NULL;
for(LONG j=0; j<NUMELE(rgLiterals); j++)
{
if(pLiteralInfo->lt == (DBLITERAL)rgLiterals[j].lItem)
pwszLiteralName = rgLiterals[j].pwszName;
}
//Column Header (DBLITERAL)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pLiteralInfo->lt);
LV_InsertColumn(hWndLiterals, i, pwszLiteralName ? pwszLiteralName : wszBuffer);
//LiteralValue (SubItem)
LV_InsertItem(hWndLiterals, 0, i, pLiteralInfo->pwszLiteralValue ? pLiteralInfo->pwszLiteralValue : NULL);
//InvalidChars (subitem)
LV_InsertItem(hWndLiterals, 1, i, pLiteralInfo->pwszInvalidChars ? pLiteralInfo->pwszInvalidChars : NULL);
//InvalidChars (subitem)
LV_InsertItem(hWndLiterals, 2, i, pLiteralInfo->pwszInvalidStartingChars ? pLiteralInfo->pwszInvalidStartingChars : NULL);
//Supported (SubItem)
LV_InsertItem(hWndLiterals, 3, i, NULL, PARAM_NONE, pLiteralInfo->fSupported ? IMAGE_CHECKED : IMAGE_UNCHECKED);
//cbMaxLen (SubItem)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pLiteralInfo->cchMaxLen);
LV_InsertItem(hWndLiterals, 4, i, wszBuffer);
}
//AutoSize all columns
for(i=0; i<cLiteralInfo; i++)
SendMessage(hWndLiterals, LVM_SETCOLUMNWIDTH, (WPARAM)i, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
CLEANUP:
CenterDialog(hWnd);
SAFE_FREE(rgLiteralInfo);
SAFE_FREE(pStringBuffer);
if(FAILED(hr))
EndDialog(hWnd, FALSE);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
case WM_NOTIFY:
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)lParam;
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lParam;
//ListView
switch(pDispInfo->hdr.code)
{
//Since we have "TwoClickActive" on this will get sent
//Whenever a row is clicked on twice!
//This functionality used to be done with NM_DBCLK
case LVN_ITEMACTIVATE:
return 0;
case LVN_ITEMCHANGED:
{
HWND hWndLiterals = ::GetDlgItem(hWnd, IDL_VALUES);
HWND hWndNames = ::GetDlgItem(hWnd, IDL_NAMES);
if(pNMListView->uNewState & LVNI_FOCUSED &&
pNMListView->uNewState & LVNI_SELECTED)
{
if(wParam == IDL_VALUES)
{
SyncSibling(hWndNames, hWndLiterals);
return FALSE;
}
if(wParam == IDL_NAMES)
{
SyncSibling(hWndLiterals, hWndNames);
return FALSE;
}
return UNHANDLED_MSG; //No return Value
}
}
}
}//WM_NOTIFY
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::AbortTransactionProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::AbortTransactionProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
HWND hWndRetaining = ::GetDlgItem(hWnd, IDC_RETAINING);
HWND hWndAsynch = ::GetDlgItem(hWnd, IDC_ASYNCH);
//Need to fill in the RETAINING ComboBox
INDEX iSel = (INDEX)SendMessage(hWndRetaining, CB_ADDSTRING, 0, (LPARAM)"TRUE");
SendMessage(hWndRetaining, CB_SETITEMDATA, iSel, (LPARAM)TRUE);
iSel = (INDEX)SendMessage(hWndRetaining, CB_ADDSTRING, 0, (LPARAM)"FALSE");
SendMessage(hWndRetaining, CB_SETITEMDATA, iSel, (LPARAM)FALSE);
//SetDefault - TRUE
SendMessage(hWndRetaining, CB_SETCURSEL, 0, (LPARAM)0);
//Need to fill in the ASYNCH ComboBox
iSel = (INDEX)SendMessage(hWndAsynch, CB_ADDSTRING, 0, (LPARAM)"TRUE");
SendMessage(hWndAsynch, CB_SETITEMDATA, iSel, (LPARAM)TRUE);
iSel = (INDEX)SendMessage(hWndAsynch, CB_ADDSTRING, 0, (LPARAM)"FALSE");
SendMessage(hWndAsynch, CB_SETITEMDATA, iSel, (LPARAM)FALSE);
//SetDefault - FALSE
SendMessage(hWndAsynch, CB_SETCURSEL, 1, 0);
//Need to fill in the Txn ComboBox
pThis->SetupTransactionCombo(::GetDlgItem(hWnd, IDC_TRANSACTION));
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
ITransaction* pITransaction = NULL;
HRESULT hr = S_OK;
HWND hWndRetaining = ::GetDlgItem(hWnd, IDC_RETAINING);
HWND hWndAsynch = ::GetDlgItem(hWnd, IDC_ASYNCH);
HWND hWndTransaction = ::GetDlgItem(hWnd, IDC_TRANSACTION);
//Just Need to Obtain selected RETAINING from Combo
INDEX iSel = (INDEX)SendMessage(hWndRetaining, CB_GETCURSEL, 0, 0);
BOOL fRetaining = (BOOL)SendMessage(hWndRetaining, CB_GETITEMDATA, iSel, 0);
//Just Need to Obtain selected ASYNCH from Combo
iSel = (INDEX)SendMessage(hWndAsynch, CB_GETCURSEL, 0, 0);
BOOL fAsynch = (BOOL)SendMessage(hWndAsynch, CB_GETITEMDATA, iSel, 0);
//get the ITransaction Pointer
iSel = (INDEX)SendMessage(hWndTransaction, CB_GETCURSEL, 0, 0);
if(iSel != CB_ERR)
pITransaction = (ITransaction*)SendMessage(hWndTransaction, CB_GETITEMDATA, iSel, 0);
//Obtain the Transaction interface
if(!pITransaction)
pITransaction = SOURCE_GETINTERFACE(pThis->m_pCSource, ITransaction);
ASSERT(pITransaction);
//Now Abort the Transaction
XTEST(hr = pITransaction->Abort(NULL, fRetaining, fAsynch));
TRACE_METHOD(hr, L"ITransaction::Abort(NULL, %s, %s)", fRetaining ? L"TRUE" : L"FALSE", fAsynch ? L"TRUE" : L"FALSE");
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::CommitTransactionProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::CommitTransactionProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//Controls
static CComboBoxLite s_comboXACTTC;
static CComboBoxLite s_comboRetaining;
static CComboBoxLite s_comboTransaction;
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
//Controls
s_comboXACTTC.CreateIndirect(hWnd, IDC_XACTTC);
s_comboRetaining.CreateIndirect(hWnd, IDC_RETAINING);
s_comboTransaction.CreateIndirect(hWnd, IDC_TRANSACTION);
//Need to fill in the RETAINING ComboBox
s_comboRetaining.AddString(L"TRUE", TRUE);
s_comboRetaining.AddString(L"FALSE", FALSE);
s_comboRetaining.SetSelValue(FALSE);
//Need to fill in the XACTTC ComboBox - and set the defualt
s_comboXACTTC.Populate(g_cXACTTC, g_rgXACTTC);
s_comboXACTTC.AddString(L"0", 0);
s_comboXACTTC.SetSelValue(XACTTC_SYNC_PHASETWO);
//Need to fill in the Txn ComboBox
pThis->SetupTransactionCombo(s_comboTransaction.m_hWnd);
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
HRESULT hr = S_OK;
//Obtain selected RETAINING from Combo
BOOL fRetaining = (BOOL)s_comboRetaining.GetSelValue();
//Obtain selected hWndXACTTC from Combo
DWORD xacttc = (DWORD)s_comboXACTTC.GetSelValue();
//get the ITransactionPointer
ITransaction* pITransaction = (ITransaction*)s_comboTransaction.GetItemParam(s_comboTransaction.GetCurSel());
//Obtain the Transaction interface
if(!pITransaction || (LPARAM)pITransaction==CB_ERR)
pITransaction = SOURCE_GETINTERFACE(pThis->m_pCSource, ITransaction);
ASSERT(pITransaction);
//Now Commit the Transaction
XTEST(hr = pITransaction->Commit(fRetaining, xacttc, 0));
TRACE_METHOD(hr, L"ITransaction::Commit(%s, %d, 0)", fRetaining ? L"TRUE" : L"FALSE", xacttc);
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetTransactionInfo
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::GetTransactionInfo(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
//Need to fill in the Txn ComboBox
pThis->SetupTransactionCombo(::GetDlgItem(hWnd, IDC_TRANSACTION));
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
HWND hWndTransaction = ::GetDlgItem(hWnd, IDC_TRANSACTION);
ITransaction* pITransaction = NULL;
XACTTRANSINFO XactInfo = {0};
HRESULT hr = S_OK;
//get the ITransactionPointer
INDEX iSel = (INDEX)SendMessage(hWndTransaction, CB_GETCURSEL, 0, 0);
if(iSel != CB_ERR)
pITransaction = (ITransaction*)SendMessage(hWndTransaction, CB_GETITEMDATA, iSel, 0);
//Obtain the Transaction interface
if(!pITransaction)
pITransaction = SOURCE_GETINTERFACE(pThis->m_pCSource, ITransaction);
ASSERT(pITransaction);
//ITransaction::GetTransactionInfo
XTEST(hr = pITransaction->GetTransactionInfo(&XactInfo));
TRACE_METHOD(hr, L"ITransaction::GetTransactionInfo(%s, %d, %s, %d, %d, %d)", /*XactInfo.uow,*/ GetMapName(XactInfo.isoLevel, g_cIsoLevels, g_rgIsoLevels), XactInfo.isoFlags, GetMapName(XactInfo.grfTCSupported, g_cXACTTC, g_rgXACTTC) , XactInfo.grfRMSupported, XactInfo.grfTCSupportedRetaining, XactInfo.grfRMSupportedRetaining);
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::StartTransactionProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::StartTransactionProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
HWND hWndIsoLevel = ::GetDlgItem(hWnd, IDC_ISOLEVEL);
//Title
if(pThis->m_idSource == IDM_ITRANSACTIONDISPENSOR_BEGINTRANSACTION)
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"TransactionDispensor::BeginTransaction");
//Need to fill in the ISOLEVEL ComboBox
for(ULONG i=0; i<g_cIsoLevels; i++)
{
INDEX iSel = (INDEX)wSendMessage(hWndIsoLevel, CB_ADDSTRING, 0, g_rgIsoLevels[i].pwszName);
SendMessage(hWndIsoLevel, CB_SETITEMDATA, iSel, (LPARAM)g_rgIsoLevels[i].lItem);
}
//SetDefault - READUNCOMMITED
SendMessage(hWndIsoLevel, CB_SETCURSEL, 2, (LPARAM)0);
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
HWND hWndIsoLevel = ::GetDlgItem(hWnd, IDC_ISOLEVEL);
WCHAR wszBuffer[MAX_NAME_LEN+1] = {0};
HRESULT hr = S_OK;
//Just Need to Obtain selected ISOLEVEL from Combo
INDEX iSel = (INDEX)SendMessage(hWndIsoLevel, CB_GETCURSEL, 0, 0);
wSendMessage(hWndIsoLevel, WM_GETTEXT, MAX_NAME_LEN, wszBuffer);
ISOLEVEL isoLevel = (ISOLEVEL)SendMessage(hWndIsoLevel, CB_GETITEMDATA, iSel, 0);
if(pThis->m_idSource != IDM_ITRANSACTIONDISPENSOR_BEGINTRANSACTION)
{
ULONG ulTransactionLevel = 0;
ITransactionLocal* pITransactionLocal = SOURCE_GETINTERFACE(pThis->m_pCSource, ITransactionLocal);
ASSERT(pITransactionLocal);
//ITransactionLocal::StartTransaction
XTEST(hr = pITransactionLocal->StartTransaction(isoLevel, 0, NULL, &ulTransactionLevel));
TRACE_METHOD(hr, L"ITransactionLocal::StartTransaction(%s, 0, NULL, &%d)", wszBuffer, ulTransactionLevel);
}
else
{
#ifdef MTSTXN
ITransaction* pITransaction = NULL;
ITransactionDispenser* pITransactionDispenser = NULL;
// Obtain the ITransactionDispenser Interface pointer
// by calling DtcGetTransactionManager()
XTEST(hr = DtcGetTransactionManager
(
NULL, // LPTSTR pszHost,
NULL, // LPTSTR pszTmName,
IID_ITransactionDispenser, // /* in */ REFIID rid,
0, // /* in */ DWORD dwReserved1,
0, // /* in */ WORD wcbReserved2,
NULL, // /* in */ void FAR * pvReserved2,
(void**)&pITransactionDispenser // /* out */ void** ppvObject
));
TRACE_METHOD(hr, L"DtcGetTransactionManager(NULL, NULL, IID_ITransactionDispenser, 0, 0, NULL, &0x%p)", pITransactionDispenser);
//start a global transaction
if(SUCCEEDED(hr))
{
XTEST(hr = pITransactionDispenser->BeginTransaction
(
NULL, // /* [in] */ IUnknown __RPC_FAR *punkOuter,
isoLevel, // /* [in] */ ISOLEVEL isoLevel,
0, // /* [in] */ ULONG isoFlags,
NULL, // /* [in] */ ITransactionOptions *pOptions
(ITransaction**)&pITransaction // /* [out] */ ITransaction **ppTransaction
));
TRACE_METHOD(hr, L"ITransactionDispenser::BeginTransaction(NULL, %s, 0, &0x%p)", wszBuffer, pITransaction);
//Add this transaciton to the list
if(SUCCEEDED(hr))
pThis->m_pCMainWindow->m_listTransactions.AddTail(pITransaction);
}
SAFE_RELEASE(pITransactionDispenser);
#endif //MTSTXN
}
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::JoinTransactionProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::JoinTransactionProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
HWND hWndIsoLevel = ::GetDlgItem(hWnd, IDC_ISOLEVEL);
//Need to fill in the ISOLEVEL ComboBox
for(ULONG i=0; i<g_cIsoLevels; i++)
{
INDEX iSel = (INDEX)wSendMessage(hWndIsoLevel, CB_ADDSTRING, 0, g_rgIsoLevels[i].pwszName);
SendMessage(hWndIsoLevel, CB_SETITEMDATA, iSel, (LPARAM)g_rgIsoLevels[i].lItem);
}
//SetDefault - READUNCOMMITED
SendMessage(hWndIsoLevel, CB_SETCURSEL, 2, (LPARAM)0);
//Need to fill in the Txn ComboBox
pThis->SetupTransactionCombo(::GetDlgItem(hWnd, IDC_TRANSACTION));
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
WCHAR wszBuffer[MAX_NAME_LEN+1] = {0};
HWND hWndIsoLevel = ::GetDlgItem(hWnd, IDC_ISOLEVEL);
HWND hWndTransaction = ::GetDlgItem(hWnd, IDC_TRANSACTION);
ITransaction* pITransaction = NULL;
HRESULT hr = S_OK;
//Just Need to Obtain selected ISOLEVEL from Combo
INDEX iSel = (INDEX)SendMessage(hWndIsoLevel, CB_GETCURSEL, 0, 0);
wSendMessage(hWndIsoLevel, WM_GETTEXT, MAX_NAME_LEN, wszBuffer);
ISOLEVEL isoLevel = (ISOLEVEL)SendMessage(hWndIsoLevel, CB_GETITEMDATA, iSel, 0);
//get the ITransactionPointer
iSel = (INDEX)SendMessage(hWndTransaction, CB_GETCURSEL, 0, 0);
if(iSel != CB_ERR)
pITransaction = (ITransaction*)SendMessage(hWndTransaction, CB_GETITEMDATA, iSel, 0);
ITransactionJoin* pITransactionJoin = SOURCE_GETINTERFACE(pThis->m_pCSource, ITransactionJoin);
ASSERT(pITransactionJoin);
//ITransactionJoin::JoinTransaction
XTEST(hr = pITransactionJoin->JoinTransaction(pITransaction, isoLevel, NULL, NULL));
TRACE_METHOD(hr, L"ITransactionJoin::JoinTransaction(0x%p, %s, 0, NULL)", pITransaction, wszBuffer);
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::SetupTransactionCombo
//
/////////////////////////////////////////////////////////////////
BOOL CMDIChild::SetupTransactionCombo(HWND hWnd)
{
INDEX iSel = 0;
ULONG cCount = 0;
WCHAR wszBuffer[MAX_NAME_LEN+1] = {0};
//Need to fill in the Txn ComboBox
POSITION pos = m_pCMainWindow->m_listTransactions.GetHeadPosition();
while(pos)
{
ITransaction* pITransaction = m_pCMainWindow->m_listTransactions.GetNext(pos);
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d - 0x%p", cCount++, pITransaction);
iSel = (INDEX)wSendMessage(hWnd, CB_ADDSTRING, 0, wszBuffer);
SendMessage(hWnd, CB_SETITEMDATA, iSel, (LPARAM)pITransaction);
}
//SetDefault - 1st txn
SendMessage(hWnd, CB_SETCURSEL, 0, (LPARAM)0);
//Enable or Diable the Combo...
::EnableWindow(hWnd, !m_pCMainWindow->m_listTransactions.IsEmpty());
return TRUE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::ReleaseTransaction
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::ReleaseTransaction(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
//Need to fill in the Txn ComboBox
pThis->SetupTransactionCombo(::GetDlgItem(hWnd, IDC_TRANSACTION));
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
HWND hWndTransaction = ::GetDlgItem(hWnd, IDC_TRANSACTION);
ITransaction* pITransaction = NULL;
//get the ITransactionPointer
INDEX iSel = (INDEX)SendMessage(hWndTransaction, CB_GETCURSEL, 0, 0);
if(iSel != CB_ERR)
pITransaction = (ITransaction*)SendMessage(hWndTransaction, CB_GETITEMDATA, iSel, 0);
if(pITransaction)
{
//Remove from list
POSITION iPos = pThis->m_pCMainWindow->m_listTransactions.Find(pITransaction);
pThis->m_pCMainWindow->m_listTransactions.RemoveAt(iPos);
//ITransaction::Release
TRACE_RELEASE(pITransaction, L"ITransaction");
}
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::SetTransactionOptionsProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::SetTransactionOptionsProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
HWND hWndTimeout = ::GetDlgItem(hWnd, IDE_TIMEOUT);
HWND hWndDescription= ::GetDlgItem(hWnd, IDE_DESCRIPTION);
//Defaults
SendMessage(hWndTimeout, WM_SETTEXT, 0, (LPARAM)"0");
SendMessage(hWndDescription, WM_SETTEXT, 0, (LPARAM)"");
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CTransactionOptions* pCTransactionOptions = SOURCE_GETOBJECT(pThis->m_pCSource, CTransactionOptions);
HRESULT hr = S_OK;
HWND hWndTimeout = ::GetDlgItem(hWnd, IDE_TIMEOUT);
HWND hWndDescription= ::GetDlgItem(hWnd, IDE_DESCRIPTION);
XACTOPT XactOptions;
XactOptions.ulTimeout = 0;
XactOptions.szDescription[0] = EOL;
//Need to Obtain Entered Timeout Value
if(!GetEditBoxValue(hWndTimeout, (LONG*)&XactOptions.ulTimeout, 0/*Min*/))
return FALSE;
//Need to Obtain Description
SendMessage(hWndDescription, WM_GETTEXT, 40-1, (LPARAM)XactOptions.szDescription);
//ITransactionOptions::SetOptions
ASSERT(pCTransactionOptions->m_pITransactionOptions);
XTEST(hr = pCTransactionOptions->m_pITransactionOptions->SetOptions(&XactOptions));
TRACE_METHOD(hr, L"ITransactionOptions::SetOptions(%d, \"%S\")", XactOptions.ulTimeout, XactOptions.szDescription);
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::CanConvertProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::CanConvertProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static DBTYPE wSavedFromType = 0;
static DBTYPE wSavedToType = 0;
static INDEX iSavedFromSel = 28; //DBTYPE_WSTR
static INDEX iSavedToSel = iSavedFromSel;
//We have a problem with DBCONVERTFLAGS being orable, but _COLUMN == 0!
//We will need to keep track of the 0 and non-0 flags,
//inorder to restore the users previous selections correctly...
static LONG fSelColumnFlag = TRUE; //Default to COLUMN
static LONG dwSavedConvFlags = DBCONVERTFLAGS_COLUMN; //Default to COLUMN
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
HWND hWndFromType = ::GetDlgItem(hWnd, IDC_FROMTYPE);
HWND hWndToType = ::GetDlgItem(hWnd, IDC_TOTYPE);
HWND hWndConvFlags = ::GetDlgItem(hWnd, IDL_CONVFLAGS);
INDEX iSel = 0;
const static WIDENAMEMAP rgConvertFlags[] =
{
VALUE_WCHAR(DBCONVERTFLAGS_COLUMN ),
VALUE_WCHAR(DBCONVERTFLAGS_PARAMETER ),
VALUE_WCHAR(DBCONVERTFLAGS_ISLONG ),
VALUE_WCHAR(DBCONVERTFLAGS_ISFIXEDLENGTH ),
VALUE_WCHAR(DBCONVERTFLAGS_FROMVARIANT ),
};
ULONG i;
//Need to fill in the From and To Type ComboBoxs
for(i=0; i<g_cDBTypes; i++)
{
WCHAR* pwszName = g_rgDBTypes[i].pwszName;
DBTYPE wType = (DBTYPE)g_rgDBTypes[i].lItem;
//FromType
iSel = (INDEX)wSendMessage(hWndFromType, CB_ADDSTRING, 0, pwszName);
SendMessage(hWndFromType, CB_SETITEMDATA, iSel, (LPARAM)wType);
//ToType
iSel = (INDEX)wSendMessage(hWndToType, CB_ADDSTRING, 0, pwszName);
SendMessage(hWndToType, CB_SETITEMDATA, iSel, (LPARAM)wType);
}
//Need to select Defaults
SendMessage(hWndFromType, CB_SETCURSEL, iSavedFromSel, 0);
SendMessage(hWndToType, CB_SETCURSEL, iSavedToSel, 0);
//Need to also select Default Modifiers
::CheckDlgButton(hWnd, IDB_FROM_BYREF, BST2STATE(wSavedFromType & DBTYPE_BYREF));
::CheckDlgButton(hWnd, IDB_FROM_ARRAY, BST2STATE(wSavedFromType & DBTYPE_ARRAY));
::CheckDlgButton(hWnd, IDB_FROM_VECTOR, BST2STATE(wSavedFromType & DBTYPE_VECTOR));
::CheckDlgButton(hWnd, IDB_TO_BYREF, BST2STATE(wSavedToType & DBTYPE_BYREF));
::CheckDlgButton(hWnd, IDB_TO_ARRAY, BST2STATE(wSavedToType & DBTYPE_ARRAY));
::CheckDlgButton(hWnd, IDB_TO_VECTOR, BST2STATE(wSavedToType & DBTYPE_VECTOR));
//Need to fill in the ConvertFlags (ListBox)
SendMessage(hWndConvFlags, LB_RESETCONTENT, 0, 0);
for(i=0; i<NUMELE(rgConvertFlags); i++)
{
INDEX iSel = (INDEX)wSendMessage(hWndConvFlags, LB_ADDSTRING, 0, rgConvertFlags[i].pwszName);
SendMessage(hWndConvFlags, LB_SETITEMDATA, iSel, (LPARAM)rgConvertFlags[i].lItem);
//Select Saved ConvFlags
if((dwSavedConvFlags & rgConvertFlags[i].lItem) || (fSelColumnFlag && rgConvertFlags[i].lItem == DBCONVERTFLAGS_COLUMN))
SendMessage(hWndConvFlags, LB_SETSEL, TRUE, i);
}
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CDataAccess* pCDataAccess = NULL;
HRESULT hr = S_OK;
HWND hWndFromType = ::GetDlgItem(hWnd, IDC_FROMTYPE);
HWND hWndToType = ::GetDlgItem(hWnd, IDC_TOTYPE);
HWND hWndConvFlags = ::GetDlgItem(hWnd, IDL_CONVFLAGS);
HWND hWndResult = ::GetDlgItem(hWnd, IDT_RESULT);
//Just Need to Obtain selected FromType from Combo
iSavedFromSel = (INDEX)SendMessage(hWndFromType, CB_GETCURSEL, 0, 0);
wSavedFromType = (DBTYPE)SendMessage(hWndFromType, CB_GETITEMDATA, iSavedFromSel, 0);
//Need to obtain any type modifier for the FromType
if(::IsDlgButtonChecked(hWnd, IDB_FROM_BYREF))
wSavedFromType |= DBTYPE_BYREF;
if(::IsDlgButtonChecked(hWnd, IDB_FROM_ARRAY))
wSavedFromType |= DBTYPE_ARRAY;
if(::IsDlgButtonChecked(hWnd, IDB_FROM_VECTOR))
wSavedFromType |= DBTYPE_VECTOR;
//Just Need to Obtain selected ToType from Combo
iSavedToSel = (INDEX)SendMessage(hWndToType, CB_GETCURSEL, 0, 0);
wSavedToType = (DBTYPE)SendMessage(hWndToType, CB_GETITEMDATA, iSavedToSel, 0);
//Need to obtain any type modifier for the ToType
if(::IsDlgButtonChecked(hWnd, IDB_TO_BYREF))
wSavedToType |= DBTYPE_BYREF;
if(::IsDlgButtonChecked(hWnd, IDB_TO_ARRAY))
wSavedToType |= DBTYPE_ARRAY;
if(::IsDlgButtonChecked(hWnd, IDB_TO_VECTOR))
wSavedToType |= DBTYPE_VECTOR;
//Obtain all Selected ConvertFlag items...
INDEX iSelCount = (INDEX)SendMessage(hWndConvFlags, LB_GETSELCOUNT, 0, 0);
ASSERT(iSelCount < 20);
LONG rgSelItems[20];
SendMessage(hWndConvFlags, LB_GETSELITEMS, (WPARAM)20, (LPARAM)rgSelItems);
fSelColumnFlag = FALSE;
dwSavedConvFlags = 0;
for(LONG i=0; i<iSelCount; i++)
{
DWORD dwSelFlag = (DWORD)SendMessage(hWndConvFlags, LB_GETITEMDATA, rgSelItems[i], 0);
if(dwSelFlag == DBCONVERTFLAGS_COLUMN)
fSelColumnFlag = TRUE;
dwSavedConvFlags |= dwSelFlag;
}
//Obtain the Correct IConvertType interface
pCDataAccess = SOURCE_GETOBJECT(pThis->m_pCSource, CDataAccess);
ASSERT(pCDataAccess);
//Now Just call IConvertType::CanConvert
ASSERT(pCDataAccess->m_pIConvertType);
hr = pCDataAccess->m_pIConvertType->CanConvert(wSavedFromType, wSavedToType, dwSavedConvFlags);
TRACE_METHOD(hr, L"IConvertType::CanConvert(%d=0x%08x, %d=0x%08x, 0x%08x)", wSavedFromType, wSavedFromType, wSavedToType, wSavedToType, dwSavedConvFlags);
//Now display the results
//We always want to display the result even on error...
wSendMessageFmt(hWndResult, WM_SETTEXT, 0, L" %S", GetErrorName(hr));
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::OpenRowsetProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::OpenRowsetProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static CComboBoxGuid s_CComboInterface;
static CRichEditLite s_editTableID;
static CRichEditLite s_editIndexID;
static BOOL fUseProps = TRUE; //Default
static BOOL fAggregation = FALSE; //Default
static BOOL fOutput = TRUE; //Default
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
//Window Title (Default is IOpenRowset::OpenRowset)
if(pThis->m_idSource == IDM_ISCOPEDOPERATIONS_OPENROWSET)
::SetWindowText(hWnd, "IScopedOperations::OpenRowset");
//Fill In TableID as Default
s_editTableID.CreateIndirect(hWnd, IDE_TABLEID);
WCHAR* pwszTableName = pThis->m_pCQueryBox->GetSelectedText();
s_editTableID.SetWindowText(pwszTableName);
//Fill in IndexID as default
s_editIndexID.CreateIndirect(hWnd, IDE_INDEXID);
//Use Properties
::CheckDlgButton(hWnd, IDB_USEPROPERTIES, BST2STATE(fUseProps));
//Aggregation
::CheckDlgButton(hWnd, IDB_AGGREGATION, BST2STATE(fAggregation));
//Output (ppIUnknown)
::CheckDlgButton(hWnd, IDB_OUTPUT, BST2STATE(fOutput));
//Interface List...
s_CComboInterface.CreateIndirect(hWnd, IDC_INTERFACE);
s_CComboInterface.Populate(g_cInterfaceMaps, g_rgInterfaceMaps);
if(s_CComboInterface.RestoreSelection() == CB_ERR)
s_CComboInterface.SetGuid(IID_IRowset);
SAFE_FREE(pwszTableName);
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_SETPROPERTIES:
{
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CMainWindow* pCMainWindow = pThis->m_pCMainWindow;
CDataSource* pCDataSource = SOURCE_GETPARENT(pThis->m_pCSource, CDataSource);
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_ROWSETALL, IID_IRowsetInfo, NULL, pCDataSource ? pCDataSource->m_pIDBProperties : NULL, &pThis->m_CDefPropSets);
return 0;
}
case IDB_AGGREGATION:
{
//Aggregation Combo Selection has changed...
//If we are now using Aggregation, automatically change the requested
//riid to IID_IUnknown, since its an error otherwise...
if(::IsDlgButtonChecked(hWnd, IDB_AGGREGATION))
s_CComboInterface.SetGuid(IID_IUnknown);
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
CRow* pCRow = SOURCE_GETOBJECT(pThis->m_pCSource, CRow);
IUnknown* pIUnknown = NULL;
HRESULT hr = S_OK;
ULONG cPropSets = 0;
DBPROPSET* rgPropSets = NULL;
//Obtain the Aggregation argument
CAggregate* pCAggregate = NULL;
fAggregation = ::IsDlgButtonChecked(hWnd, IDB_AGGREGATION);
if(fAggregation)
pCAggregate = new CAggregate();
//Obtain the Output (ppIUnknown) argument
fOutput = ::IsDlgButtonChecked(hWnd, IDB_OUTPUT);
//Interface
REFIID riid = s_CComboInterface.GetGuid();
//TableID
CComWSTR cstrTableName;
cstrTableName.Attach(s_editTableID.GetWindowText());
DBID TableID;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = cstrTableName;
DBID* pTableID = cstrTableName ? &TableID : NULL;
//IndexID
//NOTE: Most providers don't support IndexIDs and fail if a non-NULL pointer is
//passed in, so unless the user specified something just use NULL...
CComWSTR cstrIndexName;
cstrIndexName.Attach(s_editIndexID.GetWindowText());
DBID IndexID;
IndexID.eKind = DBKIND_NAME;
IndexID.uName.pwszName = cstrIndexName;
DBID* pIndexID = cstrIndexName ? &IndexID : NULL;
//Use Properties
fUseProps = ::IsDlgButtonChecked(hWnd, IDB_USEPROPERTIES);
if(fUseProps)
{
cPropSets = pThis->m_CDefPropSets.GetCount();
rgPropSets = pThis->m_CDefPropSets.GetPropSets();
}
//OpenRowset
ASSERT(pCSession || pCRow);
if(pCSession)
hr = pCSession->OpenRowset(pCAggregate, pTableID, pIndexID, riid, cPropSets, rgPropSets, fOutput ? &pIUnknown : NULL);
else
hr = pCRow->OpenRowset(pCAggregate, pTableID, pIndexID, riid, cPropSets, rgPropSets, fOutput ? &pIUnknown : NULL);
if(SUCCEEDED(hr))
{
//Create an object description from the TableName (and index if used)
//1. TableName only - "TableName"
//2. TableName and Index - "TableName.IndexName"
//3. IndexName only - "IndexName"
CComWSTR cstrDesc;
cstrDesc.CopyFrom(cstrTableName);
if(cstrIndexName)
{
if(cstrTableName)
cstrDesc += L".";
cstrDesc += cstrIndexName;
}
//Delegate to display the object
hr = pThis->HandleRowset(pThis->m_pCSource, pIUnknown, riid, CREATE_NEWWINDOW_IFEXISTS, pCSession ? IID_IOpenRowset : IID_IScopedOperations, cstrDesc);
}
if(SUCCEEDED(hr))
{
//Now just need to place this name in the EditBox
//Inserted after the current "caret"
pThis->m_pCQueryBox->ReplaceAll(cstrTableName, FALSE/*bReplaceAll*/, TRUE/*fHighlight*/);
EndDialog(hWnd, TRUE);
}
SAFE_RELEASE(pCAggregate);
SAFE_RELEASE(pIUnknown);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::RowOpenProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::RowOpenProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static INDEX iSavedType = 5; //DBGUID_STREAM
static CComboBoxGuid s_CComboInterface;
static BOOL fAggregation = FALSE; //Default
static BOOL fOutput = TRUE; //Default
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CRow* pCRow = SOURCE_GETOBJECT(pThis->m_pCSource, CRow);
INDEX iSel = 0;
HWND hWndColumns = ::GetDlgItem(hWnd, IDC_COLUMNS);
HWND hWndObjectType = ::GetDlgItem(hWnd, IDC_OBJECTTYPE);
ULONG i;
//Fill In ColumnID drop down
INDEX iDefColumn = -1;
for(i=0; i<pCRow->m_ColumnInfo.GetCount(); i++)
{
iSel = (INDEX)wSendMessage(hWndColumns, CB_ADDSTRING, 0, GetColName(&pCRow->m_ColumnInfo[i]));
SendMessage(hWndColumns, CB_SETITEMDATA, iSel, (LPARAM)&pCRow->m_ColumnInfo[i].columnid);
//Default the selected column to the first BLOB, Stream, or IUnknown object
if(iDefColumn==-1 && ((pCRow->m_ColumnInfo[i].wType == DBTYPE_IUNKNOWN) || (pCRow->m_ColumnInfo[i].dwFlags & (DBCOLUMNFLAGS_ISLONG | DBCOLUMNFLAGS_ISDEFAULTSTREAM))))
iDefColumn = i;
}
//Now also add the special column guids, which may not be a part of the ColumnInfo
for(i=0; i<g_cRowColMaps; i++)
{
iSel = (INDEX)wSendMessage(hWndColumns, CB_ADDSTRING, 0, g_rgRowColMaps[i].pwszName);
SendMessage(hWndColumns, CB_SETITEMDATA, iSel, (LPARAM)g_rgRowColMaps[i].pDBID);
}
//Set the Default Selection
if(iDefColumn == -1)
iDefColumn = iSel;
SendMessage(hWndColumns, CB_SETCURSEL, iDefColumn, 0);
//Fill In ObjectType drop down
for(i=0; i<g_cObjectTypeMaps; i++)
{
iSel = (INDEX)wSendMessage(hWndObjectType, CB_ADDSTRING, 0, g_rgObjectTypeMaps[i].pwszName);
SendMessage(hWndObjectType, CB_SETITEMDATA, iSel, (LPARAM)&g_rgObjectTypeMaps[i]);
}
SendMessage(hWndObjectType, CB_SETCURSEL, iSavedType, 0);
//Aggregation
::CheckDlgButton(hWnd, IDB_AGGREGATION, BST2STATE(fAggregation));
//Output (ppIUnknown)
::CheckDlgButton(hWnd, IDB_OUTPUT, BST2STATE(fOutput));
//Interface List...
s_CComboInterface.CreateIndirect(hWnd, IDC_INTERFACE);
s_CComboInterface.Populate(g_cInterfaceMaps, g_rgInterfaceMaps);
if(s_CComboInterface.RestoreSelection() == CB_ERR)
s_CComboInterface.SetGuid(IID_ISequentialStream);
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_AGGREGATION:
{
//Aggregation Combo Selection has changed...
//If we are now using Aggregation, automatically change the requested
//riid to IID_IUnknown, since its an error otherwise...
if(::IsDlgButtonChecked(hWnd, IDB_AGGREGATION))
s_CComboInterface.SetGuid(IID_IUnknown);
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CRow* pCRow = SOURCE_GETOBJECT(pThis->m_pCSource, CRow);
IUnknown* pIUnknown = NULL;
DWORD dwCreateOpts = CREATE_NEWWINDOW;
HWND hWndColumns = ::GetDlgItem(hWnd, IDC_COLUMNS);
HWND hWndObjectType = ::GetDlgItem(hWnd, IDC_OBJECTTYPE);
HRESULT hr = S_OK;
//ColumnID
INDEX iSel = (INDEX)SendMessage(hWndColumns, CB_GETCURSEL, 0, 0);
DBID* pColID = (DBID*)SendMessage(hWndColumns, CB_GETITEMDATA, iSel, 0);
//ObjectType
iSavedType = (INDEX)SendMessage(hWndObjectType, CB_GETCURSEL, 0, 0);
WIDEGUIDMAP* pObjectMap = (WIDEGUIDMAP*)SendMessage(hWndObjectType, CB_GETITEMDATA, iSavedType, 0);
GUID guidObjectType = *pObjectMap->pGuid;
if(guidObjectType == GUID_NULL)
dwCreateOpts |= CREATE_DETERMINE_TYPE;
//Obtain the Aggregation argument
CAggregate* pCAggregate = NULL;
fAggregation = ::IsDlgButtonChecked(hWnd, IDB_AGGREGATION);
if(fAggregation)
pCAggregate = new CAggregate();
//Obtain the Output (ppIUnknown) argument
fOutput = ::IsDlgButtonChecked(hWnd, IDB_OUTPUT);
//Interface
REFIID riid = s_CComboInterface.GetGuid();
//IRow::Open
TESTC(hr = pCRow->Open(pCAggregate, pColID, guidObjectType, riid, fOutput ? &pIUnknown : NULL));
//Handle the returned object type...
//NOTE: We know the object returned, or eCUnknown is passed to determine it
if(!pThis->m_pCMainWindow->HandleObjectType(pCRow, pIUnknown, riid, GuidToSourceType(guidObjectType), 0, NULL, dwCreateOpts))
TESTC(hr = E_FAIL);
CLEANUP:
SAFE_RELEASE(pCAggregate);
SAFE_RELEASE(pIUnknown);
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetObject
//
/////////////////////////////////////////////////////////////////
CBase* CMDIChild::GetObject(SOURCE eSource, BOOL fAlways)
{
//First try to obtain the last object...
CBase** ppCBase = GetObjectAddress(eSource);
if(ppCBase)
{
CBase* pCBase = *ppCBase;
if(pCBase && (eSource==eCUnknown || pCBase->GetObjectType()==eSource || pCBase->GetBaseType() & eSource) && (fAlways || pCBase->m_pIUnknown))
return pCBase;
}
return NULL;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetObjectAddress
//
/////////////////////////////////////////////////////////////////
CBase** CMDIChild::GetObjectAddress(SOURCE eSource)
{
CBase** ppCObject = NULL;
switch(eSource)
{
case eCDataSource:
ppCObject = (CBase**)&m_pCDataSource;
break;
case eCSession:
ppCObject = (CBase**)&m_pCSession;
break;
case eCCommand:
ppCObject = (CBase**)&m_pCCommand;
break;
case eCMultipleResults:
ppCObject = (CBase**)&m_pCMultipleResults;
break;
case eCDataset:
case eCRowset:
case eCRow:
//Only one of these objects is active at any one time
//Since all of them actually use the "DataGrid" we can only have one per MDIChild
ppCObject = (CBase**)&m_pCDataAccess;
break;
case eCUnknown:
//Determine "Last" object type...
if(m_pCDataAccess && m_pCDataAccess->m_pIUnknown)
return (CBase**)&m_pCDataAccess;
else if(m_pCMultipleResults && m_pCMultipleResults->m_pIUnknown)
return (CBase**)&m_pCMultipleResults;
else if(m_pCCommand && m_pCCommand->m_pIUnknown)
return (CBase**)&m_pCCommand;
else if(m_pCSession && m_pCSession->m_pIUnknown)
return (CBase**)&m_pCSession;
else if(m_pCDataSource && m_pCDataSource->m_pIUnknown)
return (CBase**)&m_pCDataSource;
break;
default:
break;
};
return ppCObject;
}
////////////////////////////////////////////////////////////////
// CMDIChild::HandleRowset
//
/////////////////////////////////////////////////////////////////
HRESULT CMDIChild::HandleRowset(CBase* pCSource, IUnknown* pIUnknown, REFIID riid, DWORD dwFlags, REFGUID guidSource, WCHAR* pwszTableName, BOOL fSchemaRowset)
{
HRESULT hr = S_OK;
//Handle the Result
//NOTE: Result can be NULL for non-row returning results...
if(pIUnknown)
{
//Don't display the object
dwFlags |= CREATE_NODISPLAY;
//Now Create the object...
//NOTE: Can pontentially return other object types: (ie: CREATE_DETERMINE_TYPE)
CBase* pCObject = m_pCMainWindow->HandleObjectType(pCSource, pIUnknown, riid, eCRowset, 0, NULL, dwFlags | CREATE_DETERMINE_TYPE);
if(pCObject)
{
//Record the source of the object...
pCObject->m_guidSource = guidSource;
CDataAccess* pCDataAccess = SOURCE_GETOBJECT(pCObject, CDataAccess);
if(pCDataAccess)
{
pCDataAccess->m_bSchemaRowset = fSchemaRowset;
//Save the passed in TableName...
pCDataAccess->SetObjectDesc(pwszTableName);
}
//Now Display the object...
pCObject->DisplayObject();
}
else
{
TESTC(hr = E_FAIL);
}
}
CLEANUP:
UpdateControls();
return hr;
}
////////////////////////////////////////////////////////////////
// CMDIChild::AdminCreateDataSourceProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::AdminCreateDataSourceProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL fUseProps = TRUE; //Default to TRUE
static CPropSets s_CAdminPropSets;
static CComboBoxGuid s_CComboInterface;
static BOOL fAggregation = FALSE; //Default
static BOOL fOutput = TRUE; //Default
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
//Use Properties
::CheckDlgButton(hWnd, IDB_USEPROPERTIES, BST2STATE(fUseProps));
//Reset our static properties...
s_CAdminPropSets.RemoveAll();
//Aggregation
::CheckDlgButton(hWnd, IDB_AGGREGATION, BST2STATE(fAggregation));
//Output (ppIUnknown)
::CheckDlgButton(hWnd, IDB_OUTPUT, BST2STATE(fOutput));
//Interface List...
s_CComboInterface.CreateIndirect(hWnd, IDC_INTERFACE);
s_CComboInterface.Populate(g_cInterfaceMaps, g_rgInterfaceMaps);
if(s_CComboInterface.RestoreSelection() == CB_ERR)
s_CComboInterface.SetGuid(IID_IOpenRowset);
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_SETPROPERTIES:
{
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CMainWindow* pCMainWindow = pThis->m_pCMainWindow;
CDataSource* pCDataSource = SOURCE_GETOBJECT(pThis->m_pCSource, CDataSource);
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_DBINITALL, IID_IDBProperties, pCDataSource ? pCDataSource->m_pIDBProperties : NULL, pCDataSource ? pCDataSource->m_pIDBProperties : NULL, &s_CAdminPropSets);
return 0;
}
case IDB_AGGREGATION:
{
//Aggregation Combo Selection has changed...
//If we are now using Aggregation, automatically change the requested
//riid to IID_IUnknown, since its an error otherwise...
if(::IsDlgButtonChecked(hWnd, IDB_AGGREGATION))
s_CComboInterface.SetGuid(IID_IUnknown);
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CDataSource* pCDataSource = SOURCE_GETOBJECT(pThis->m_pCSource, CDataSource);
HRESULT hr = S_OK;
ULONG cPropSets = 0;
DBPROPSET* rgPropSets = NULL;
IUnknown* pIUnknown = NULL;
//Obtain the Aggregation argument
CAggregate* pCAggregate = NULL;
fAggregation = ::IsDlgButtonChecked(hWnd, IDB_AGGREGATION);
if(fAggregation)
pCAggregate = new CAggregate();
//Obtain the Output (ppIUnknown) argument
fOutput = ::IsDlgButtonChecked(hWnd, IDB_OUTPUT);
//Interface
REFIID riid = s_CComboInterface.GetGuid();
//Use Properties
fUseProps = ::IsDlgButtonChecked(hWnd, IDB_USEPROPERTIES);
if(fUseProps)
{
cPropSets = s_CAdminPropSets.GetCount();
rgPropSets = s_CAdminPropSets.GetPropSets();
}
//IDBDataSourceAdmin::CreateDataSource
//NOTE: Our helper takes care of aggregation...
hr = pCDataSource->AdminCreateDataSource(pCAggregate, cPropSets, rgPropSets, riid, fOutput ? &pIUnknown : NULL);
//Display the Result
if(SUCCEEDED(hr) && fOutput)
{
//Just pass in a guess for the object type and let our helper figure out what object it is...
if(!pThis->m_pCMainWindow->HandleObjectType(pCDataSource, pIUnknown, riid, eCSession, 0, NULL, CREATE_NEWWINDOW_IFEXISTS))
hr = E_FAIL;
}
//Release
SAFE_RELEASE(pIUnknown);
SAFE_RELEASE(pCAggregate);
pThis->UpdateControls();
if(SUCCEEDED(hr))
{
s_CAdminPropSets.RemoveAll();
EndDialog(hWnd, TRUE);
return 0;
}
return 0;
}
case IDCANCEL:
{
s_CAdminPropSets.RemoveAll();
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::CreateIndexProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::CreateIndexProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//NOTE: These are static variables, just to hold the PropertyInfo
//Information temporarily. There are messages that need this info which
//gets setup on INITDIALOG. On OK or CANCEL this info will be freed...
static WCHAR *pStringBuffer = NULL;
ULONG i;
LONG iSel = 0;
static WCHAR wszBuffer[MAX_NAME_LEN+1];
switch(message)
{
case WM_INITDIALOG:
{
//Save the "this" pointer
CWaitCursor waitCursor;
CMDIChild *pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
//Use Extended ListView Styles!
HWND hWndIndexColumnDesc = ::GetDlgItem(hWnd, IDL_INDEXCOLUMNDESC);
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
HWND hWndOrder = ::GetDlgItem(hWnd, IDC_ORDER);
HWND hWndColumnID = ::GetDlgItem(hWnd, IDE_COLUMNID);
RECT rect;
SendMessage(hWndIndexColumnDesc, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE);
//Fill In TableID as Default
WCHAR* pwszTableName = pThis->m_pCQueryBox->GetSelectedText();
wSendMessage(hWndTableID, WM_SETTEXT, 0, pwszTableName);
//ColumnHeaders for INDEXCOLUMNDESC report
LV_InsertColumn(hWndIndexColumnDesc, COLUMN_ID, L"Column ID", IMAGE_NONE);
LV_InsertColumn(hWndIndexColumnDesc, COLUMN_ORDER,L"Order", IMAGE_NONE);
//AutoSize Columns
GetWindowRect(hWndColumnID, (LPRECT)&rect);
SendMessage(hWndIndexColumnDesc, LVM_SETCOLUMNWIDTH, (WPARAM)COLUMN_ID, (LPARAM)(rect.right-rect.left));
GetWindowRect(hWndOrder, (LPRECT)&rect);
SendMessage(hWndIndexColumnDesc, LVM_SETCOLUMNWIDTH, (WPARAM)COLUMN_ORDER, (LPARAM)(rect.right-rect.left));
// Order list...
SendMessage(hWndOrder, CB_ADDSTRING, 0, (LPARAM)"Ascendent");
SendMessage(hWndOrder, CB_ADDSTRING, 0, (LPARAM)"Descendent");
SendMessage(hWndOrder, CB_SETCURSEL, 0, 0); // ascendent
//Placement of Dialog, want it just below the "Init" button...
CenterDialog(hWnd);
//Disable fields
::EnableWindow(::GetDlgItem(hWnd, IDE_COLUMNID), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDC_ORDER), FALSE);
SAFE_FREE(pwszTableName)
return TRUE;
}
case WM_COMMAND:
{
switch (GET_WM_COMMAND_CMD(wParam, lParam))
{
case EN_KILLFOCUS:
{
switch((int)LOWORD(wParam))
{
case IDE_COLUMNID:
{
HWND hWndIndexColumnDesc = ::GetDlgItem(hWnd, IDL_INDEXCOLUMNDESC);
HWND hWndColumnID = ::GetDlgItem(hWnd, IDE_COLUMNID);
HWND hWndColName = ::GetDlgItem(hWnd, IDE_COLNAME);
WCHAR wszBuffer2[MAX_NAME_LEN+1];
// get the selected item
iSel = ListView_GetNextItem(hWndIndexColumnDesc, -1, LVNI_SELECTED);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
// and to Column Name static field
wSendMessage(hWndColumnID, WM_GETTEXT, MAX_NAME_LEN, wszBuffer2);
StringFormat(wszBuffer, NUMELE(wszBuffer), L"Current item %d (%s)", iSel, wszBuffer2);
LV_SetItemText(hWndIndexColumnDesc, iSel, COLUMN_ID, wszBuffer2);
wSendMessage(hWndColName, WM_SETTEXT, 0, wszBuffer);
return 0;
}
}
return 0;
}
}
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
//CBN_SELCHANGE
switch(GET_WM_COMMAND_CMD(wParam, lParam))
{
case CBN_SELCHANGE:
{
switch(GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_ORDER:
{
HWND hWndIndexColumnDesc = ::GetDlgItem(hWnd, IDL_INDEXCOLUMNDESC);
HWND hWndOrder = ::GetDlgItem(hWnd, IDC_ORDER);
INDEX iSelOrder = (INDEX)SendMessage(hWndOrder, CB_GETCURSEL, 0, 0);
// get the selected item
iSel = ListView_GetNextItem(hWndIndexColumnDesc, -1, LVNI_SELECTED);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
wSendMessage(hWndOrder, CB_GETLBTEXT, (WPARAM)iSelOrder, wszBuffer);
LV_SetItemText(hWndIndexColumnDesc, iSel, COLUMN_ORDER, wszBuffer);
return 0;
}
}
return 0;
}
}
//Regular command messages
switch(GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_INDEXPROPERTIES:
{
//Get the "this" pointer
CMDIChild *pThis = (CMDIChild*)GetThis(hWnd);
CMainWindow* pCMainWindow = pThis->m_pCMainWindow;
CDataSource* pCDataSource = SOURCE_GETPARENT(pThis->m_pCSource, CDataSource);
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_INDEXALL, IID_IRowsetInfo, NULL, pCDataSource ? pCDataSource->m_pIDBProperties : NULL, &pThis->m_CDefPropSets);
return 0;
}
case IDB_ADD:
{
HWND hWndIndexColumnDesc = ::GetDlgItem(hWnd, IDL_INDEXCOLUMNDESC);
ULONG cItems = ListView_GetItemCount(hWndIndexColumnDesc);
// make the insertion
StringFormat(wszBuffer, NUMELE(wszBuffer), L"Column%lu", cItems);
LV_InsertItem(hWndIndexColumnDesc, cItems, COLUMN_ID, wszBuffer);
// order
LV_InsertItem(hWndIndexColumnDesc, cItems, COLUMN_ORDER, L"Ascendent");
LV_SetItemState(hWndIndexColumnDesc, cItems, COLUMN_ID, LVIS_SELECTED, LVIS_SELECTED);
return 0;
}
case IDB_DELETE:
{
HWND hWndIndexColumnDesc = ::GetDlgItem(hWnd, IDL_INDEXCOLUMNDESC);
INT cItems = ListView_GetItemCount(hWndIndexColumnDesc);
// get the selected item
iSel = ListView_GetNextItem(hWndIndexColumnDesc, -1, LVNI_SELECTED);
if (iSel > -1)
{
ListView_DeleteItem(hWndIndexColumnDesc, iSel);
SendMessage(::GetDlgItem(hWnd, IDE_COLNAME), WM_SETTEXT, 0, (LPARAM)"");
LV_SetItemState(hWndIndexColumnDesc, iSel >= cItems-1 ? iSel-1: iSel,
COLUMN_DBCID, LVIS_SELECTED, LVIS_SELECTED);
}
//Disable fields
::EnableWindow(::GetDlgItem(hWnd, IDE_COLUMNID), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDC_ORDER), FALSE);
return 0;
}
case IDCANCEL:
{
//Cleanup any memory allocated
SAFE_FREE(pStringBuffer);
EndDialog(hWnd, FALSE);
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild *pThis = (CMDIChild*)GetThis(hWnd);
CSession *pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
HWND hWndIndexColumnDesc = ::GetDlgItem(hWnd, IDL_INDEXCOLUMNDESC);
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
HWND hWndIndexID = ::GetDlgItem(hWnd, IDE_INDEXID);
DBINDEXCOLUMNDESC *rgIndexColumnDesc = NULL;
ULONG cIndexColumnDesc = 0;
DBID TableID;
WCHAR wszTableDBID[MAX_QUERY_LEN+1];
DBID IndexID;
WCHAR wszIndexDBID[MAX_QUERY_LEN+1];
DBPROPSET *rgPropSet = NULL;
ULONG cPropSet = 0;
HRESULT hr;
// alloc space for the column desc array
cIndexColumnDesc = ListView_GetItemCount(hWndIndexColumnDesc);
SAFE_ALLOC(rgIndexColumnDesc, DBINDEXCOLUMNDESC, cIndexColumnDesc);
// get the column desc array
for (i=0; i<cIndexColumnDesc; i++)
{
// initialize the whole structure
memset(&rgIndexColumnDesc[i], 0, sizeof(DBINDEXCOLUMNDESC));
// get column name
LV_GetItemText(hWndIndexColumnDesc, i, COLUMN_ID, wszBuffer, MAX_NAME_LEN);
SAFE_ALLOC(rgIndexColumnDesc[i].pColumnID, DBID, 1);
rgIndexColumnDesc[i].pColumnID->eKind = DBKIND_NAME;
rgIndexColumnDesc[i].pColumnID->uName.pwszName = wcsDuplicate(wszBuffer);
// get column order
LV_GetItemText(hWndIndexColumnDesc, i, COLUMN_ORDER, wszBuffer, MAX_NAME_LEN);
if (StringCompare(wszBuffer, L"Descendent"))
rgIndexColumnDesc[i].eIndexColOrder = DBINDEX_COL_ORDER_DESC;
else
rgIndexColumnDesc[i].eIndexColOrder = DBINDEX_COL_ORDER_ASC;
}
// get TableID
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = wGetWindowText(hWndTableID);
DBIDToString(&TableID, wszTableDBID, MAX_QUERY_LEN);
// get IndexID
IndexID.eKind = DBKIND_NAME;
IndexID.uName.pwszName = wGetWindowText(hWndIndexID);
DBIDToString(&IndexID, wszIndexDBID, MAX_QUERY_LEN);
// check whether rowset/table properties are used
if(::IsDlgButtonChecked(hWnd, IDB_USEPROPERTIES))
{
cPropSet = pThis->m_CDefPropSets.GetCount();
rgPropSet = pThis->m_CDefPropSets.GetPropSets();
}
XTEST(hr = pCSession->m_pIIndexDefinition->CreateIndex(&TableID, &IndexID, cIndexColumnDesc, rgIndexColumnDesc, cPropSet, rgPropSet, NULL));
TESTC(TRACE_METHOD(hr, L"IIndexDefinition::CreateIndex(%s, %s, %lu, 0x%p, %d, 0x%p, NULL)", wszTableDBID, wszIndexDBID, cIndexColumnDesc, rgIndexColumnDesc, cPropSet, rgPropSet));
CLEANUP:
for (i=0; i<cIndexColumnDesc; i++)
{
if (DBKIND_NAME == rgIndexColumnDesc[i].pColumnID->eKind)
SAFE_FREE(rgIndexColumnDesc[i].pColumnID->uName.pwszName);
}
if(SUCCEEDED(hr))
{
//Now just need to place this name in the EditBox
//Inserted after the current "caret"
pThis->m_pCQueryBox->ReplaceAll(TableID.uName.pwszName, FALSE/*bReplaceAll*/, TRUE/*fHighlight*/);
EndDialog(hWnd, TRUE);
}
SAFE_FREE(rgIndexColumnDesc);
SAFE_FREE(TableID.uName.pwszName);
SAFE_FREE(IndexID.uName.pwszName);
return 0;
}
}
break;
}//WM_COMMAND
case WM_NOTIFY:
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)lParam;
//ListView
switch(pDispInfo->hdr.code)
{
//Since we have "TwoClickActive" on this will get sent
//Whenever a row is clicked on twice!
//This functionality used to be done with NM_DBCLK
case LVN_ITEMACTIVATE:
{
return FALSE;
}
case LVN_ITEMCHANGED:
{
HWND hWndIndexColumnDesc = ::GetDlgItem(hWnd, IDL_INDEXCOLUMNDESC);
HWND hWndColumnID = ::GetDlgItem(hWnd, IDE_COLUMNID);
HWND hWndOrder = ::GetDlgItem(hWnd, IDC_ORDER);
HWND hWndColName = ::GetDlgItem(hWnd, IDE_COLNAME);
WCHAR wszBuffer2[MAX_NAME_LEN+1];
NMLISTVIEW *pLV = (NMLISTVIEW*)lParam;
INDEX iOrder = 0;
if (pLV->uChanged != LVIF_STATE)
return 0;
// get the selected item
iSel = pLV->iItem;
if (!(pLV->uNewState & LVIS_SELECTED))
{
if (!(pLV->uOldState & LVIS_SELECTED))
return 0;
// this is the previously selected item
// retrieve the column name and copy it to the IDE_COLUMNID field
wSendMessage(hWndColumnID, WM_GETTEXT, MAX_NAME_LEN, wszBuffer2);
LV_SetItemText(hWndIndexColumnDesc, iSel, COLUMN_ID, wszBuffer2);
StringFormat(wszBuffer, NUMELE(wszBuffer), L"Current item %lu (%s)", iSel, wszBuffer2);
wSendMessage(hWndColName, WM_SETTEXT, 0, wszBuffer);
// retrieve the column type and copy it to the IDC_ORDER field
iOrder = (INDEX)SendMessage(hWndOrder, CB_GETCURSEL, 0, 0);
wSendMessage(hWndOrder, CB_GETLBTEXT, iOrder, wszBuffer);
LV_SetItemText(hWndIndexColumnDesc, iSel, COLUMN_ORDER, wszBuffer);
}
else
{
// retrieve the column name and copy it to the IDE_COLUMNID field
LV_GetItemText(hWndIndexColumnDesc, iSel, COLUMN_ID, wszBuffer2, MAX_NAME_LEN);
wSendMessage(hWndColumnID, WM_SETTEXT, 0, wszBuffer2);
StringFormat(wszBuffer, NUMELE(wszBuffer), L"Current item %lu (%s)", iSel, wszBuffer2);
wSendMessage(hWndColName, WM_SETTEXT, 0, wszBuffer);
// retrieve the column type and copy it to the IDC_ORDER field
LV_GetItemText(hWndIndexColumnDesc, iSel, COLUMN_ORDER, wszBuffer, MAX_NAME_LEN);
SendMessage(hWndOrder, CB_SELECTSTRING, -1, (LPARAM)wszBuffer);
}
//Disable fields
::EnableWindow(::GetDlgItem(hWnd, IDE_COLUMNID), TRUE);
::EnableWindow(::GetDlgItem(hWnd, IDC_ORDER), TRUE);
return FALSE;
}
case LVN_ITEMCHANGING:
{
return FALSE; //Allow the change
}
}
}//WM_NOTIFY
}//switch message
return FALSE;
} //CMDIChild::CreateIndexProc
////////////////////////////////////////////////////////////////
// CMDIChild::DropIndexProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::DropIndexProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static CRichEditLite s_editTableID;
static CRichEditLite s_editIndexID;
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
//Fill In TableID as Default
s_editTableID.CreateIndirect(hWnd, IDE_TABLEID);
WCHAR* pwszIndexName = pThis->m_pCQueryBox->GetSelectedText();
s_editTableID.SetWindowText(pwszIndexName);
//Fill In IndexID
s_editIndexID.CreateIndirect(hWnd, IDE_INDEXID);
CenterDialog(hWnd);
SAFE_FREE(pwszIndexName);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
WCHAR wszTableDBID[MAX_NAME_LEN+1];
WCHAR wszIndexDBID[MAX_NAME_LEN+1];
HRESULT hr = S_OK;
//TableID
DBID TableID;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = s_editTableID.GetWindowText();
DBID* pTableID = TableID.uName.pwszName ? &TableID : NULL;
DBIDToString(pTableID, wszTableDBID, MAX_NAME_LEN);
//IndexID
DBID IndexID;
IndexID.eKind = DBKIND_NAME;
IndexID.uName.pwszName = s_editIndexID.GetWindowText();
DBID* pIndexID = IndexID.uName.pwszName ? &IndexID : NULL;
DBIDToString(pIndexID, wszIndexDBID, MAX_NAME_LEN);
//IIndexDefinition::DropIndex
XTEST(hr = pCSession->m_pIIndexDefinition->DropIndex(pTableID, pIndexID));
TRACE_METHOD(hr, L"IIndexDefinition::DropIndex(%s, %s)", wszTableDBID, wszIndexDBID);
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
SAFE_FREE(TableID.uName.pwszName);
SAFE_FREE(IndexID.uName.pwszName);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::AddColumnProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::AddColumnProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static CComboBoxGuid s_CComboInterface;
static BOOL fUseProps = TRUE; //Default to TRUE
static WCHAR wszBuffer[MAX_NAME_LEN+1];
ULONG i;
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
INDEX iSel = 0;
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
HWND hWndTypeName = ::GetDlgItem(hWnd, IDC_TYPENAME);
HWND hWndDataType = ::GetDlgItem(hWnd, IDC_TYPE);
HWND hWndSize = ::GetDlgItem(hWnd, IDE_SIZE);
HWND hWndPrecision = ::GetDlgItem(hWnd, IDE_PRECISION);
HWND hWndScale = ::GetDlgItem(hWnd, IDE_SCALE);
//Make sure we have the Provider Types rowset ahead of time
pCSession->GetProviderTypes();
//Fill In TableID as Default
WCHAR* pwszTableName = pThis->m_pCQueryBox->GetSelectedText();
wSendMessage(hWndTableID, WM_SETTEXT, 0, pwszTableName);
//Fill In column size as Default
wSendMessageFmt(hWndSize, WM_SETTEXT, 0, L"%d", 0);
//Fill In column precision as Default
wSendMessageFmt(hWndPrecision, WM_SETTEXT, 0, L"%d", 0);
//Fill In column scale as Default
wSendMessageFmt(hWndScale, WM_SETTEXT, 0, L"%d", 0);
//Use Properties
::CheckDlgButton(hWnd, IDB_USEPROPERTIES, BST2STATE(fUseProps));
// Type Name list...
for(i=0; i<pCSession->m_cProvTypes; i++)
{
//Type Name
iSel = (INDEX)wSendMessage(hWndTypeName, CB_ADDSTRING, 0, pCSession->m_rgProvTypes[i].wszTypeName);
}
SendMessage(hWndTypeName, CB_SETCURSEL, 0, 0);
// DBType list
for(i=0; i<g_cDBTypes; i++)
{
//DBTypes
iSel = (INDEX)wSendMessage(hWndDataType, CB_ADDSTRING, 0, g_rgDBTypes[i].pwszName);
}
SendMessage(hWndDataType, CB_SETCURSEL, 0, 0);
for (i=0; i<g_cDBTypes; i++)
{
if (pCSession->m_rgProvTypes[0].wType == g_rgDBTypes[i].lItem)
{
SendMessage(hWndDataType, CB_SETCURSEL, i, 0);
break;
}
}
CenterDialog(hWnd);
SAFE_FREE(pwszTableName);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
//CBN_SELCHANGE
switch(GET_WM_COMMAND_CMD(wParam, lParam))
{
//Selection change
case CBN_SELCHANGE:
{
//See which combo box has changed
switch(GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_TYPE:
{
CMDIChild *pThis = (CMDIChild*)GetThis(hWnd);
CSession *pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
HWND hWndSize = ::GetDlgItem(hWnd, IDE_SIZE);
HWND hWndPrecision = ::GetDlgItem(hWnd, IDE_PRECISION);
HWND hWndScale = ::GetDlgItem(hWnd, IDE_SCALE);
INDEX iSelTypeName;
HWND hWndTypeName = ::GetDlgItem(hWnd, IDC_TYPENAME);
//Get the Selected Type
CComboBoxLite comboTypes(hWnd, IDC_TYPE);
comboTypes.GetSelText(wszBuffer, MAX_NAME_LEN);
DBTYPE wType = GetDBType(wszBuffer);
//Get Default Size,Prec,Scale for this type...
DBLENGTH ulMaxSize = 0;
BYTE bPrecision, bScale;
GetDBTypeMaxSize(wType, &ulMaxSize, &bPrecision, &bScale);
//Set Size
wSendMessageFmt(hWndSize, WM_SETTEXT, 0, L"%Iu", ulMaxSize!=0 ? ulMaxSize : 255);
//Set Precision
wSendMessageFmt(hWndPrecision, WM_SETTEXT, 0, L"%d", bPrecision);
//Set Scale
wSendMessageFmt(hWndScale, WM_SETTEXT, 0, L"%d", bScale);
// determine a type on the DBTYPE
for (i = 0; i < pCSession->m_cProvTypes; i++)
{
if (wType == pCSession->m_rgProvTypes[i].wType)
iSelTypeName = i;
}
SendMessage(hWndTypeName, CB_SETCURSEL, iSelTypeName, 0);
return 0;
}
break;
case IDC_TYPENAME:
{
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
HWND hWndTypeName = ::GetDlgItem(hWnd, IDC_TYPENAME);
HWND hWndDataType = ::GetDlgItem(hWnd, IDC_TYPE);
HWND hWndColSize = ::GetDlgItem(hWnd, IDE_SIZE);
HWND hWndColPrec = ::GetDlgItem(hWnd, IDE_PRECISION);
HWND hWndColScale = ::GetDlgItem(hWnd, IDE_SCALE);
INDEX iSelTypeName = (INDEX)SendMessage(hWndTypeName, CB_GETCURSEL, 0, 0);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
wSendMessage(hWndTypeName, CB_GETLBTEXT, (WPARAM)iSelTypeName, wszBuffer);
if (iSelTypeName >= 0)
{
wSendMessage(hWndDataType, CB_SELECTSTRING, -1, GetDBTypeName(pCSession->m_rgProvTypes[iSelTypeName].wType));
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", pCSession->m_rgProvTypes[iSelTypeName].ulColumnSize);
wSendMessage(hWndColSize, WM_SETTEXT, 0, wszBuffer);
if (IsNumericType(pCSession->m_rgProvTypes[iSelTypeName].wType))
{
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", pCSession->m_rgProvTypes[iSelTypeName].ulColumnSize);
wSendMessage(hWndColPrec, WM_SETTEXT, 0, wszBuffer);
}
else
{
SendMessage(hWndColPrec, WM_SETTEXT, 0, (LPARAM)"0");
}
}
}
break;
}
break;
}
return FALSE;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_SETPROPERTIES:
{
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CMainWindow* pCMainWindow = pThis->m_pCMainWindow;
CDataSource* pCDataSource = SOURCE_GETPARENT(pThis->m_pCSource, CDataSource);
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_COLUMNALL, IID_IRowsetInfo, NULL, pCDataSource ? pCDataSource->m_pIDBProperties : NULL, &pThis->m_CDefPropSets);
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
HWND hWndColumnID = ::GetDlgItem(hWnd, IDE_COLUMNID);
HWND hWndTypeName = ::GetDlgItem(hWnd, IDC_TYPENAME);
HWND hWndSize = ::GetDlgItem(hWnd, IDE_SIZE);
HWND hWndPrecision = ::GetDlgItem(hWnd, IDE_PRECISION);
HWND hWndScale = ::GetDlgItem(hWnd, IDE_SCALE);
WCHAR wszTableDBID[MAX_QUERY_LEN+1];
WCHAR wszBuffer[MAX_NAME_LEN+1];
HRESULT hr = S_OK;
DBCOLUMNDESC ColumnDesc;
LONG lValue;
// initialize column desc stru
memset(&ColumnDesc, 0, sizeof(DBCOLUMNDESC));
// TableID
DBID TableID;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = wGetWindowText(hWndTableID);
DBIDToString(&TableID, wszTableDBID, MAX_QUERY_LEN);
// ColumnID of ColumnDesc
ColumnDesc.dbcid.eKind = DBKIND_NAME;
ColumnDesc.dbcid.uName.pwszName = wGetWindowText(hWndColumnID);
// Column Size
GetEditBoxValue(hWndSize, &lValue, 0, LONG_MAX, TRUE);
ColumnDesc.ulColumnSize = lValue;
// Column Precision
GetEditBoxValue(hWndPrecision, &lValue, 0, 255, TRUE);
ColumnDesc.bPrecision = (BYTE)lValue;
// Column Scale
GetEditBoxValue(hWndScale, &lValue, 0, 255, TRUE);
ColumnDesc.bScale = (BYTE)lValue;
//Use Properties
fUseProps = ::IsDlgButtonChecked(hWnd, IDB_USEPROPERTIES);
if(fUseProps)
{
ColumnDesc.cPropertySets = pThis->m_CDefPropSets.GetCount();
ColumnDesc.rgPropertySets = pThis->m_CDefPropSets.GetPropSets();
}
// Type Name
ColumnDesc.pwszTypeName = wGetWindowText(hWndTypeName);
// DBType
CComboBoxLite comboTypes(hWnd, IDC_TYPE);
comboTypes.GetSelText(wszBuffer, MAX_NAME_LEN);
ColumnDesc.wType = GetDBType(wszBuffer);
// ITableDefinition::AddColumn
XTEST(hr = pCSession->m_pITableDefinition->AddColumn(&TableID, &ColumnDesc, NULL));
TESTC(TRACE_METHOD(hr, L"ITableDefinition::AddColumn(%s, 0x%p, NULL)", wszTableDBID, &ColumnDesc));
if(SUCCEEDED(hr))
{
//Now just need to place this name in the EditBox
//Inserted after the current "caret"
pThis->m_pCQueryBox->ReplaceAll(TableID.uName.pwszName, FALSE/*bReplaceAll*/, TRUE/*fHighlight*/);
EndDialog(hWnd, TRUE);
}
SAFE_FREE(TableID.uName.pwszName);
SAFE_FREE(ColumnDesc.dbcid.uName.pwszName);
SAFE_FREE(ColumnDesc.pwszTypeName);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
CLEANUP:
return FALSE;
} // CMDIChild::AddColumnProc
////////////////////////////////////////////////////////////////
// CMDIChild::CreateTableProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::CreateTableProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static CComboBoxGuid s_CComboInterface;
static WCHAR wszBuffer[MAX_NAME_LEN+1];
static BOOL fUseProps = TRUE;
static BOOL fAggregation = FALSE; //Default
static BOOL fOutput = TRUE; //Default
switch(message)
{
case WM_INITDIALOG:
{
//Save the "this" pointer
CWaitCursor waitCursor;
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
//Use Extended ListView Styles!
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
HWND hWndTypeName = ::GetDlgItem(hWnd, IDC_TYPENAME);
HWND hWndDataType = ::GetDlgItem(hWnd, IDC_DATATYPE);
HWND hWndColumnID = ::GetDlgItem(hWnd, IDE_COLUMNID);
HWND hWndColSize = ::GetDlgItem(hWnd, IDE_SIZE);
HWND hWndColPrec = ::GetDlgItem(hWnd, IDE_PRECISION);
HWND hWndColScale = ::GetDlgItem(hWnd, IDE_SCALE);
RECT rect;
SendMessage(hWndColumnDesc, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE);
//ColumnHeaders for COLUMNDESC report
LV_InsertColumn(hWndColumnDesc, COLUMN_DBCID, L"Column DBCID", IMAGE_NONE);
LV_InsertColumn(hWndColumnDesc, COLUMN_TYPENAME, L"TypeName", IMAGE_NONE);
LV_InsertColumn(hWndColumnDesc, COLUMN_DATATYPE, L"DataType", IMAGE_NONE);
LV_InsertColumn(hWndColumnDesc, COLUMN_SIZE, L"Size", IMAGE_NONE);
LV_InsertColumn(hWndColumnDesc, COLUMN_PREC, L"Precision", IMAGE_NONE);
LV_InsertColumn(hWndColumnDesc, COLUMN_SCALE, L"Scale", IMAGE_NONE);
//AutoSize Columns
GetWindowRect(hWndColumnID, (LPRECT)&rect);
SendMessage(hWndColumnDesc, LVM_SETCOLUMNWIDTH, (WPARAM)COLUMN_DBCID, (LPARAM)(rect.right-rect.left));
GetWindowRect(hWndTypeName, (LPRECT)&rect);
SendMessage(hWndColumnDesc, LVM_SETCOLUMNWIDTH, (WPARAM)COLUMN_TYPENAME, (LPARAM)(rect.right-rect.left));
GetWindowRect(hWndDataType, (LPRECT)&rect);
SendMessage(hWndColumnDesc, LVM_SETCOLUMNWIDTH, (WPARAM)COLUMN_DATATYPE, (LPARAM)(rect.right-rect.left));
GetWindowRect(hWndColSize, (LPRECT)&rect);
SendMessage(hWndColumnDesc, LVM_SETCOLUMNWIDTH, (WPARAM)COLUMN_SIZE, (LPARAM)(rect.right-rect.left));
GetWindowRect(hWndColPrec, (LPRECT)&rect);
SendMessage(hWndColumnDesc, LVM_SETCOLUMNWIDTH, (WPARAM)COLUMN_PREC, (LPARAM)(rect.right-rect.left));
GetWindowRect(hWndColScale, (LPRECT)&rect);
SendMessage(hWndColumnDesc, LVM_SETCOLUMNWIDTH, (WPARAM)COLUMN_SCALE, (LPARAM)(rect.right-rect.left));
//Make sure we have the Provider Types rowset ahead of time
pCSession->GetProviderTypes();
ULONG i;
// Type Name list...
for(i=0; i<pCSession->m_cProvTypes; i++)
{
//Type Name
wSendMessage(hWndTypeName, CB_ADDSTRING, 0, pCSession->m_rgProvTypes[i].wszTypeName);
}
SendMessage(hWndTypeName, CB_SETCURSEL, 0, 0);
// DBType list
for(i=0; i<g_cDBTypes; i++)
{
//DBTypes
wSendMessage(hWndDataType, CB_ADDSTRING, 0, g_rgDBTypes[i].pwszName);
}
for (i=0; i<g_cDBTypes; i++)
{
if (pCSession->m_rgProvTypes[0].wType == g_rgDBTypes[i].lItem)
{
SendMessage(hWndDataType, CB_SETCURSEL, i, 0);
break;
}
}
//Use Properties
::CheckDlgButton(hWnd, IDB_USEPROPERTIES, BST2STATE(fUseProps));
//Aggregation
::CheckDlgButton(hWnd, IDB_AGGREGATION, BST2STATE(fAggregation));
//Output (ppIUnknown)
::CheckDlgButton(hWnd, IDB_OUTPUT, BST2STATE(fOutput));
//Interface List...
s_CComboInterface.CreateIndirect(hWnd, IDC_INTERFACE);
s_CComboInterface.Populate(g_cInterfaceMaps, g_rgInterfaceMaps);
if(s_CComboInterface.RestoreSelection() == CB_ERR)
s_CComboInterface.SetGuid(IID_IRowset);
pCSession->m_listCPropSets.RemoveAll();
//Fill In TableID as Default
WCHAR* pwszTableName = pThis->m_pCQueryBox->GetSelectedText();
wSendMessage(hWndTableID, WM_SETTEXT, 0, pwszTableName);
//Placement of Dialog, want it just below the "Init" button...
CenterDialog(hWnd);
//Disable fields
::EnableWindow(::GetDlgItem(hWnd, IDB_COLPROP), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDE_COLUMNID), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDC_TYPENAME), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDC_DATATYPE), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDE_SIZE), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDE_PRECISION), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDE_SCALE), FALSE);
SendMessage(hWndTypeName, CB_SETCURSEL, 0, 0);
SAFE_FREE(pwszTableName);
return TRUE;
}
case WM_COMMAND:
{
switch (GET_WM_COMMAND_CMD(wParam, lParam))
{
case EN_KILLFOCUS:
{
switch((int)LOWORD(wParam))
{
case IDE_COLUMNID:
{
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
HWND hWndColumnID = ::GetDlgItem(hWnd, IDE_COLUMNID);
HWND hWndColName = ::GetDlgItem(hWnd, IDE_COLNAME);
WCHAR wszBuffer2[MAX_NAME_LEN+1];
// get the selected item
INDEX iSel = ListView_GetNextItem(hWndColumnDesc, -1, LVNI_SELECTED);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
// and to Column Name static field
wSendMessage(hWndColumnID, WM_GETTEXT, MAX_NAME_LEN, wszBuffer2);
StringFormat(wszBuffer, NUMELE(wszBuffer), L"Current item %Iu (%s)", iSel, wszBuffer2);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_DBCID, wszBuffer2);
wSendMessage(hWndColName, WM_SETTEXT, 0, wszBuffer);
break;
}
case IDE_SIZE:
{
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
HWND hWndColSize = ::GetDlgItem(hWnd, IDE_SIZE);
// get the selected item
INDEX iSel = ListView_GetNextItem(hWndColumnDesc, -1, LVNI_SELECTED);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
// and to Column Name static field
wSendMessage(hWndColSize, WM_GETTEXT, MAX_NAME_LEN, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_SIZE, wszBuffer);
break;
}
case IDE_PRECISION:
{
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
HWND hWndColPrec = ::GetDlgItem(hWnd, IDE_PRECISION);
// get the selected item
INDEX iSel = ListView_GetNextItem(hWndColumnDesc, -1, LVNI_SELECTED);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
// and to Column Name static field
wSendMessage(hWndColPrec, WM_GETTEXT, MAX_NAME_LEN, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_PREC, wszBuffer);
break;
}
case IDE_SCALE:
{
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
HWND hWndColScale = ::GetDlgItem(hWnd, IDE_SCALE);
// get the selected item
INDEX iSel = ListView_GetNextItem(hWndColumnDesc, -1, LVNI_SELECTED);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
// and to Column Name static field
wSendMessage(hWndColScale, WM_GETTEXT, MAX_NAME_LEN, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_SCALE, wszBuffer);
break;
}
}
return 0;
}
}
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
//CBN_SELCHANGE
switch(GET_WM_COMMAND_CMD(wParam, lParam))
{
case CBN_SELCHANGE:
{
switch(GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_TYPENAME:
{
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
HWND hWndTypeName = ::GetDlgItem(hWnd, IDC_TYPENAME);
HWND hWndDataType = ::GetDlgItem(hWnd, IDC_DATATYPE);
HWND hWndColSize = ::GetDlgItem(hWnd, IDE_SIZE);
HWND hWndColPrec = ::GetDlgItem(hWnd, IDE_PRECISION);
HWND hWndColScale = ::GetDlgItem(hWnd, IDE_SCALE);
INDEX iSelTypeName = (INDEX)SendMessage(hWndTypeName, CB_GETCURSEL, 0, 0);
// get the selected item
INDEX iSel = ListView_GetNextItem(hWndColumnDesc, -1, LVNI_SELECTED);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
wSendMessage(hWndTypeName, CB_GETLBTEXT, (WPARAM)iSelTypeName, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_TYPENAME, wszBuffer);
if (iSelTypeName >= 0)
{
wSendMessage(hWndDataType, CB_SELECTSTRING, -1, GetDBTypeName(pCSession->m_rgProvTypes[iSelTypeName].wType));
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_DATATYPE, GetDBTypeName(pCSession->m_rgProvTypes[iSelTypeName].wType));
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", pCSession->m_rgProvTypes[iSelTypeName].ulColumnSize);
wSendMessage(hWndColSize, WM_SETTEXT, 0, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_SIZE, wszBuffer);
if (IsNumericType(pCSession->m_rgProvTypes[iSelTypeName].wType))
{
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", pCSession->m_rgProvTypes[iSelTypeName].ulColumnSize);
wSendMessage(hWndColPrec, WM_SETTEXT, 0, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_PREC, wszBuffer);
}
else
{
SendMessage(hWndColPrec, WM_SETTEXT, 0, (LPARAM)"0");
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_PREC, wszBuffer);
}
}
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pCSession->m_rgProvTypes[iSelTypeName].iMaxScale);
wSendMessage(hWndColScale, WM_SETTEXT, 0, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_SCALE, wszBuffer);
}
break;
case IDC_DATATYPE:
{
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
HWND hWndTypeName = ::GetDlgItem(hWnd, IDC_TYPENAME);
HWND hWndDataType = ::GetDlgItem(hWnd, IDC_DATATYPE);
HWND hWndColSize = ::GetDlgItem(hWnd, IDE_SIZE);
HWND hWndColPrec = ::GetDlgItem(hWnd, IDE_PRECISION);
HWND hWndColScale = ::GetDlgItem(hWnd, IDE_SCALE);
INDEX iSelDBType = (INDEX)SendMessage(hWndDataType, CB_GETCURSEL, 0, 0);
ULONG i;
INT iSelTypeName = 0;
DBTYPE wType;
// get the selected item
INDEX iSel = ListView_GetNextItem(hWndColumnDesc, -1, LVNI_SELECTED);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
wSendMessage(hWndDataType, CB_GETLBTEXT, (WPARAM)iSelDBType, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_DATATYPE, wszBuffer);
// determine a type on the DBTYPE
wType = (DBTYPE)g_rgDBTypes[iSelDBType].lItem;
for (i = 0; i < pCSession->m_cProvTypes; i++)
{
if (wType == pCSession->m_rgProvTypes[i].wType)
iSelTypeName = i;
}
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", pCSession->m_rgProvTypes[iSelTypeName].ulColumnSize);
SendMessage(hWndColSize, WM_SETTEXT, 0, (LPARAM)wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_SIZE, wszBuffer);
if(IsNumericType(wType))
{
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", pCSession->m_rgProvTypes[iSelTypeName].ulColumnSize);
wSendMessage(hWndColPrec, WM_SETTEXT, 0, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_PREC, wszBuffer);
}
else
{
SendMessage(hWndColPrec, WM_SETTEXT, 0, (LPARAM)"0");
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_PREC, wszBuffer);
}
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pCSession->m_rgProvTypes[iSelTypeName].iMaxScale);
wSendMessage(hWndColScale, WM_SETTEXT, 0, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_SCALE, wszBuffer);
SendMessage(hWndTypeName, CB_SETCURSEL, iSelTypeName, 0);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_TYPENAME, pCSession->m_rgProvTypes[iSelTypeName].wszTypeName);
}
break;
}
return 0;
}
}
//Regular command messages
switch(GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_ROWSETPROPERTIES:
{
//Get the "this" pointer
CMDIChild *pThis = (CMDIChild*)GetThis(hWnd);
CMainWindow* pCMainWindow = pThis->m_pCMainWindow;
CDataSource *pCDataSource = SOURCE_GETPARENT(pThis->m_pCSource, CDataSource);
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_ROWSETALL, IID_IRowsetInfo, NULL, pCDataSource ? pCDataSource->m_pIDBProperties : NULL, &pThis->m_CDefPropSets);
return 0;
}
case IDB_COLPROP:
{
//Get the "this" pointer
CMDIChild *pThis = (CMDIChild*)GetThis(hWnd);
CMainWindow* pCMainWindow = pThis->m_pCMainWindow;
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
CDataSource* pCDataSource = SOURCE_GETPARENT(pCSession, CDataSource);
// get the selected item
ULONG iSel = ListView_GetNextItem(hWndColumnDesc, -1, LVNI_SELECTED);
if ((LONG)iSel <0)
return 0;
POSITION pos = pCSession->m_listCPropSets.FindIndex(iSel);
CPropSets* pPropEl = pCSession->m_listCPropSets.GetAt(pos);
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_COLUMNALL, IID_IRowsetInfo, NULL, pCDataSource ? pCDataSource->m_pIDBProperties : NULL, pPropEl);
return 0;
}
case IDB_ADD:
{
CMDIChild *pThis = (CMDIChild*)GetThis(hWnd);
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
ULONG cItems = ListView_GetItemCount(hWndColumnDesc);
// make the insertion
StringFormat(wszBuffer, NUMELE(wszBuffer), L"Column%lu", cItems);
LV_InsertItem(hWndColumnDesc, cItems, COLUMN_DBCID, wszBuffer);
// type name
LV_InsertItem(hWndColumnDesc, cItems, COLUMN_TYPENAME, pCSession->m_rgProvTypes[0].wszTypeName);
ULONG i;
// data type
for(i=0; i<g_cDBTypes; i++)
{
if (pCSession->m_rgProvTypes[0].wType == g_rgDBTypes[i].lItem)
break;
}
LV_InsertItem(hWndColumnDesc, cItems, COLUMN_DATATYPE, g_rgDBTypes[i].pwszName);
// Column Size, Precision and Scale
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%Iu", pCSession->m_rgProvTypes[0].ulColumnSize);
LV_InsertItem(hWndColumnDesc, cItems, COLUMN_SIZE, wszBuffer);
LV_InsertItem(hWndColumnDesc, cItems, COLUMN_PREC, wszBuffer);
if (IsNumericType(pCSession->m_rgProvTypes[0].wType))
LV_InsertItem(hWndColumnDesc, cItems, COLUMN_PREC, wszBuffer);
else
LV_InsertItem(hWndColumnDesc, cItems, COLUMN_PREC, L"0");
StringFormat(wszBuffer, NUMELE(wszBuffer), L"%d", pCSession->m_rgProvTypes[0].iMaxScale);
LV_InsertItem(hWndColumnDesc, cItems, COLUMN_SCALE, wszBuffer);
// get the selected item
INDEX iSel = ListView_GetNextItem(hWndColumnDesc, -1, LVNI_SELECTED);
if(iSel < 0)
{
LV_SetItemState(hWndColumnDesc, 0, COLUMN_DBCID, LVIS_SELECTED, LVIS_SELECTED);
}
// enable column properties
::EnableWindow(::GetDlgItem(hWnd, IDB_COLPROP), TRUE);
// set column properties
pCSession->m_listCPropSets.AddTail(new CPropSets());
return 0;
}
case IDB_DELETE:
{
CMDIChild *pThis = (CMDIChild*)GetThis(hWnd);
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
ULONG cItems = ListView_GetItemCount(hWndColumnDesc);
// get the selected item
ULONG iSel = ListView_GetNextItem(hWndColumnDesc, -1, LVNI_SELECTED);
if(iSel != -1)
{
ListView_DeleteItem(hWndColumnDesc, iSel);
SendMessage(::GetDlgItem(hWnd, IDE_COLNAME), WM_SETTEXT, 0, (LPARAM)"");
// delete col props
POSITION pos = pCSession->m_listCPropSets.FindIndex(iSel);
CPropSets* pPropEl = pCSession->m_listCPropSets.RemoveAt(pos);
pPropEl->RemoveAll();
}
if (cItems > 1)
{
LV_SetItemState(hWndColumnDesc, iSel == cItems-1 ? iSel-1: iSel, COLUMN_DBCID, LVIS_SELECTED, LVIS_SELECTED);
}
else
{
//Disable fields
::EnableWindow(::GetDlgItem(hWnd, IDB_COLPROP), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDE_COLUMNID), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDC_TYPENAME), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDC_DATATYPE), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDE_SIZE), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDE_PRECISION), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDE_SCALE), FALSE);
}
return 0;
}
case IDB_AGGREGATION:
{
//Aggregation Combo Selection has changed...
//If we are now using Aggregation, automatically change the requested
//riid to IID_IUnknown, since its an error otherwise...
if(::IsDlgButtonChecked(hWnd, IDB_AGGREGATION))
s_CComboInterface.SetGuid(IID_IUnknown);
return 0;
}
case IDCANCEL:
{
//Cleanup any memory allocated
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
pCSession->m_listCPropSets.RemoveAll();
EndDialog(hWnd, FALSE);
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild *pThis = (CMDIChild*)GetThis(hWnd);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
DBCOLUMNDESC *rgColumnDesc = NULL;
ULONG cColumnDesc = 0;
IUnknown* pIUnknown = NULL;
DBID TableID;
WCHAR wszTableDBID[MAX_QUERY_LEN+1];
WCHAR wszTableName[MAX_NAME_LEN+1];
DBPROPSET *rgPropSet = NULL;
ULONG i,cPropSet = 0;
HRESULT hr;
ULONG ulValue;
POSITION pos;
CPropSets *pPropEl = NULL;
//Use Properties
fUseProps = ::IsDlgButtonChecked(hWnd, IDB_USEPROPERTIES);
//Obtain the Aggregation argument
CAggregate* pCAggregate = NULL;
fAggregation = ::IsDlgButtonChecked(hWnd, IDB_AGGREGATION);
if(fAggregation)
pCAggregate = new CAggregate();
//Obtain the Output (ppIUnknown) argument
fOutput = ::IsDlgButtonChecked(hWnd, IDB_OUTPUT);
//Interface
REFIID riid = s_CComboInterface.GetGuid();
// alloc space for the column desc array
cColumnDesc = ListView_GetItemCount(hWndColumnDesc);
SAFE_ALLOC(rgColumnDesc, DBCOLUMNDESC, cColumnDesc);
// get the column desc array
for(i=0; i<cColumnDesc; i++)
{
// initialize the whole structure
memset(&rgColumnDesc[i], 0, sizeof(DBCOLUMNDESC));
// get column name
LV_GetItemText(hWndColumnDesc, i, COLUMN_DBCID, wszBuffer, MAX_NAME_LEN);
rgColumnDesc[i].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[i].dbcid.uName.pwszName = wcsDuplicate(wszBuffer);
// get column type name
LV_GetItemText(hWndColumnDesc, i, COLUMN_TYPENAME, wszBuffer, MAX_NAME_LEN);
rgColumnDesc[i].pwszTypeName = wcsDuplicate(wszBuffer);
// get column data type
LV_GetItemText(hWndColumnDesc, i, COLUMN_DATATYPE, wszBuffer, MAX_NAME_LEN);
rgColumnDesc[i].wType = GetDBType(wszBuffer);
// get column size
LV_GetItemText(hWndColumnDesc, i, COLUMN_SIZE, wszBuffer, MAX_NAME_LEN);
rgColumnDesc[i].ulColumnSize = wcstoul(wszBuffer, NULL, 10);
// get column precision
LV_GetItemText(hWndColumnDesc, i, COLUMN_PREC, wszBuffer, MAX_NAME_LEN);
ulValue = wcstoul(wszBuffer, NULL, 10);
rgColumnDesc[i].bPrecision = (BYTE)ulValue;
// get column size
LV_GetItemText(hWndColumnDesc, i, COLUMN_SCALE, wszBuffer, MAX_NAME_LEN);
ulValue = wcstoul(wszBuffer, NULL, 10);
rgColumnDesc[i].bScale = (BYTE)ulValue;
// get properties
pos = pCSession->m_listCPropSets.FindIndex(i);
pPropEl = pCSession->m_listCPropSets.GetAt(pos);
rgColumnDesc[i].cPropertySets = pPropEl->GetCount();
rgColumnDesc[i].rgPropertySets = pPropEl->GetPropSets();
}
// get TableID
wSendMessage(hWndTableID, WM_GETTEXT, MAX_NAME_LEN, wszTableName);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = wszTableName;
DBIDToString(&TableID, wszTableDBID, MAX_QUERY_LEN);
// check whether rowset/table properties are used
if(fUseProps)
{
cPropSet = pThis->m_CDefPropSets.GetCount();
rgPropSet = pThis->m_CDefPropSets.GetPropSets();
}
//ITableDefinition::CreateTable
XTEST(hr = pCSession->m_pITableDefinition->CreateTable(pCAggregate, &TableID, cColumnDesc, rgColumnDesc, riid, cPropSet, rgPropSet, NULL, fOutput ? &pIUnknown : NULL));
TESTC(TRACE_METHOD(hr, L"ITableDefinition::CreateTable(0x%p, %s, %lu, 0x%p, %s, %d, 0x%p, NULL, &0x%p)", pCAggregate, wszTableDBID, cColumnDesc, rgColumnDesc, GetInterfaceName(riid), cPropSet, rgPropSet, pIUnknown));
if(fOutput)
{
//Handle Aggregation
if(pCAggregate)
pCAggregate->HandleAggregation(riid, &pIUnknown);
//Display the Result
//Just pass in a guess for the object type and let our helper figure out what object it is...
//NOTE: Can pontentially return other object types: (ie: CREATE_DETERMINE_TYPE)
if(!pThis->m_pCMainWindow->HandleObjectType(pCSession, pIUnknown, riid, eCRowset, 0, NULL, CREATE_NEWWINDOW_IFEXISTS | CREATE_DETERMINE_TYPE))
TESTC(hr = E_FAIL);
}
CLEANUP:
pThis->UpdateControls();
for (i=0; i<cColumnDesc; i++)
{
SAFE_FREE(rgColumnDesc[i].pwszTypeName);
if (DBKIND_NAME == rgColumnDesc[i].dbcid.eKind)
SAFE_FREE(rgColumnDesc[i].dbcid.uName.pwszName);
}
SAFE_FREE(rgColumnDesc);
SAFE_RELEASE(pIUnknown);
SAFE_RELEASE(pCAggregate);
if(SUCCEEDED(hr))
{
//Now just need to place this name in the EditBox
//Inserted after the current "caret"
pThis->m_pCQueryBox->ReplaceAll(wszTableName, FALSE/*bReplaceAll*/, TRUE/*fHighlight*/);
pCSession->m_listCPropSets.RemoveAll(); //FreeColumnProperties();
EndDialog(hWnd, TRUE);
return 0;
}
return 0;
}
}
break;
}//WM_COMMAND
case WM_NOTIFY:
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)lParam;
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lParam;
//ListView
switch(pDispInfo->hdr.code)
{
//Since we have "TwoClickActive" on this will get sent
//Whenever a row is clicked on twice!
//This functionality used to be done with NM_DBCLK
case LVN_ITEMACTIVATE:
{
return FALSE;
}
case LVN_ITEMCHANGED:
{
HWND hWndColumnDesc = ::GetDlgItem(hWnd, IDL_COLUMNDESC);
HWND hWndColumnID = ::GetDlgItem(hWnd, IDE_COLUMNID);
HWND hWndTypeName = ::GetDlgItem(hWnd, IDC_TYPENAME);
HWND hWndDataType = ::GetDlgItem(hWnd, IDC_DATATYPE);
HWND hWndColSize = ::GetDlgItem(hWnd, IDE_SIZE);
HWND hWndColPrec = ::GetDlgItem(hWnd, IDE_PRECISION);
HWND hWndColScale = ::GetDlgItem(hWnd, IDE_SCALE);
HWND hWndColName = ::GetDlgItem(hWnd, IDE_COLNAME);
WCHAR wszBuffer2[MAX_NAME_LEN+1];
NMLISTVIEW *pLV = (NMLISTVIEW*)lParam;
if (pLV->uChanged != LVIF_STATE)
return 0;
// get the selected item
INDEX iSel = pLV->iItem;
if (!(pLV->uNewState & LVIS_SELECTED))
{
if (!(pLV->uOldState & LVIS_SELECTED))
return 0;
// this is the previously selected item
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
// and to Column Name static field
wSendMessage(hWndColumnID, WM_GETTEXT, MAX_NAME_LEN, wszBuffer2);
StringFormat(wszBuffer, NUMELE(wszBuffer), L"Current item %Iu (%s)", iSel, wszBuffer2);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_DBCID, wszBuffer2);
wSendMessage(hWndColName, WM_SETTEXT, 0, wszBuffer);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
// and to Column Name static field
wSendMessage(hWndColSize, WM_GETTEXT, MAX_NAME_LEN, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_SIZE, wszBuffer);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
// and to Column Name static field
wSendMessage(hWndColPrec, WM_GETTEXT, MAX_NAME_LEN, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_PREC, wszBuffer);
// retrieve the column type name and copy it to the COLUMN_TYPENAME field of the list view
// and to Column Name static field
wSendMessage(hWndColScale, WM_GETTEXT, MAX_NAME_LEN, wszBuffer);
LV_SetItemText(hWndColumnDesc, iSel, COLUMN_SCALE, wszBuffer);
}
else
{
// retrieve the column name and copy it to the IDE_COLUMNID field
LV_GetItemText(hWndColumnDesc, iSel, COLUMN_DBCID, wszBuffer2, MAX_NAME_LEN);
wSendMessage(hWndColumnID, WM_SETTEXT, 0, wszBuffer2);
StringFormat(wszBuffer, NUMELE(wszBuffer), L"Current item %Iu (%s)", iSel, wszBuffer2);
wSendMessage(hWndColName, WM_SETTEXT, 0, wszBuffer);
// retrieve the column type and copy it to the IDC_TYPENAME field
LV_GetItemText(hWndColumnDesc, iSel, COLUMN_TYPENAME, wszBuffer, MAX_NAME_LEN);
wSendMessage(hWndTypeName, CB_SELECTSTRING, -1, wszBuffer);
// retrieve the column datatype and copy it to the IDC_DATATYPE field
LV_GetItemText(hWndColumnDesc, iSel, COLUMN_DATATYPE, wszBuffer, MAX_NAME_LEN);
wSendMessage(hWndDataType, CB_SELECTSTRING, -1, wszBuffer);
// retrieve the column size and copy it to the IDE_SIZE field
LV_GetItemText(hWndColumnDesc, iSel, COLUMN_SIZE, wszBuffer, MAX_NAME_LEN);
wSendMessage(hWndColSize, WM_SETTEXT, 0, wszBuffer);
// retrieve the column datatype and copy it to the IDE_PRECISION field
LV_GetItemText(hWndColumnDesc, iSel, COLUMN_PREC, wszBuffer, MAX_NAME_LEN);
wSendMessage(hWndColPrec, WM_SETTEXT, 0, wszBuffer);
// retrieve the column datatype and copy it to the IDE_SCALE field
LV_GetItemText(hWndColumnDesc, iSel, COLUMN_SCALE, wszBuffer, MAX_NAME_LEN);
wSendMessage(hWndColScale, WM_SETTEXT, 0, wszBuffer);
//Enable fields
::EnableWindow(::GetDlgItem(hWnd, IDB_COLPROP), TRUE);
::EnableWindow(::GetDlgItem(hWnd, IDE_COLUMNID), TRUE);
::EnableWindow(::GetDlgItem(hWnd, IDC_TYPENAME), TRUE);
::EnableWindow(::GetDlgItem(hWnd, IDC_DATATYPE), TRUE);
::EnableWindow(::GetDlgItem(hWnd, IDE_SIZE), TRUE);
::EnableWindow(::GetDlgItem(hWnd, IDE_PRECISION), TRUE);
::EnableWindow(::GetDlgItem(hWnd, IDE_SCALE), TRUE);
}
return FALSE;
}
case LVN_ITEMCHANGING:
{
return FALSE; //Allow the change
}
}
}//WM_NOTIFY
}//switch message
return FALSE;
} // CMDIChild::CreateTableProc
////////////////////////////////////////////////////////////////
// CMDIChild::DropColumnProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::DropColumnProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
//Fill In TableID as Default
WCHAR* pwszTableName = pThis->m_pCQueryBox->GetSelectedText();
wSendMessage(hWndTableID, WM_SETTEXT, 0, pwszTableName);
CenterDialog(hWnd);
SAFE_FREE(pwszTableName);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
HWND hWndColumnID = ::GetDlgItem(hWnd, IDE_COLUMNID);
WCHAR wszTableDBID[MAX_QUERY_LEN+1];
WCHAR wszColumnDBID[MAX_QUERY_LEN+1];
HRESULT hr = S_OK;
//TableID
DBID TableID;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = wGetWindowText(hWndTableID);
DBIDToString(&TableID, wszTableDBID, MAX_QUERY_LEN);
//ColumnID
DBID ColumnID;
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = wGetWindowText(hWndColumnID);
DBIDToString(&ColumnID, wszColumnDBID, MAX_QUERY_LEN);
//ITableDefinition::DropColumn
XTEST(hr = pCSession->m_pITableDefinition->DropColumn(&TableID, &ColumnID));
TESTC(TRACE_METHOD(hr, L"ITableDefinition::DropColumn(%s, %s)", wszTableDBID, wszColumnDBID));
if(SUCCEEDED(hr))
{
EndDialog(hWnd, TRUE);
}
SAFE_FREE(TableID.uName.pwszName);
SAFE_FREE(ColumnID.uName.pwszName);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
CLEANUP:
return FALSE;
} // CMDIChild::DropColumnProc
////////////////////////////////////////////////////////////////
// CMDIChild::DropTableProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::DropTableProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
//Fill In TableID as Default
WCHAR* pwszTableName = pThis->m_pCQueryBox->GetSelectedText();
wSendMessage(hWndTableID, WM_SETTEXT, 0, pwszTableName);
CenterDialog(hWnd);
SAFE_FREE(pwszTableName);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CSession* pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
WCHAR wszTableDBID[MAX_QUERY_LEN+1];
HRESULT hr = S_OK;
//TableID
DBID TableID;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = wGetWindowText(hWndTableID);
DBIDToString(&TableID, wszTableDBID, MAX_QUERY_LEN);
//ITableDefinition::DropTable
XTEST(hr = pCSession->m_pITableDefinition->DropTable(&TableID));
TRACE_METHOD(hr, L"ITableDefinition::DropTable(%s)", wszTableDBID);
if(SUCCEEDED(hr))
{
EndDialog(hWnd, TRUE);
}
SAFE_FREE(TableID.uName.pwszName);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::DropConstraintProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::DropConstraintProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
//Fill In TableID as Default
WCHAR* pwszTableName = pThis->m_pCQueryBox->GetSelectedText();
wSendMessage(hWndTableID, WM_SETTEXT, 0, pwszTableName);
CenterDialog(hWnd);
SAFE_FREE(pwszTableName);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild *pThis = (CMDIChild*)GetThis(hWnd);
CSession *pCSession = SOURCE_GETOBJECT(pThis->m_pCSource, CSession);
HWND hWndTableID = ::GetDlgItem(hWnd, IDE_TABLEID);
HWND hWndConsID = ::GetDlgItem(hWnd, IDE_CONSTRAINTID);
WCHAR wszTableDBID[MAX_QUERY_LEN+1];
WCHAR wszConsDBID[MAX_QUERY_LEN+1];
HRESULT hr = S_OK;
//TableID
DBID TableID;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = wGetWindowText(hWndTableID);
DBIDToString(&TableID, wszTableDBID, MAX_QUERY_LEN);
//ConstraintID
DBID ConstraintID;
ConstraintID.eKind = DBKIND_NAME;
ConstraintID.uName.pwszName = wGetWindowText(hWndConsID);
DBIDToString(&ConstraintID, wszConsDBID, MAX_QUERY_LEN);
//ITableDefinitionWithConstraints::DropConstraint
XTEST(hr = pCSession->m_pITableDefinitionWithConstraints->DropConstraint(&TableID, &ConstraintID));
TESTC(TRACE_METHOD(hr, L"ITableDefinitionWithConstraints::DropConstraint(%s, %s)", wszTableDBID, wszConsDBID));
if(SUCCEEDED(hr))
{
EndDialog(hWnd, TRUE);
}
SAFE_FREE(TableID.uName.pwszName);
SAFE_FREE(ConstraintID.uName.pwszName);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
CLEANUP:
return FALSE;
} // CMDIChild::DropConstraintProc
////////////////////////////////////////////////////////////////
// CMDIChild::ISCO_DeleteProc
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::ISCO_DeleteProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
const static WIDENAMEMAP rgISODeleteFlags[] =
{
VALUE_WCHAR(DBDELETE_ASYNC),
VALUE_WCHAR(DBDELETE_ATOMIC),
};
switch(message)
{
case WM_INITDIALOG:
{
//Save the "this" pointer
CWaitCursor waitCursor;
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
HWND hWndFlags = ::GetDlgItem(hWnd, IDC_ISCO_FLAGS);
for(ULONG i=0; i<NUMELE(rgISODeleteFlags); i++)
{
INDEX iSel = SendMessageW(hWndFlags, LB_ADDSTRING, 0, (LPARAM)rgISODeleteFlags[i].pwszName);
SendMessageW(hWndFlags, LB_SETITEMDATA, iSel, rgISODeleteFlags[i].lItem);
}
//Placement of Dialog, want it just below the "Init" button...
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_ADD:
{
HWND hWndEditURL = ::GetDlgItem(hWnd, IDE_URL);
HWND hWndURLs = ::GetDlgItem(hWnd, IDC_URLs);
CHAR szURL[MAX_NAME_LEN+1] = "";
// get the text from the edit field
SendMessageA(hWndEditURL, WM_GETTEXT, MAX_NAME_LEN, (LPARAM)szURL);
if (szURL[0])
{
// and add it to the URL list box
SendMessageA(hWndURLs, LB_ADDSTRING, 0, (LPARAM)szURL);
}
else
MessageBox(GetFocus(), "There is no URL to ADD!", "WARNING", MB_OK);
return 0;
}
case IDB_DELETE:
{
HWND hWndURLs = ::GetDlgItem(hWnd, IDC_URLs);
INDEX iSel = (INDEX)SendMessage(hWndURLs, LB_GETCURSEL, 0, 0);
if (LB_ERR != iSel)
SendMessage(hWndURLs, LB_DELETESTRING, iSel, 0);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild *pThis = (CMDIChild*)GetThis(hWnd);
HWND hWndURLs = ::GetDlgItem(hWnd, IDC_URLs);
HWND hWndFlags = ::GetDlgItem(hWnd, IDC_ISCO_FLAGS);
DWORD dwDeleteFlags = 0;
WCHAR **rgpwszURLs = NULL;
WCHAR wszBuffer[MAX_NAME_LEN+1]= {0};
DBSTATUS *rgdbStatus = NULL;
HRESULT hr;
//Obtain IScopedOperations
IScopedOperations* pIScopedOperations = SOURCE_GETINTERFACE(pThis->m_pCSource, IScopedOperations);
ASSERT(pIScopedOperations);
INDEX iSel;
INDEX nCount = (INDEX)SendMessage(hWndFlags, LB_GETCOUNT, 0, 0);
for( iSel = 0; iSel < nCount; iSel++)
{
//Is this a selected Item?
if(SendMessage(hWndFlags, LB_GETSEL, iSel, 0) > 0)
{
//We setup the listbox with the item data as the value for each selection
dwDeleteFlags |= SendMessage(hWndFlags, LB_GETITEMDATA, iSel, 0);
}
}
// get URL array
nCount = (ULONG)SendMessage(hWndURLs, LB_GETCOUNT, 0, 0);
if (nCount > 0)
{
SAFE_ALLOC(rgpwszURLs, WCHAR*, nCount);
SAFE_ALLOC(rgdbStatus, DBSTATUS, nCount);
}
for(iSel=0; iSel<nCount; iSel++)
{
wSendMessage(hWndURLs, LB_GETTEXT, iSel, wszBuffer);
rgpwszURLs[iSel] = wcsDuplicate(wszBuffer);
}
XTEST(hr = pIScopedOperations->Delete(nCount, (const WCHAR**)rgpwszURLs, dwDeleteFlags, rgdbStatus));
TESTC(TRACE_METHOD(hr, L"IScopedOperations::Delete(%Iu, 0x%p, 0x%08x, 0x%p)", nCount, rgpwszURLs, dwDeleteFlags, rgdbStatus));
CLEANUP:
pThis->UpdateControls();
//Display Status errors...
for(iSel=0; iSel<nCount; iSel++)
{
SAFE_FREE(rgpwszURLs[iSel]);
if(rgdbStatus[iSel] != DBSTATUS_S_OK)
wMessageBox(GetFocus(), MB_OK, wsz_ERROR, L"Status = %s \nrgpwszURL[%Iu] = %s", GetStatusName(rgdbStatus[iSel]), iSel, rgpwszURLs[iSel]);
}
SAFE_FREE(rgpwszURLs);
SAFE_FREE(rgdbStatus);
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
}
break;
}//WM_COMMAND
}//switch message
return FALSE;
} // CMDIChild::ISCO_DeleteProc
////////////////////////////////////////////////////////////////
// CMDIChild::ISCO_Proc
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::ISCO_Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
const static WIDENAMEMAP rgISOCopyFlags[] =
{
VALUE_WCHAR(DBCOPY_REPLACE_EXISTING),
VALUE_WCHAR(DBCOPY_ASYNC),
VALUE_WCHAR(DBCOPY_ALLOW_EMULATION),
VALUE_WCHAR(DBCOPY_NON_RECURSIVE),
VALUE_WCHAR(DBCOPY_ATOMIC),
};
const static WIDENAMEMAP rgISOMoveFlags[] =
{
VALUE_WCHAR(DBMOVE_REPLACE_EXISTING),
VALUE_WCHAR(DBMOVE_ASYNC),
VALUE_WCHAR(DBMOVE_DONT_UPDATE_LINKS),
VALUE_WCHAR(DBMOVE_ALLOW_EMULATION),
VALUE_WCHAR(DBMOVE_ATOMIC),
};
switch(message)
{
case WM_INITDIALOG:
{
//Save the "this" pointer
CWaitCursor waitCursor;
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
HWND hWndFlags = ::GetDlgItem(hWnd, IDC_ISCO_FLAGS);
HWND hWndURLs = ::GetDlgItem(hWnd, IDL_URLs);
RECT rect;
//Populate the ListBox
if(pThis->m_idSource == IDM_ISCOPEDOPERATIONS_MOVE)
{
::SetWindowText(hWnd, "IScopedOperations::Move");
for(ULONG i=0; i<NUMELE(rgISOMoveFlags); i++)
{
INDEX iSel = SendMessageW(hWndFlags, LB_ADDSTRING, 0, (LPARAM)rgISOMoveFlags[i].pwszName);
SendMessageW(hWndFlags, LB_SETITEMDATA, iSel, rgISOMoveFlags[i].lItem);
}
}
else
{
::SetWindowText(hWnd, "IScopedOperations::Copy");
for(ULONG i=0; i<NUMELE(rgISOCopyFlags); i++)
{
INDEX iSel = SendMessageW(hWndFlags, LB_ADDSTRING, 0, (LPARAM)rgISOCopyFlags[i].pwszName);
SendMessageW(hWndFlags, LB_SETITEMDATA, iSel, rgISOCopyFlags[i].lItem);
}
}
SendMessage(hWndURLs, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE);
LV_InsertColumn(hWndURLs, COLUMN_ISCO_SRCURL, L"Source URL", IMAGE_NONE);
LV_InsertColumn(hWndURLs, COLUMN_ISCO_DESTURL, L"Destination URL", IMAGE_NONE);
GetWindowRect(hWndURLs, (LPRECT)&rect);
SendMessage(hWndURLs, LVM_SETCOLUMNWIDTH, (WPARAM)COLUMN_ISCO_SRCURL, (LPARAM)(rect.right-rect.left)/2);
SendMessage(hWndURLs, LVM_SETCOLUMNWIDTH, (WPARAM)COLUMN_ISCO_DESTURL, (LPARAM)(rect.right-rect.left)/2);
//Placement of Dialog, want it just below the "Init" button...
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_ADD:
{
HWND hWndSrcURL = ::GetDlgItem(hWnd, IDE_ISCO_SOURCE);
HWND hWndDestURL = ::GetDlgItem(hWnd, IDE_ISCO_DESTINATION);
HWND hWndURLs = ::GetDlgItem(hWnd, IDL_URLs);
WCHAR wszSrcURL[MAX_NAME_LEN+1] = L"";
WCHAR wszDestURL[MAX_NAME_LEN+1] = L"";
ULONG cItems = ListView_GetItemCount(hWndURLs);
// get the text from the edit field
wSendMessage(hWndSrcURL, WM_GETTEXT, MAX_NAME_LEN, wszSrcURL);
wSendMessage(hWndDestURL, WM_GETTEXT, MAX_NAME_LEN, wszDestURL);
if(wszSrcURL[0] || wszDestURL[0])
{
// and add it to the URL list box
// make the insertion
LV_InsertItem(hWndURLs, cItems, COLUMN_ISCO_SRCURL, wszSrcURL);
LV_InsertItem(hWndURLs, cItems, COLUMN_ISCO_DESTURL, wszDestURL);
}
else
{
wMessageBox(GetFocus(), MB_OK, wsz_ERROR, L"There is no source or destination URL to ADD!");
}
return 0;
}
case IDB_DELETE:
{
HWND hWndURLs = ::GetDlgItem(hWnd, IDL_URLs);
INT cItems;
INT iSel;
// get the selected item
iSel = ListView_GetNextItem(hWndURLs, -1, LVNI_SELECTED);
cItems = ListView_GetItemCount(hWndURLs);
if (iSel > -1)
ListView_DeleteItem(hWndURLs, iSel);
if (cItems > 1)
LV_SetItemState(hWndURLs, iSel == cItems-1 ? iSel-1: iSel, COLUMN_ISCO_SRCURL, LVIS_SELECTED, LVIS_SELECTED);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild *pThis = (CMDIChild*)GetThis(hWnd);
HWND hWndURLs = ::GetDlgItem(hWnd, IDL_URLs);
HWND hWndFlags = ::GetDlgItem(hWnd, IDC_ISCO_FLAGS);
DWORD dwFlags = 0;
WCHAR **rgpwszSourceURLs = NULL;
WCHAR **rgpwszDestURLs = NULL;
WCHAR **rgpwszNewURLs = NULL;
OLECHAR *pStringsBuffer = NULL;
DBSTATUS *rgdbStatus = NULL;
WCHAR wszBuffer[MAX_NAME_LEN+1]= {0};
INDEX cRows = 0;
HRESULT hr = S_OK;
//Obtain IScopedOperations
IScopedOperations* pIScopedOperations = SOURCE_GETINTERFACE(pThis->m_pCSource, IScopedOperations);
ASSERT(pIScopedOperations);
INDEX iSel;
INDEX nCount = (INDEX)SendMessage(hWndFlags, LB_GETCOUNT, 0, 0);
for(iSel = 0; iSel < nCount; iSel++)
{
//Is this a selected Item?
if(SendMessage(hWndFlags, LB_GETSEL, iSel, 0) > 0)
{
//We setup the listbox with the item data as the value for each selection
dwFlags |= SendMessage(hWndFlags, LB_GETITEMDATA, iSel, 0);
}
}
// get URL array
cRows = ListView_GetItemCount(hWndURLs);
SAFE_ALLOC(rgpwszSourceURLs, WCHAR*, cRows);
SAFE_ALLOC(rgpwszDestURLs, WCHAR*, cRows);
SAFE_ALLOC(rgpwszNewURLs, WCHAR*, cRows);
SAFE_ALLOC(rgdbStatus, DBSTATUS, cRows);
// get the arrays of source and destination URLs
for (iSel=0; iSel<cRows; iSel++)
{
// get source URL
LV_GetItemText(hWndURLs, iSel, COLUMN_ISCO_SRCURL, wszBuffer, MAX_NAME_LEN);
rgpwszSourceURLs[iSel] = wcsDuplicate(wszBuffer);
// get destination URL
LV_GetItemText(hWndURLs, iSel, COLUMN_ISCO_DESTURL, wszBuffer, MAX_NAME_LEN);
rgpwszDestURLs[iSel] = wcsDuplicate(wszBuffer);
}
switch(pThis->m_idSource)
{
case IDM_ISCOPEDOPERATIONS_COPY:
XTEST(hr = pIScopedOperations->Copy(cRows, (const WCHAR**)rgpwszSourceURLs, (const WCHAR**)rgpwszDestURLs, dwFlags, NULL, rgdbStatus, rgpwszNewURLs, &pStringsBuffer));
TESTC(TRACE_METHOD(hr, L"IScopedOperations::Copy(%Iu, 0x%p, 0x%p, 0x%08x, NULL, 0x%p, 0x%p, &0x%p)", cRows, rgpwszSourceURLs, rgpwszDestURLs, dwFlags, rgdbStatus, rgpwszNewURLs, pStringsBuffer));
break;
case IDM_ISCOPEDOPERATIONS_MOVE:
XTEST(hr = pIScopedOperations->Move(cRows, (const WCHAR**)rgpwszSourceURLs, (const WCHAR**)rgpwszDestURLs, dwFlags, NULL, rgdbStatus, rgpwszNewURLs, &pStringsBuffer));
TESTC(TRACE_METHOD(hr, L"IScopedOperations::Move(%Iu, 0x%p, 0x%p, 0x%08x, NULL, 0x%p, 0x%p, &0x%p)", cRows, rgpwszSourceURLs, rgpwszDestURLs, dwFlags, rgdbStatus, rgpwszNewURLs, pStringsBuffer));
break;
};
CLEANUP:
pThis->UpdateControls();
for(iSel = 0; iSel < cRows; iSel++)
{
SAFE_FREE(rgpwszSourceURLs[iSel]);
SAFE_FREE(rgpwszDestURLs[iSel]);
}
SAFE_FREE(rgpwszSourceURLs);
SAFE_FREE(rgpwszDestURLs);
SAFE_FREE(rgdbStatus);
SAFE_FREE(pStringsBuffer);
if (S_OK == hr)
EndDialog(hWnd, TRUE);
return 0;
}
}
break;
}//WM_COMMAND
}//switch message
return FALSE;
} // CMDIChild::ISCO_Proc
////////////////////////////////////////////////////////////////
// CMDIChild::ExecuteProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::ExecuteProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static CComboBoxGuid s_CComboInterface;
static BOOL fSetCommandText = TRUE; //Default to TRUE
static BOOL fSetCommandStream = FALSE; //Default to FALSE
static BOOL fUseParams = FALSE; //Default to FALSE
static BOOL fAggregation = FALSE; //Default
static BOOL fOutput = TRUE; //Default
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CDataSource* pCDataSource = SOURCE_GETPARENT(pThis->m_pCSource, CDataSource);
//Fill In CommandText as Default
HWND hWndCmdText = ::GetDlgItem(hWnd, IDE_COMMANDTEXT);
WCHAR* pwszQuery = pThis->m_pCQueryBox->GetSelectedText();
wSendMessage(hWndCmdText, WM_SETTEXT, 0, pwszQuery);
//Use Parameters
::CheckDlgButton(hWnd, IDB_USEPARAMS, BST2STATE(fUseParams));
//SetCommandText
::CheckDlgButton(hWnd, IDB_SETCOMMANDTEXT, BST2STATE(fSetCommandText));
//SetCommandStream
::CheckDlgButton(hWnd, IDB_SETCOMMANDSTREAM,BST2STATE(fSetCommandStream));
//None
::CheckDlgButton(hWnd, IDB_SETCOMMANDNONE, BST2STATE(!(fSetCommandText || fSetCommandStream)));
//Aggregation
::CheckDlgButton(hWnd, IDB_AGGREGATION, BST2STATE(fAggregation));
//Output (ppIUnknown)
::CheckDlgButton(hWnd, IDB_OUTPUT, BST2STATE(fOutput));
//Interface List...
s_CComboInterface.CreateIndirect(hWnd, IDC_INTERFACE);
s_CComboInterface.Populate(g_cInterfaceMaps, g_rgInterfaceMaps);
if(s_CComboInterface.RestoreSelection() == CB_ERR)
s_CComboInterface.SetGuid(IID_IRowset);
//Defaults (refiid) other than those last used...
if(pCDataSource && BIT_SET(pCDataSource->m_lDataSourceType, DBPROPVAL_DST_MDP))
s_CComboInterface.SetGuid(IID_IMDDataset);
else if(s_CComboInterface.GetGuid() == IID_IMDDataset)
s_CComboInterface.SetGuid(IID_IRowset);
CenterDialog(hWnd);
SAFE_FREE(pwszQuery);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_SETPARAMS:
{
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
//Display the Parameter Dialog
CExecuteParamDlg paramDlg(pThis);
if(IDOK == paramDlg.DoModal(hWnd))
{
//Since the user setup the params correctly they probably want to
//now use these parameters with execute. Check the "use params" box...
::CheckDlgButton(hWnd, IDB_USEPARAMS, BST2STATE(TRUE));
}
return 0;
}
case IDB_SETPROPERTIES:
{
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CMainWindow* pCMainWindow = pThis->m_pCMainWindow;
CCommand* pCCommand = SOURCE_GETOBJECT(pThis->m_pCSource, CCommand);
CDataSource* pCDataSource = SOURCE_GETPARENT(pCCommand, CDataSource);
CRowset* pCRowset = (CRowset*)pThis->GetObject(eCRowset);
//We should release the Open Objects at this point (avoid DB_E_OPENOBJECT)
if(pCCommand && pThis->GetOptions()->m_dwCommandOpts & COMMAND_RELEASE_OPENOBJECTS)
{
pCCommand->ReleaseChildren();
pThis->UpdateControls();
}
//ICommandProperties::SetProperties
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_ROWSETALL, IID_ICommandProperties, pCCommand->m_pICommandProperties, pCDataSource ? pCDataSource->m_pIDBProperties : NULL);
return 0;
}
case IDB_AGGREGATION:
{
//Aggregation Combo Selection has changed...
//If we are now using Aggregation, automatically change the requested
//riid to IID_IUnknown, since its an error otherwise...
if(::IsDlgButtonChecked(hWnd, IDB_AGGREGATION))
s_CComboInterface.SetGuid(IID_IUnknown);
return 0;
}
case IDB_SETCOMMANDSTREAM:
{
//By default: If the user chooses to use ICommandStream::SetCommandStream
//they probably want a stream back as well, set this for them. They can always
//override this, byt changing it in the combo afterwards...
if(::IsDlgButtonChecked(hWnd, IDB_SETCOMMANDSTREAM))
s_CComboInterface.SetGuid(IID_ISequentialStream);
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CCommand* pCCommand = SOURCE_GETOBJECT(pThis->m_pCSource, CCommand);
HWND hWndCmdText = ::GetDlgItem(hWnd, IDE_COMMANDTEXT);
HRESULT hr = S_OK;
IUnknown* pIUnknown = NULL;
WCHAR* pwszCommandText = NULL;
//Obtain the Aggregation argument
CAggregate* pCAggregate = NULL;
fAggregation = ::IsDlgButtonChecked(hWnd, IDB_AGGREGATION);
if(fAggregation)
pCAggregate = new CAggregate();
//Obtain the Output (ppIUnknown) argument
fOutput = ::IsDlgButtonChecked(hWnd, IDB_OUTPUT);
//Interface
IID iid = s_CComboInterface.GetGuid();
//Use Parameters
fUseParams = ::IsDlgButtonChecked(hWnd, IDB_USEPARAMS);
//SetCommandText
fSetCommandText = ::IsDlgButtonChecked(hWnd, IDB_SETCOMMANDTEXT);
fSetCommandStream = ::IsDlgButtonChecked(hWnd, IDB_SETCOMMANDSTREAM);
if(fSetCommandText || fSetCommandStream)
pwszCommandText = wGetWindowText(hWndCmdText);
//Execute the Command
TESTC(hr = pCCommand->Execute(pCAggregate, pwszCommandText, iid, fUseParams, NULL, fOutput ? &pIUnknown : NULL, fSetCommandStream));
//Process the Rowset
TESTC(hr = pThis->HandleRowset(pCCommand, pIUnknown, iid, CREATE_NEWWINDOW_IFEXISTS, IID_ICommand, pwszCommandText));
CLEANUP:
if(SUCCEEDED(hr))
{
//Now just need to place this name in the EditBox
//Inserted after the current "caret"
if(fSetCommandText)
pThis->m_pCQueryBox->ReplaceAll(pwszCommandText, FALSE/*bReplaceAll*/, TRUE/*fHighlight*/);
EndDialog(hWnd, TRUE);
}
SAFE_RELEASE(pCAggregate);
SAFE_RELEASE(pIUnknown);
SAFE_FREE(pwszCommandText);
pThis->UpdateControls();
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::CommandPersistProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::CommandPersistProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
DBCOMMANDPERSISTFLAG dwSavedFlags = DBCOMMANDPERSISTFLAG_DEFAULT;
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CCommand* pCCommand = SOURCE_GETOBJECT(pThis->m_pCSource, CCommand);
HWND hWndCommandID = ::GetDlgItem(hWnd, IDE_COMMANDID);
HWND hWndFlags = ::GetDlgItem(hWnd, IDL_FLAGS);
DBID* pCommandID = NULL;
HRESULT hr = S_OK;
//Fill in the correct window title
if(pThis->m_idSource == IDM_COMMANDPERSIST_DELETECOMMAND)
{
//Falgs not a paraemter for DeleteCommand
::EnableWindow(hWndFlags, FALSE);
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"ICommandPersist::DeleteCommand");
}
else if(pThis->m_idSource == IDM_COMMANDPERSIST_LOADCOMMAND)
{
SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"ICommandPersist::LoadCommand");
}
else
{
//Default title is SaveCommand
ASSERT(pThis->m_idSource == IDM_COMMANDPERSIST_SAVECOMMAND);
}
//CommandID
//Default to the current command
ASSERT(pCCommand);
hr = pCCommand->GetCurrentCommand(&pCommandID);
if(SUCCEEDED(hr) && pCommandID)
{
//Fill In CommandID as Default
if(pCommandID->eKind==DBKIND_NAME && pCommandID->uName.pwszName)
wSendMessage(hWndCommandID, WM_SETTEXT, 0, pCommandID->uName.pwszName);
}
//dwFlags
const static WIDENAMEMAP rgFlags[] =
{
VALUE_WCHAR(DBCOMMANDPERSISTFLAG_NOSAVE),
VALUE_WCHAR(DBCOMMANDPERSISTFLAG_DEFAULT),
VALUE_WCHAR(DBCOMMANDPERSISTFLAG_PERSISTVIEW),
VALUE_WCHAR(DBCOMMANDPERSISTFLAG_PERSISTPROCEDURE),
};
//Populate the Flags ListBox
SendMessage(hWndFlags, LB_RESETCONTENT, 0, 0);
for(ULONG i=0; i<NUMELE(rgFlags); i++)
{
INDEX iSel = (INDEX)wSendMessage(hWndFlags, LB_ADDSTRING, 0, rgFlags[i].pwszName);
SendMessage(hWndFlags, LB_SETITEMDATA, iSel, (LPARAM)rgFlags[i].lItem);
//Reselect all previously selected items...
SendMessage(hWndFlags, LB_SETSEL, (dwSavedFlags & rgFlags[i].lItem) == (DBCOMMANDPERSISTFLAG)rgFlags[i].lItem, i);
}
CenterDialog(hWnd);
DBIDFree(pCommandID);
SAFE_FREE(pCommandID);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CCommand* pCCommand = SOURCE_GETOBJECT(pThis->m_pCSource, CCommand);
HWND hWndCommandID = ::GetDlgItem(hWnd, IDE_COMMANDID);
HWND hWndFlags = ::GetDlgItem(hWnd, IDL_FLAGS);
HRESULT hr = S_OK;
//Obtain the CommandID
DBID CommandID;
CommandID.eKind = DBKIND_NAME;
CommandID.uName.pwszName = wGetWindowText(hWndCommandID);
//Obtain all Selected Flags...
INDEX iSelCount = (INDEX)SendMessage(hWndFlags, LB_GETSELCOUNT, 0, 0);
ASSERT(iSelCount < 20);
LONG rgSelItems[20];
SendMessage(hWndFlags, LB_GETSELITEMS, (WPARAM)20, (LPARAM)rgSelItems);
for(LONG i=0; i<iSelCount; i++)
{
DBCOMMANDPERSISTFLAG dwSelFlag = (DBCOMMANDPERSISTFLAG)SendMessage(hWndFlags, LB_GETITEMDATA, rgSelItems[i], 0);
dwSavedFlags |= dwSelFlag;
}
if(pThis->m_idSource == IDM_COMMANDPERSIST_DELETECOMMAND)
{
//ICommandPersist::DeleteCommand
XTEST(hr = pCCommand->m_pICommandPersist->DeleteCommand(&CommandID));
TESTC(TRACE_METHOD(hr, L"ICommandPersist::DeleteCommand({\"%s\"})", CommandID.uName.pwszName));
}
else if(pThis->m_idSource == IDM_COMMANDPERSIST_LOADCOMMAND)
{
//ICommandPersist::LoadCommand
XTEST(hr = pCCommand->m_pICommandPersist->LoadCommand(&CommandID, dwSavedFlags));
TESTC(TRACE_METHOD(hr, L"ICommandPersist::LoadCommand({\"%s\"}, 0x%08x)", CommandID.uName.pwszName, dwSavedFlags));
//The symmantics of LoadCommand replace the "underlying" command.
//so there is no interface to "repopluate" the current command with, and
//all currently held interfaces should still be valid...
}
else
{
//ICommandPersist::SaveCommand
ASSERT(pThis->m_idSource == IDM_COMMANDPERSIST_SAVECOMMAND);
XTEST(hr = pCCommand->m_pICommandPersist->SaveCommand(&CommandID, dwSavedFlags));
TESTC(TRACE_METHOD(hr, L"ICommandPersist::SaveCommand({\"%s\"}, 0x%08x)", CommandID.uName.pwszName, dwSavedFlags));
}
CLEANUP:
SAFE_FREE(CommandID.uName.pwszName);
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::SetCommandTextProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::SetCommandTextProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL fRelOpenObjects = TRUE; //Default
static BOOL fUnicodeStream = TRUE; //Default
static CComboBoxGuid s_CComboDialect;
static CComboBoxGuid s_CComboRefiid;
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CCommand* pCCommand = SOURCE_GETOBJECT(pThis->m_pCSource, CCommand);
HWND hWndCmdText = ::GetDlgItem(hWnd, IDE_COMMANDTEXT);
//Fill-in Dialect Combo
s_CComboDialect.CreateIndirect(hWnd, IDC_DIALECT);
s_CComboDialect.Populate(g_cDialectMaps, g_rgDialectMaps);
s_CComboDialect.SetGuid(pCCommand->m_guidDialect);
//Fill-in REFIID Combo (ICommandStream)
if(pThis->m_idSource == IDM_SETCOMMANDSTREAM)
{
s_CComboRefiid.CreateIndirect(hWnd, IDC_REFIID);
s_CComboRefiid.Populate(g_cInterfaceMaps, g_rgInterfaceMaps);
s_CComboRefiid.SetGuid(IID_ISequentialStream);
}
//Fill In CommandText as Default
WCHAR* pwszQuery = pThis->m_pCQueryBox->GetSelectedText();
wSendMessage(hWndCmdText, WM_SETTEXT, 0, pwszQuery);
//Default Options
::CheckDlgButton(hWnd, IDB_UNICODE, BST2STATE(fUnicodeStream));
::CheckDlgButton(hWnd, IDB_RELEASE_OPENOBJECTS, BST2STATE(fRelOpenObjects));
CenterDialog(hWnd);
SAFE_FREE(pwszQuery);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CCommand* pCCommand = SOURCE_GETOBJECT(pThis->m_pCSource, CCommand);
CRowset* pCRowset = (CRowset*)pThis->GetObject(eCRowset);
WCHAR* pwszCommandText = NULL;
HWND hWndCmdText = ::GetDlgItem(hWnd, IDE_COMMANDTEXT);
HRESULT hr = S_OK;
//Options
fUnicodeStream = ::IsDlgButtonChecked(hWnd, IDB_UNICODE);
fRelOpenObjects = ::IsDlgButtonChecked(hWnd, IDB_RELEASE_OPENOBJECTS);
if(pCCommand && fRelOpenObjects)
{
pCCommand->ReleaseChildren();
pThis->UpdateControls();
}
//Get Guid Dialect
//NOTE: Save it into a temporary in case this fails...
GUID guidDialect = GUID_NULL;
INDEX iSel = s_CComboDialect.GetCurSel();
if(iSel != CB_ERR)
{
//Get ItemData which is the Guid Pointer
guidDialect = s_CComboDialect.GetGuid();
}
else
{
//Convert Users String to a Guid
WCHAR wszBuffer[MAX_NAME_LEN] = {0};
s_CComboDialect.GetSelText(wszBuffer, MAX_NAME_LEN);
XTESTC(hr = CLSIDFromString(wszBuffer, &guidDialect));
}
//ICommand::SetCommandText
pwszCommandText = wGetWindowText(hWndCmdText);
if(pThis->m_idSource == IDM_SETCOMMANDSTREAM)
{
REFIID riid = s_CComboRefiid.GetGuid();
TESTC(hr = pCCommand->SetCommandStream(pwszCommandText,
riid,
&guidDialect,
fUnicodeStream));
}
else
{
TESTC(hr = pCCommand->SetCommandText(pwszCommandText, &guidDialect));
}
CLEANUP:
if(SUCCEEDED(hr))
{
//Now just need to place this name in the EditBox
//Inserted after the current "caret"
pThis->m_pCQueryBox->ReplaceAll(pwszCommandText, FALSE/*bReplaceAll*/, TRUE/*fHighlight*/);
EndDialog(hWnd, TRUE);
}
SAFE_FREE(pwszCommandText);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetColumnsRowsetProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::GetColumnsRowsetProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static CComboBoxGuid s_CComboInterface;
static CPropSets s_CPropSets;
static BOOL fUseProps = TRUE; //Default
static bool fOptColumns = TRUE; //Default
static BOOL fAggregation = FALSE; //Default
static BOOL fOutput = TRUE; //Default
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
//Use Optional Columns
::CheckDlgButton(hWnd, IDB_USEOPTCOLUMNS, BST2STATE(fOptColumns));
//Use Properties
::CheckDlgButton(hWnd, IDB_USEPROPERTIES, BST2STATE(fUseProps));
//Aggregation
::CheckDlgButton(hWnd, IDB_AGGREGATION, BST2STATE(fAggregation));
//Output (ppIUnknown)
::CheckDlgButton(hWnd, IDB_OUTPUT, BST2STATE(fOutput));
//Interface List...
s_CComboInterface.CreateIndirect(hWnd, IDC_INTERFACE);
s_CComboInterface.Populate(g_cInterfaceMaps, g_rgInterfaceMaps);
if(s_CComboInterface.RestoreSelection() == CB_ERR)
s_CComboInterface.SetGuid(IID_IRowset);
//Only set these "Default" properties, if requested by the user
if(pThis->GetOptions()->m_dwRowsetOpts & ROWSET_SETDEFAULTPROPS)
{
//DBPROP_CANHOLDROWS is required by the OLE DB Spec - Level-0 Conformance
//Since it is also legal to set a ReadOnly property, just blindy set it...
s_CPropSets.SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, DBTYPE_BOOL, (void*)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
}
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDB_SETPROPERTIES:
{
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CMainWindow* pCMainWindow = pThis->m_pCMainWindow;
CDataSource* pCDataSource = SOURCE_GETPARENT(pThis->m_pCSource, CDataSource);
CPropertiesDlg sCPropertiesDlg(pCMainWindow);
sCPropertiesDlg.SetProperties(hWnd, &DBPROPSET_ROWSETALL, IID_IRowsetInfo, NULL, pCDataSource ? pCDataSource->m_pIDBProperties : NULL, &s_CPropSets);
return 0;
}
case IDB_AGGREGATION:
{
//Aggregation Combo Selection has changed...
//If we are now using Aggregation, automatically change the requested
//riid to IID_IUnknown, since its an error otherwise...
if(::IsDlgButtonChecked(hWnd, IDB_AGGREGATION))
s_CComboInterface.SetGuid(IID_IUnknown);
return 0;
}
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CDataAccess* pCDataAccess = SOURCE_GETOBJECT(pThis->m_pCSource, CDataAccess);
HRESULT hr = S_OK;
IUnknown* pIUnknown = NULL;
ULONG cPropSets = 0;
DBPROPSET* rgPropSets = NULL;
//Obtain the Aggregation argument
CAggregate* pCAggregate = NULL;
fAggregation = ::IsDlgButtonChecked(hWnd, IDB_AGGREGATION);
if(fAggregation)
pCAggregate = new CAggregate();
//Obtain the Output (ppIUnknown) argument
fOutput = ::IsDlgButtonChecked(hWnd, IDB_OUTPUT);
//Interface
REFIID riid = s_CComboInterface.GetGuid();
//Use Properties
fUseProps = ::IsDlgButtonChecked(hWnd, IDB_USEPROPERTIES);
if(fUseProps)
{
cPropSets = s_CPropSets.GetCount();
rgPropSets = s_CPropSets.GetPropSets();
}
//Use Optional Columns
fOptColumns = ::IsDlgButtonChecked(hWnd, IDB_USEOPTCOLUMNS) ? true : false;
//IColumnsRowset::GetColumnsRowset
hr = pCDataAccess->GetColumnsRowset(pCAggregate, fOptColumns, riid, cPropSets, rgPropSets, fOutput ? &pIUnknown : NULL);
if(SUCCEEDED(hr))
{
//Process the Rowset
hr = pThis->HandleRowset(pCDataAccess, pIUnknown, riid, CREATE_NEWWINDOW_IFEXISTS, IID_IColumnsRowset);
}
SAFE_RELEASE(pCAggregate);
SAFE_RELEASE(pIUnknown);
//Have to exit, even if failure. The failure can happen at any
//point, ie: during accessor creation. So we end up with a
//valid rowset, but not neccessaryliy something that supports
//IColumnsRowset...
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetChapteredChild
//
/////////////////////////////////////////////////////////////////
HRESULT CMDIChild::GetChapteredChild(INDEX iSelectedCol, const DBBINDING* pBinding, REFIID riid)
{
ASSERT(pBinding);
IUnknown* pIUnknown = NULL;
HRESULT hr = S_OK;
CRowset* pCRowset = (CRowset*)GetObject(eCRowset);
HROW hRow = NULL;
CBase* pCObject = NULL;
INDEX iSelRow = 0;
WCHAR wszChapter[POINTER_DISPLAYSIZE] = {0};
HCHAPTER hChapter = NULL;
if(pCRowset && pCRowset->m_pIRowsetInfo)
{
//IRowsetInfo::GetReferencedRowset
XTEST(hr = pCRowset->m_pIRowsetInfo->GetReferencedRowset(pBinding->iOrdinal, riid, &pIUnknown));
TESTC(TRACE_METHOD(hr, L"IRowsetInfo::GetReferencedRowset(%Id, %s, &0x%p)", pBinding->iOrdinal, GetInterfaceName(riid), pIUnknown));
//Obtain the hChapter from the rowset for the selected row. If a row is not selected this
//would be to open the entire child rowset. If the bookmark column is used it useally
//means to return the current rowset - again. Both cases theres no chapter specified...
iSelRow = m_pCDataGrid->GetSelectedRow(&hRow, FALSE);
if(iSelRow != LVM_ERR && pBinding->iOrdinal!=0)
{
if(hRow)
{
TESTC(hr = pCRowset->GetChapter(hRow, pBinding->iOrdinal, &hChapter));
StringFormat(wszChapter, NUMELE(wszChapter), L"%p", hChapter);
}
else
{
//Get the Item from the 'insert' ListView
m_pCDataGrid->GetItemText(iSelRow, iSelectedCol+1, wszChapter, NUMELE(wszChapter));
hChapter = wcstoul(wszChapter, NULL, 16);
}
}
//Create a new Rowset Window for the result...
//But dont actually display the object, until we set the hChapter
//NOTE: Can pontentially return other object types: (ie: CREATE_DETERMINE_TYPE)
pCObject = m_pCMainWindow->HandleObjectType(pCRowset, pIUnknown, riid, eCRowset, 0, NULL, CREATE_NEWWINDOW | CREATE_NODISPLAY | CREATE_DETERMINE_TYPE);
if(pCObject)
{
//Set the Chapter handle, before displaying rowset...
CRowset* pCRowset = SOURCE_GETOBJECT(pCObject, CRowset);
if(pCRowset)
{
pCRowset->m_hChapter = hChapter;
pCRowset->SetObjectDesc(wszChapter);
}
pCObject->DisplayObject();
}
else
{
TESTC(hr = E_FAIL);
}
}
CLEANUP:
TRACE_RELEASE(pIUnknown, L"Rowset");
return hr;
}
////////////////////////////////////////////////////////////////
// CMDIChild::GetReferencedRowsetProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::GetReferencedRowsetProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static CComboBoxGuid s_CComboInterface;
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CRowset* pCRowset = SOURCE_GETOBJECT(pThis->m_pCSource, CRowset);
INDEX iSel = 0;
HWND hWndColumn = ::GetDlgItem(hWnd, IDC_COLUMN);
//Column List...
INDEX iSavedCol = CB_ERR;
for(ULONG i=0; i<pCRowset->m_Bindings.GetCount(); i++)
{
//Column Ordinal - Column Name
DBORDINAL iOrdinal = pCRowset->m_Bindings[i].iOrdinal;
const DBCOLUMNINFO* pColInfo = pCRowset->m_ColumnInfo.GetOrdinal(iOrdinal);
//SetDefault to first chaptered column...
if(pColInfo->dwFlags & DBCOLUMNFLAGS_ISCHAPTER)
{
iSel = (INDEX)wSendMessageFmt(hWndColumn, CB_ADDSTRING, 0, L"%2Id - %s <ISCHAPTER>", iOrdinal, GetColName(pColInfo));
if(iSavedCol == CB_ERR)
iSavedCol = iSel;
}
else
{
iSel = (INDEX)wSendMessageFmt(hWndColumn, CB_ADDSTRING, 0, L"%2Id - %s", iOrdinal, GetColName(pColInfo));
}
//Save the iBinding in ther listview
SendMessage(hWndColumn, CB_SETITEMDATA, iSel, (LPARAM)i);
}
//Set Default...
SendMessage(hWndColumn, CB_SETCURSEL, iSavedCol < (INDEX)pCRowset->m_Bindings.GetCount() && iSavedCol!=CB_ERR ? iSavedCol : 0, 0);
//Interface List...
s_CComboInterface.CreateIndirect(hWnd, IDC_INTERFACE);
s_CComboInterface.Populate(g_cInterfaceMaps, g_rgInterfaceMaps);
if(s_CComboInterface.RestoreSelection() == CB_ERR)
s_CComboInterface.SetGuid(IID_IRowset);
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CRowset* pCRowset = SOURCE_GETOBJECT(pThis->m_pCSource, CRowset);
HWND hWndColumn = ::GetDlgItem(hWnd, IDC_COLUMN);
HRESULT hr = S_OK;
//Column
INDEX iSavedCol = (INDEX)SendMessage(hWndColumn, CB_GETCURSEL, 0, 0);
DBCOUNTITEM iBinding = SendMessage(hWndColumn, CB_GETITEMDATA, iSavedCol!=CB_ERR ? iSavedCol : 0, 0);
const DBBINDING* pBinding = &pCRowset->m_Bindings[iBinding];
//Interface
REFIID riid = s_CComboInterface.GetGuid();
//Obtain the Child rowset..
hr = pThis->GetChapteredChild(iSavedCol, pBinding, riid);
if(SUCCEEDED(hr))
EndDialog(hWnd, TRUE);
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::FindNextRowProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::FindNextRowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static INDEX iSavedCol = 1; //Default column
static INDEX iSavedOp = 2; //Default DBCOMPAREOPS_EQ
static LONG cSavedRows = 1; //Default to cRows=1
static DWORD dwCompareOps = 0; //Default to not CASESENSITIVE
switch(message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
//Save the "this" pointer
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CRowset* pCRowset = SOURCE_GETOBJECT(pThis->m_pCSource, CRowset);
INDEX iSel = 0;
HWND hWndColumn = ::GetDlgItem(hWnd, IDC_COLUMN);
HWND hWndCompareOp = ::GetDlgItem(hWnd, IDC_COMPAREOP);
HWND hWndcRows = ::GetDlgItem(hWnd, IDE_COUNT);
HWND hWndValue = ::GetDlgItem(hWnd, IDE_VALUE);
ULONG i;
//Column List...
for(i=0; i<pCRowset->m_Bindings.GetCount(); i++)
{
//Column Ordinal - Column Name
DBORDINAL iOrdinal = pCRowset->m_Bindings[i].iOrdinal;
const DBCOLUMNINFO* pColInfo = pCRowset->m_ColumnInfo.GetOrdinal(iOrdinal);
iSel = (INDEX)wSendMessageFmt(hWndColumn, CB_ADDSTRING, 0, L"%2Id - %s", iOrdinal, GetColName(pColInfo));
SendMessage(hWndColumn, CB_SETITEMDATA, iSel, (LPARAM)i);
}
//Set Default...
SendMessage(hWndColumn, CB_SETCURSEL, iSavedCol < (INDEX)pCRowset->m_Bindings.GetCount() && iSavedCol!=CB_ERR ? iSavedCol : 0, 0);
const static WIDENAMEMAP rgCompareOps[] =
{
VALUE_WCHAR(DBCOMPAREOPS_LT),
VALUE_WCHAR(DBCOMPAREOPS_LE),
VALUE_WCHAR(DBCOMPAREOPS_EQ),
VALUE_WCHAR(DBCOMPAREOPS_GE),
VALUE_WCHAR(DBCOMPAREOPS_GT),
VALUE_WCHAR(DBCOMPAREOPS_BEGINSWITH),
VALUE_WCHAR(DBCOMPAREOPS_CONTAINS),
VALUE_WCHAR(DBCOMPAREOPS_NE),
VALUE_WCHAR(DBCOMPAREOPS_IGNORE),
VALUE_WCHAR(DBCOMPAREOPS_NOTBEGINSWITH),
VALUE_WCHAR(DBCOMPAREOPS_NOTCONTAINS),
};
//CompareOp List...
for(i=0; i<NUMELE(rgCompareOps); i++)
{
iSel = (INDEX)wSendMessage(hWndCompareOp, CB_ADDSTRING, 0, rgCompareOps[i].pwszName);
SendMessage(hWndCompareOp, CB_SETITEMDATA, iSel, (LPARAM)rgCompareOps[i].lItem);
}
//Set Default...
iSavedOp = (INDEX)SendMessage(hWndCompareOp, CB_SETCURSEL, iSavedOp != CB_ERR ? iSavedOp : 0, 0);
//dwModifiers
//DBCOMPAREOPS_CASESENSITIVE
//DBCOMPAREOPS_CASEINSENSITIVE
::CheckDlgButton(hWnd, IDB_CASESENSITIVE, BST2STATE(dwCompareOps & DBCOMPAREOPS_CASESENSITIVE));
::CheckDlgButton(hWnd, IDB_CASEINSENSITIVE, BST2STATE(dwCompareOps & DBCOMPAREOPS_CASEINSENSITIVE));
//cRows
wSendMessageFmt(hWndcRows, WM_SETTEXT, 0, L"%lu", cSavedRows);
//Value
SendMessage(hWndValue, WM_SETTEXT, 0, (LPARAM)"");
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
{
CWaitCursor waitCursor;
//Get the "this" pointer
CMDIChild* pThis = (CMDIChild*)GetThis(hWnd);
CRowset* pCRowset = SOURCE_GETOBJECT(pThis->m_pCSource, CRowset);
HRESULT hr = S_OK;
HWND hWndColumn = ::GetDlgItem(hWnd, IDC_COLUMN);
HWND hWndCompareOp = ::GetDlgItem(hWnd, IDC_COMPAREOP);
HWND hWndcRows = ::GetDlgItem(hWnd, IDE_COUNT);
HWND hWndValue = ::GetDlgItem(hWnd, IDE_VALUE);
HACCESSOR hAccessor = NULL;
//Bookmark
DBBKMARK cbBookmark = 0;
BYTE* pBookmark = NULL;
HROW hRow = NULL;
void* pData = pCRowset->m_pData;
DBROWOFFSET lOffset = 0;
DBCOUNTITEM cRowsObtained = 0;
HROW* rghRows = NULL;
HCHAPTER hChapter = pCRowset->m_hChapter;
//Column
iSavedCol = (INDEX)SendMessage(hWndColumn, CB_GETCURSEL, 0, 0);
DBCOUNTITEM iBinding = SendMessage(hWndColumn, CB_GETITEMDATA, iSavedCol!=CB_ERR ? iSavedCol : 0, 0);
const DBBINDING* pBinding = &pCRowset->m_Bindings[iBinding];
const DBCOLUMNINFO* pColInfo = pCRowset->m_ColumnInfo.GetOrdinal(pBinding->iOrdinal);
//CompareOp
iSavedOp = (INDEX)SendMessage(hWndCompareOp, CB_GETCURSEL, 0, 0);
dwCompareOps = (DBCOMPAREOP)SendMessage(hWndCompareOp, CB_GETITEMDATA, iSavedOp != CB_ERR ? iSavedOp : 0, 0);
//dwModifiers
if(::IsDlgButtonChecked(hWnd, IDB_CASESENSITIVE))
dwCompareOps |= DBCOMPAREOPS_CASESENSITIVE;
if(::IsDlgButtonChecked(hWnd, IDB_CASEINSENSITIVE))
dwCompareOps |= DBCOMPAREOPS_CASEINSENSITIVE;
//cRows
GetEditBoxValue(hWndcRows, &cSavedRows);
//Value
WCHAR* pwszValue = wGetWindowText(hWndValue);
//Create An Accessor binding only this column
TESTC(hr = pCRowset->CreateAccessor(DBACCESSOR_ROWDATA, 1, pBinding, 0, &hAccessor));
//Setup the pData buffer containg the users value
TESTC(hr = pCRowset->SetColumnData(pBinding, pData, DBSTATUS_S_OK, pwszValue ? wcslen(pwszValue) : 0, pwszValue ? pwszValue : L"", CONV_NONE, pColInfo->wType));
//Obtain the bookmark(s) for the selected row(s)...
if(pThis->m_pCDataGrid->GetSelectedRow(&hRow, FALSE)!=LVM_ERR)
hr = pCRowset->GetBookmark(hRow, &cbBookmark, (BYTE**)&pBookmark);
//Release previously fetched rows, (if user requested)
TESTC(hr = pThis->m_pCDataGrid->ReleaseHeldRows());
//IRowsetFind::FindNextRow
XTEST(hr = pCRowset->m_pIRowsetFind->FindNextRow(hChapter, hAccessor, pData, dwCompareOps, cbBookmark, pBookmark, lOffset, cSavedRows, &cRowsObtained, &rghRows));
TESTC(TRACE_METHOD(hr, L"IRowsetFind::FindNextRow(0x%p, 0x%p, \"%s\", 0x%08x, %Iu, 0x%p, %Id, %ld, &%Iu, &0x%p)", hChapter, hAccessor, pwszValue, dwCompareOps, cbBookmark, pBookmark, lOffset, cSavedRows, cRowsObtained, rghRows));
CLEANUP:
//TODO - need to free in the case of errors as well. But have to be careful
//since the pData may not have been setup yet, or other errors where its undefined...
if(SUCCEEDED(hr))
FreeBindingData(1, pBinding, pData, TRUE/*SetData*/);
pCRowset->ReleaseAccessor(&hAccessor);
SAFE_FREE(pBookmark);
SAFE_FREE(rghRows);
SAFE_FREE(pwszValue);
if(SUCCEEDED(hr))
{
EndDialog(hWnd, TRUE);
return 0;
}
return 0;
}
case IDCANCEL:
{
EndDialog(hWnd, FALSE);
return 0;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMDIChild::ProviderInfoProc
//
/////////////////////////////////////////////////////////////////
INT_PTR WINAPI CMDIChild::ProviderInfoProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
CWaitCursor waitCursor;
CMDIChild* pThis = (CMDIChild*)SetThis(hWnd, (void*)lParam);
CComBSTR cstrString;
CComBSTR cstrString2;
DWORD dwValue = 0;
//Determine which object were on...
IDBProperties* pIDBProperties = SOURCE_GETINTERFACE(pThis->m_pCSource, IDBProperties);
if(pIDBProperties)
{
//DBPROP_PROVIDERFILENAME
GetProperty(IID_IDBProperties, pIDBProperties, DBPROP_PROVIDERFILENAME, DBPROPSET_DATASOURCEINFO, DBTYPE_BSTR, &cstrString);
wSendMessage(::GetDlgItem(hWnd, IDT_PROVIDERFILENAME), WM_SETTEXT, 0, cstrString ? cstrString : L"");
cstrString.Empty();
//DBPROP_PROVIDERFRIENDLYNAME
GetProperty(IID_IDBProperties, pIDBProperties, DBPROP_PROVIDERFRIENDLYNAME, DBPROPSET_DATASOURCEINFO, DBTYPE_BSTR, &cstrString);
wSendMessage(::GetDlgItem(hWnd, IDT_PROVIDERDESC), WM_SETTEXT, 0, cstrString ? cstrString : L"");
cstrString.Empty();
//DBPROP_PROVIDERVER
GetProperty(IID_IDBProperties, pIDBProperties, DBPROP_PROVIDERVER, DBPROPSET_DATASOURCEINFO, DBTYPE_BSTR, &cstrString);
//DBPROP_PROVIDEROLEDBVER
GetProperty(IID_IDBProperties, pIDBProperties, DBPROP_PROVIDEROLEDBVER, DBPROPSET_DATASOURCEINFO, DBTYPE_BSTR, &cstrString2);
wSendMessageFmt(::GetDlgItem(hWnd, IDT_PROVIDERVERSION), WM_SETTEXT, 0, L"Prov - %s OLEDB - %s", cstrString ? cstrString : L"Unknown", cstrString2 ? cstrString2 : L"Unknown");
cstrString.Empty();
cstrString2.Empty();
//DBMS / DBMSVER
GetProperty(IID_IDBProperties, pIDBProperties, DBPROP_DBMSNAME, DBPROPSET_DATASOURCEINFO, DBTYPE_BSTR, &cstrString);
GetProperty(IID_IDBProperties, pIDBProperties, DBPROP_DBMSVER, DBPROPSET_DATASOURCEINFO, DBTYPE_BSTR, &cstrString2);
wSendMessageFmt(::GetDlgItem(hWnd, IDT_DBMS), WM_SETTEXT, 0, L"%s %s", cstrString ? cstrString : L"", cstrString2 ? cstrString2 : L"");
cstrString.Empty();
cstrString2.Empty();
//DATASOURCE
GetProperty(IID_IDBProperties, pIDBProperties, DBPROP_DATASOURCENAME, DBPROPSET_DATASOURCEINFO, DBTYPE_BSTR, &cstrString);
wSendMessage(::GetDlgItem(hWnd, IDT_DATASOURCE), WM_SETTEXT, 0, cstrString ? cstrString : L"");
cstrString.Empty();
//DBPROP_DATASOURCEREADONLY
VARIANT_BOOL bReadOnly = VARIANT_FALSE;
GetProperty(IID_IDBProperties, pIDBProperties, DBPROP_DATASOURCEREADONLY, DBPROPSET_DATASOURCEINFO, DBTYPE_BOOL, &bReadOnly);
SendMessage(::GetDlgItem(hWnd, IDT_READONLY), WM_SETTEXT, 0, bReadOnly ? (LPARAM)"Read-Only" : (LPARAM)"Updatable");
//DBPROP_CURRENTCATALOG
GetProperty(IID_IDBProperties, pIDBProperties, DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, DBTYPE_BSTR, &cstrString);
wSendMessage(::GetDlgItem(hWnd, IDT_CATALOG), WM_SETTEXT, 0, cstrString);
cstrString.Empty();
//DBPROP_DSOTHREADMODEL
GetProperty(IID_IDBProperties, pIDBProperties, DBPROP_DSOTHREADMODEL, DBPROPSET_DATASOURCEINFO, DBTYPE_I4, &dwValue);
SendMessage(::GetDlgItem(hWnd, IDT_THREADMODEL), WM_SETTEXT, 0, (LPARAM)(dwValue & DBPROPVAL_RT_FREETHREAD ? "FreeThreaded" : dwValue & DBPROPVAL_RT_APTMTTHREAD ? "ApartmentModel" : dwValue & DBPROPVAL_RT_SINGLETHREAD ? "SingleThreaded" : "Unknown"));
}
CenterDialog(hWnd);
return TRUE;
}
case WM_COMMAND:
{
//Filter out any Control Notification codes
if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
{
return UNHANDLED_MSG;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
case IDCANCEL:
{
CWaitCursor waitCursor;
EndDialog(hWnd, TRUE);
return TRUE;
}
}
break;
}//WM_COMMAND
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CQueryBox::CQueryBox
//
/////////////////////////////////////////////////////////////////
CQueryBox::CQueryBox(CMDIChild* pCMDIChild)
{
ASSERT(pCMDIChild);
m_pCMDIChild = pCMDIChild;
}
////////////////////////////////////////////////////////////////
// CQueryBox::~CQueryBox
//
/////////////////////////////////////////////////////////////////
CQueryBox::~CQueryBox()
{
}
////////////////////////////////////////////////////////////////
// CQueryBox::OnRButtonDown
//
/////////////////////////////////////////////////////////////////
BOOL CQueryBox::OnRButtonDown(WPARAM fwKeys, REFPOINTS pts)
{
//NOTE: The right mouse button doesn't automatically activate the MDI window...
m_pCMDIChild->m_pCMainWindow->MDIActivate(m_hWndParent);
//xPos, yPos are Relative to the Client Area...
DisplayContextMenu(
m_hWnd,
IDM_EDITMENU,
pts,
m_pCMDIChild->m_hWnd,
TRUE
);
return TRUE;
}
////////////////////////////////////////////////////////////////
// CQueryBox::OnContextMenu
//
/////////////////////////////////////////////////////////////////
BOOL CQueryBox::OnContextMenu(HWND hWnd, REFPOINTS pts)
{
DisplayContextMenu(
hWnd,
IDM_EDITMENU,
pts,
m_pCMDIChild->m_hWnd
);
return TRUE;
}
////////////////////////////////////////////////////////////////
// CQueryBox::OnKeyDown
//
/////////////////////////////////////////////////////////////////
BOOL CQueryBox::OnKeyDown(WPARAM nVirtKey, LPARAM lKeyData)
{
switch(nVirtKey)
{
case VK_TAB:
{
MSG msg;
m_pCMDIChild->m_pCDataGrid->SetFocus();
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
return TRUE;
}
};
return FALSE;
}
////////////////////////////////////////////////////////////////
// CDataGrid::CDataGrid
//
/////////////////////////////////////////////////////////////////
CDataGrid::CDataGrid(CMDIChild* pCMDIChild)
{
ASSERT(pCMDIChild);
//Data
m_pCMDIChild = pCMDIChild;
m_lMaxRows = 0;
//Cursor
m_fLastFetchForward = FALSE;
m_lCurPos = 0;
}
////////////////////////////////////////////////////////////////
// CDataGrid::~CDataGrid
//
/////////////////////////////////////////////////////////////////
CDataGrid::~CDataGrid()
{
}
////////////////////////////////////////////////////////////////
// CDataGrid::GetOptions
//
/////////////////////////////////////////////////////////////////
COptionsSheet* CDataGrid::GetOptions()
{
return m_pCMDIChild->GetOptions();
}
/////////////////////////////////////////////////////////////////////
// CDataGrid::OnSize
//
/////////////////////////////////////////////////////////////////////
BOOL CDataGrid::OnSize(WPARAM nType, REFPOINTS pts)
{
switch(nType)
{
case SIZE_RESTORED:
case SIZE_MAXIMIZED:
{
if(pts.x && pts.y)
{
//Obtain the total number of available items (subtract for ScrollBar)
m_lMaxRows = GetCountPerPage()-1;
m_lMaxRows = max(m_lMaxRows, 0); //At least 0
}
return FALSE;
}
};
return FALSE;
}
////////////////////////////////////////////////////////////////
// CDataGrid::OnRButtonDown
//
/////////////////////////////////////////////////////////////////
BOOL CDataGrid::OnRButtonDown(WPARAM fwKeys, REFPOINTS pts)
{
//NOTE: The right mouse button doesn't automatically activate the MDI window...
CDataAccess* pCDataAccess = m_pCMDIChild->m_pCDataAccess;
//xPos, yPos are Relative to the Client Area...
if(pCDataAccess)
{
DisplayContextMenu(
m_hWnd,
pCDataAccess->GetObjectMenu(),
pts,
m_pCMDIChild->m_pCMainWindow->m_hWnd,
TRUE
);
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// CDataGrid::OnContextMenu
//
/////////////////////////////////////////////////////////////////
BOOL CDataGrid::OnContextMenu(HWND hWnd, REFPOINTS pts)
{
CDataAccess* pCDataAccess = m_pCMDIChild->m_pCDataAccess;
if(pCDataAccess)
{
DisplayContextMenu(
m_hWnd,
pCDataAccess->GetObjectMenu(),
pts,
m_pCMDIChild->m_pCMainWindow->m_hWnd
);
return TRUE;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////
// CDataGrid::OnColumnClick
//
/////////////////////////////////////////////////////////////////////
BOOL CDataGrid::OnColumnClick(INT idCtrl, NMLISTVIEW* pNMListView)
{
//Can't edit "Row-Handle" Column
if(pNMListView->iSubItem == 0)
return TRUE;
CWaitCursor waitCursor;
//Save the SelectedCol so the new dialog box knows which Column were concerned with...
m_iSelCol = pNMListView->iSubItem-1;
CRowset* pCRowset = (CRowset*)m_pCMDIChild->GetObject(eCRowset);
//See if the selected column is a chapter column...
if(pCRowset)
{
if((DBCOUNTITEM)m_iSelCol < pCRowset->m_Bindings.GetCount())
{
const DBBINDING* pBinding = &pCRowset->m_Bindings[m_iSelCol];
const DBCOLUMNINFO* pColInfo = pCRowset->m_ColumnInfo.GetOrdinal(pBinding->iOrdinal);
if(pColInfo->dwFlags & DBCOLUMNFLAGS_ISCHAPTER)
{
//Obtain the Child rowset..
m_pCMDIChild->GetChapteredChild(m_iSelCol, pBinding);
return TRUE;
}
}
}
//Otherwise we will assume the user wants to "edit" the column...
if(GetItemCount())
{
CRow* pCRow = (CRow*)m_pCMDIChild->GetObject(eCRow);
CDataset* pCDataset = (CDataset*)m_pCMDIChild->GetObject(eCDataset);
CRowset* pCRowset = (CRowset*)m_pCMDIChild->GetObject(eCRowset);
//Determine the Object Type...
if(pCRow)
m_pCMDIChild->DisplayDialog(IDD_ROWCHANGE, m_hWnd, CMDIChild::ColumnChangeProc, pCRow, IDM_IROW_SETCOLUMNS);
else if(pCDataset)
m_pCMDIChild->DisplayDialog(IDD_ROWCHANGE, m_hWnd, CMDIChild::ColumnChangeProc, pCDataset, IDM_DATASET_GETCELLDATA);
else if(pCRowset)
m_pCMDIChild->DisplayDialog(IDD_ROWCHANGE, m_hWnd, CMDIChild::ColumnChangeProc, pCRowset, IDM_SETDATA);
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////
// CDataGrid::OnItemActivate
//
/////////////////////////////////////////////////////////////////////
BOOL CDataGrid::OnItemActivate(INT idCtrl, NMLISTVIEW* pNMListView)
{
CDataAccess* pCDataAccess = m_pCMDIChild->m_pCDataAccess;
CRow* pCRow = SOURCE_GETOBJECT(pCDataAccess, CRow);
CDataset* pCDataset = SOURCE_GETOBJECT(pCDataAccess, CDataset);
INDEX iSelCol = pNMListView->iSubItem-1;
//If this is a row object, then bring up the SetColumns dialog...
if(pCRow)
{
//IRowChange::SetColumns
m_pCMDIChild->ChangeSelectedRow(pCRow, IDM_IROW_SETCOLUMNS);
}
else if(pCDataset)
{
//IMDDataset::GetCellData
m_pCMDIChild->ChangeSelectedRow(pCDataset, IDM_DATASET_GETCELLDATA);
}
else
{
CRowset* pCRowset = SOURCE_GETOBJECT(pCDataAccess, CRowset);
if(pCRowset)
{
//If the parent object is an enumerator, then Double Clicking on the row
//means you wish to "drill" into that row of the enumerator and call ParseDisplayName...
if(pCRowset->m_pCParent && pCRowset->m_pCParent->GetObjectType() == eCEnumerator)
{
//If enumertor rowset, double-clicking on a row
//brings up the ParseName object in another window
CWaitCursor waitCursor;
m_pCMDIChild->CreateEnumChild();
return TRUE;
}
//See if the selected column is a chapter column...
if((DBCOUNTITEM)iSelCol < pCRowset->m_Bindings.GetCount())
{
const DBBINDING* pBinding = &pCRowset->m_Bindings[iSelCol];
const DBCOLUMNINFO* pColInfo = pCRowset->m_ColumnInfo.GetOrdinal(pBinding->iOrdinal);
if(pColInfo->dwFlags & DBCOLUMNFLAGS_ISCHAPTER)
{
//Obtain the Child rowset..
m_pCMDIChild->GetChapteredChild(iSelCol, pBinding);
return TRUE;
}
}
//Otherwise we just have a "normal" rowset...
HROW hRow;
if(GetSelectedRow(&hRow, FALSE) != LVM_ERR)
{
CWaitCursor waitCursor;
IUnknown* pIUnknown = NULL;
//So either we are drilling into a row object from the rowset, or
//were are trying to edit the actual data of the row handle
if(SUCCEEDED(pCRowset->GetRowFromHROW(NULL, hRow, IID_IRow, &pIUnknown)))
{
//Create in new window
CBase* pCObject = m_pCMDIChild->m_pCMainWindow->HandleObjectType(pCRowset, pIUnknown, IID_IRow, eCRow, 0, NULL, CREATE_NEWWINDOW | CREATE_NODISPLAY);
if(pCObject)
{
//Fill in which row handle this row was created from...
//Just for display purposes...
CRow* pCRow = SOURCE_GETOBJECT(pCObject, CRow);
if(pCRow)
pCRow->m_hSourceRow = hRow;
pCObject->DisplayObject();
}
}
else
{
//Otherwise were just trying to update or view detailed info...
m_pCMDIChild->ChangeSelectedRow(pCRowset, IDM_SETDATA);
}
SAFE_RELEASE(pIUnknown);
}
}
}
return TRUE;
}
////////////////////////////////////////////////////////////////
// CDataGrid::OnKeyDown
//
/////////////////////////////////////////////////////////////////
BOOL CDataGrid::OnKeyDown(WPARAM nVirtKey, LPARAM lKeyData)
{
switch(nVirtKey)
{
case VK_DELETE:
{
PostMessage(m_pCMDIChild->m_hWnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_DELETEROWS, 0, 0));
return TRUE;
}
case VK_INSERT:
{
PostMessage(m_pCMDIChild->m_hWnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_INSERTROW, 0, 0));
return TRUE;
}
case VK_UP:
ScrollGrid(-1);
return TRUE;
case VK_DOWN:
ScrollGrid(1);
return TRUE;
case VK_PRIOR:
ScrollGrid(-m_lMaxRows);
return TRUE;
case VK_NEXT:
ScrollGrid(m_lMaxRows);
return TRUE;
case VK_TAB:
{
MSG msg;
m_pCMDIChild->m_pCQueryBox->SetFocus();
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
return TRUE;
}
};
return FALSE;
}
/////////////////////////////////////////////////////////////////////
// CDataGrid::OnVScroll
//
/////////////////////////////////////////////////////////////////////
BOOL CDataGrid::OnVScroll(int nScrollCode, int nPos, HWND hWnd)
{
switch(nScrollCode)
{
case SB_LINEUP:
ScrollGrid(-1);
break;
case SB_LINEDOWN:
ScrollGrid(1);
break;
case SB_PAGEUP:
ScrollGrid(-m_lMaxRows);
break;
case SB_PAGEDOWN:
ScrollGrid(m_lMaxRows);
break;
};
return FALSE;
}
////////////////////////////////////////////////////////////////
// CDataGrid::DisplayColumnInfo
//
/////////////////////////////////////////////////////////////////
HRESULT CDataGrid::DisplayColumnInfo()
{
INDEX iResult = 0;
CDataAccess* pCDataAccess = m_pCMDIChild->m_pCDataAccess;
//Insert the Column Headers.
//Only display the columns for which are bound in the Accessor
//Insert Row Header
InsertColumn(0, pCDataAccess->GetObjectType() == eCDataset ? L" Cell Ordinal " : L" Row Handle ");
ULONG i;
//Loop through the columns
for(i=0; i<pCDataAccess->m_Bindings.GetCount(); i++)
{
const DBCOLUMNINFO* pColInfo = pCDataAccess->m_ColumnInfo.GetOrdinal(pCDataAccess->m_Bindings[i].iOrdinal);
//Get ColumnName
iResult = InsertColumn(i+1, GetColName(pColInfo), pCDataAccess->GetColumnImage(pColInfo));
}
//AutoSize Columns, (including "Row-Handle" column)
for(i=0; i<pCDataAccess->m_Bindings.GetCount()+1; i++)
SetColumnWidth(i, LVSCW_AUTOSIZE_USEHEADER);
//CLEANUP:
return iResult == LVM_ERR ? E_FAIL : S_OK;
}
////////////////////////////////////////////////////////////////
// CDataGrid::RefreshData
//
/////////////////////////////////////////////////////////////////
HRESULT CDataGrid::RefreshData()
{
CWaitCursor waitCursor;
HRESULT hr = S_OK;
CDataAccess* pCDataAccess = m_pCMDIChild->m_pCDataAccess;
CRow* pCRow = SOURCE_GETOBJECT(pCDataAccess, CRow);
CRowset* pCRowset = SOURCE_GETOBJECT(pCDataAccess, CRowset);
DWORD dwRowsetOpts = GetOptions()->m_dwRowsetOpts;
//Clear ListView object
ClearAll();
//Display the Column Headers
//TODO: Would be nice to optimize this to not require a complete dump of all
//columns and redisplay, need to split out between create accessor and refresh...
TESTC(hr = DisplayColumnInfo());
//Row Object?
if(pCRow)
{
//Insert an empty row into the ListView
InsertItem(0, 0, L"", 0, IMAGE_NORMAL);
//Display the row data
TESTC(hr = DisplayData(pCRow->m_hSourceRow, 0, DBPROP_IRow));
}
else
{
//Determine the number of rows the user wants (initially)
//Always obtain more rows than what the grid allows so we can get the scroll bar
//visable. This way they can use the scroll bar up/dn to populate more rows
DBROWCOUNT cRowsToFetch = m_lMaxRows+3;
if(GetOptions()->m_dwRowsetOpts & ROWSET_ROWSTOFETCH)
cRowsToFetch = GetOptions()->m_cRowsToFetch;
if(cRowsToFetch)
TESTC(hr = GetNextRows(0, cRowsToFetch, TRUE/*fRetry*/));
}
CLEANUP:
m_pCMDIChild->UpdateControls();
return hr;
}
////////////////////////////////////////////////////////////////
// CDataGrid::DisplayData
//
/////////////////////////////////////////////////////////////////
HRESULT CDataGrid::DisplayData
(
HROW hRow,
INDEX iIndex,
DBPROPID dwSourceID,
bool fAlways
)
{
ASSERT(iIndex >=0 && iIndex<ULONG_MAX);
HRESULT hr = E_FAIL;
CDataAccess* pCDataAccess = m_pCMDIChild->m_pCDataAccess;
CRow* pCRow = SOURCE_GETOBJECT(pCDataAccess, CRow);
CRowset* pCRowset = SOURCE_GETOBJECT(pCDataAccess, CRowset);
CDataset* pCDataset = SOURCE_GETOBJECT(pCDataAccess, CDataset);
void* pData = pCDataAccess->m_pData;
DBSTATUS dbStatus = 0;
DWORD i,dwConvFlags = GetOptions()->m_dwConvFlags;
WCHAR wszBuffer[MAX_COL_SIZE+1] = {0};
//NOTE: We obtain/display the data - unless the users wishes to not obtain
//the data by default, or this is called from a method that should always obtain data (ie: GetData)
if(fAlways || !(GetOptions()->m_dwRowsetOpts & ROWSET_NODATA))
{
//This displays data from any source.
if(pCRow && dwSourceID == DBPROP_IRow)
{
//IRow::GetColumns
hr = pCRow->GetColumns(pCRow->m_cColAccess, pCRow->m_rgColAccess);
}
else if(pCRowset)
{
//IRowset::GetData
hr = pCRowset->GetData(hRow, NULL, pData, dwSourceID);
}
else if(pCDataset)
{
hRow = iIndex;
//IMDDataset::GetCellData
hr = pCDataset->GetCellData(hRow, hRow);
}
//Relax the errors here. With Get*Data both DB_S/DB_E will return a bad
//status for 1 or more columns. Or DataGrid will just display the column
//status if not S_OK. So for these errors just display the data anyway...
if(SUCCEEDED(hr) || hr== DB_E_ERRORSOCCURRED)
{
//Display all Columns
for(i=0; i<pCDataAccess->m_Bindings.GetCount(); i++)
{
const DBBINDING* pBinding = &pCDataAccess->m_Bindings[i];
const DBCOLUMNINFO* pColInfo = pCDataAccess->m_ColumnInfo.GetOrdinal(pBinding->iOrdinal);
//Obtain the column data...
pCDataAccess->GetColumnData(pBinding, pData, &dbStatus, NULL/*pdbLength*/, NULL, wszBuffer, MAX_COL_SIZE, dwConvFlags | CONV_TYPENAME, pColInfo->wType);
//Set item in ListView
SetItemText(iIndex, i+1, wszBuffer);
SetItemImage(iIndex, i+1, pCDataAccess->GetColumnImage(NULL, dbStatus));
}
//Clean outofline memory data
//TODO - need to free in the case of errors as well. But have to be careful
//since the pData may not have been setup yet, or other errors where its undefined...
pCDataAccess->m_Bindings.FreeData(pData);
}
}
//Now add the "hRow" indicator
if(hRow)
StringFormat(wszBuffer, NUMELE(wszBuffer), L"0x%p", hRow);
else
StringFormat(wszBuffer, NUMELE(wszBuffer), L"No Handle");
SetItemText(iIndex, 0, wszBuffer);
SetItemParam(iIndex, 0, hRow);
return hr;
}
////////////////////////////////////////////////////////////////
// CDataGrid::DisplayRows
//
/////////////////////////////////////////////////////////////////
HRESULT CDataGrid::DisplayRows(DBROWOFFSET lOffset, DBROWCOUNT cRows, DBCOUNTITEM cRowsObtained, HROW* rghRows, BOOL fAdjustFetchPosition)
{
HRESULT hr = S_OK;
DBROWOFFSET lStartIndex = lOffset;
BOOL fLastFetchForward = FALSE;
//Obtain total ListItems
INDEX cItems = GetItemCount();
ASSERT(cItems >= 0);
// Since RowsetViewer displays the abstract "NextFetchPosition" to
// the user and we need to make sure we put the correct rows obtained into
// the correct indexs, we need to map the OLE DB Fetch Position into an index
// based method for our listview.
//
// The OLE DB Cursor (NextFetchPosition) is always "in-between" rows
// Meaning its either before or after the row, (not actually on the row).
// For example: If the NFP is before row 2, and cRows=1, then row 2 will be
// retrieved, but if it was after then row 3 is retrieved. Likewise if
// NFP is before row and cRows=-1, then row 1 is retrived, but if it was
// after then row 2 is retrieved. Doing a Forward fetch (cRows++) makes
// the NFP after that row, and a Backward fetch (cRows--) makes the
// NFP appear before.
// +---------------+---------------+---------------------------|-----------------------------------+
// | LastFetch | cRows | StartIndex | EndIndex |
// +---------------+---------------+---------------------------+-----------------------------------+
// |#1 Forward | Positive | CurIndex + Offset + 1 | StartIndex + cRowsObtained - 1 |
// |#2 Forward | Negative | CurIndex + Offset | StartIndex - cRowsObtained + 1 |
// |#3 Backward | Positive | CurIndex + Offset | StartIndex + cRowsObtained - 1 |
// |#4 Backward | Negative | CurIndex + Offset - 1 | StartIndex - cRowsObtained + 1 |
// +---------------+---------------+---------------------------+-----------------------------------+
//Calculate the StartIndex (using the Table Above)
if(fAdjustFetchPosition)
{
//#1, #2, #3, #4 (Common Case) is just CurIndex + Offset
lStartIndex = m_lCurPos + lOffset;
fLastFetchForward = m_fLastFetchForward;
//#1
if(fLastFetchForward && cRows > 0)
lStartIndex += 1;
//#4
if(!fLastFetchForward && cRows < 0)
lStartIndex -= 1;
}
//Determine Ending Index
DBROWOFFSET lEndIndex = lStartIndex;
if(cRowsObtained)
{
if(cRows > 0)
{
//#1, #3
lEndIndex = lStartIndex + cRowsObtained - 1;
fLastFetchForward = TRUE;
}
else
{
//#2, #4
lEndIndex = lStartIndex - cRowsObtained + 1;
fLastFetchForward = FALSE;
}
//Remove Previous Fetch Icon
if(fAdjustFetchPosition)
SetItemImage((INDEX)m_lCurPos, 0, IMAGE_NORMAL);
//Remove Previous Selection Bars
for(INDEX iIndex=0; iIndex<cItems; iIndex++)
SetItemState(iIndex, 0, ~LVIS_SELECTED, LVIS_SELECTED);
}
//Loop over rows obtained, displaying/updating in the ListView
for(DBCOUNTITEM iRow=0; iRow<cRowsObtained; iRow++)
{
ASSERT(rghRows);
//Calulate which direction to start with
HROW hRow = rghRows[iRow];
INDEX iIndex = (INDEX)(cRows > 0 ? lStartIndex + iRow : lStartIndex - iRow);
//We may need extra row padding, if fetched out of sequence...
while(iIndex >= cItems)
{
InsertItem(iIndex, 0, L"", 0, IMAGE_NORMAL);
cItems++;
}
//We may need to insert rows before the beginging if scrolling
//around the rowset...
while(iIndex < 0)
{
InsertItem(0, 0, L"", 0, IMAGE_NORMAL);
cItems++;
//A row is being inserted, meaning this shifts all our
//current indexes by one...
lStartIndex++;
lEndIndex++;
iIndex++;
m_lCurPos++;
}
//Display GetData in the ListView
hr = DisplayData(hRow, iIndex);
}
//Scroll the new rows into view...
if(cRowsObtained)
{
//Adjust our saved Fetched Position
if(fAdjustFetchPosition)
{
//Display the direction of the cursor
DisplayFetchPosition(lEndIndex, fLastFetchForward);
}
//Make sure the item is visible
EnsureVisible(lEndIndex);
}
return hr;
}
////////////////////////////////////////////////////////////////
// CDataGrid::DisplayFetchPosition
//
/////////////////////////////////////////////////////////////////
HRESULT CDataGrid::DisplayFetchPosition(INDEX iIndex, BOOL fLastFetchForward)
{
//Display the direction of the cursor
SetItemImage(iIndex, 0, fLastFetchForward ? IMAGE_ARROW_DOWN : IMAGE_ARROW_UP);
//Display the new Selection Bar for this row
SetItemState(iIndex, 0, LVIS_SELECTED, LVIS_SELECTED);
//Update our saved cursor position
m_lCurPos = iIndex;
m_fLastFetchForward = fLastFetchForward;
//Make sure the item is visible
EnsureVisible(iIndex);
return S_OK;
}
////////////////////////////////////////////////////////////////
// CDataGrid::RestartPosition
//
/////////////////////////////////////////////////////////////////
HRESULT CDataGrid::RestartPosition()
{
CWaitCursor waitCursor;
HRESULT hr = S_OK;
CRowset* pCRowset = (CRowset*)m_pCMDIChild->GetObject(eCRowset);
if(pCRowset && pCRowset->m_pIRowset)
{
//Release previously fetched rows, (if user requested)
TESTC(hr = ReleaseHeldRows());
//RestartPosition...
TESTC(hr = pCRowset->RestartPosition());
}
//Need to remove the "NextFetchPositon" icon from the "old" row
SetItemImage((INDEX)m_lCurPos, 0, IMAGE_NORMAL);
m_fLastFetchForward = FALSE;
m_lCurPos = 0;
//Need to show the "NextFetchPositon" icon
SetItemImage((INDEX)m_lCurPos, 0, IMAGE_ARROW_UP);
EnsureVisible((INDEX)m_lCurPos);
CLEANUP:
return hr;
}
////////////////////////////////////////////////////////////////
// CDataGrid::GetNextRows
//
/////////////////////////////////////////////////////////////////
HRESULT CDataGrid::GetNextRows(DBROWOFFSET lOffset, DBROWCOUNT cRows, BOOL fRetry)
{
HRESULT hr = S_OK;
HRESULT hrGNR = S_OK;
CDataAccess* pCDataAccess = m_pCMDIChild->m_pCDataAccess;
CRowset* pCRowset = SOURCE_GETOBJECT(pCDataAccess, CRowset);
CWaitCursor waitCursor;
DBCOUNTITEM cRowsObtained = 0;
HROW rghRows[MAX_OPENROWS];
HROW* phRows = rghRows;
//Only use dynamic memory allocation if more rows than our static array
if((cRows > MAX_OPENROWS) || (cRows < -MAX_OPENROWS))
phRows = NULL;
if(pCRowset)
{
//Retry is dependednt upon ability to release previously held rows...
fRetry = fRetry && (GetOptions()->m_dwRowsetOpts & ROWSET_ALWAYSRELEASEROWS);
while(TRUE)
{
//Release previously fetched rows, (if user requested)
TESTC(hr = ReleaseHeldRows());
//IRowset::GetNextRows
TESTC(hr = hrGNR = pCRowset->GetNextRows(lOffset, cRows, &cRowsObtained, &phRows));
//Now Display the rows...
TESTC(hr = DisplayRows(lOffset, cRows, cRowsObtained, phRows, TRUE/*fAdjustFetchPosition*/));
//Some providers may have limitations on the number of rows that can be returned in
//one call, but the consumer may actually just wish to see all the rows without having
//to "manually" scroll down one row at a time. The consumer indicates they wish this
//behavior by having "ReleaseRowsAlways" on, so we will do whatever possible to obtain
//all the requested rows - assuming the calling context is "retry-able" - ie: fRetry
if(fRetry && cRowsObtained)
{
//If we are not at the end of the rowset, and not all rows were retrieved
//then retry. Provider probably returned DB_S_ROWLIMITEXCEEDED
if(hrGNR!=DB_S_ENDOFROWSET && cRowsObtained < (DBCOUNTITEM)ABS(cRows))
{
cRows -= cRowsObtained;
continue;
}
}
//Were done...
break;
}
}
else
{
ASSERT(cRows <= MAX_OPENROWS);
cRowsObtained = ABS(cRows);
//Now Display the rows...
TESTC(hr = DisplayRows(lOffset, cRows, cRowsObtained, phRows, TRUE/*fAdjustFetchPosition*/));
}
CLEANUP:
//Delete the rows if provider allocated
if(phRows != rghRows)
SAFE_FREE(phRows);
return hr;
}
////////////////////////////////////////////////////////////////
// CDataGrid::GetSelectedRow
//
/////////////////////////////////////////////////////////////////
INDEX CDataGrid::GetSelectedRow(HROW* phRow, BOOL fValidate)
{
//Find the Selected Item in the ListView
INDEX iSelRow = GetNextItem(-1, LVNI_SELECTED);
if(iSelRow == LVM_ERR)
{
if(fValidate)
{
wMessageBox(GetFocus(), MB_TASKMODAL | MB_ICONHAND | MB_OK | MB_DEFBUTTON1,
wsz_ERROR, L"Must first select a row...");
}
return iSelRow;
}
//Otherwise we have a valid row...
if(phRow)
*phRow = GetItemParam(iSelRow);
return iSelRow;
}
////////////////////////////////////////////////////////////////
// CDataGrid::ReleaseHeldRows
//
/////////////////////////////////////////////////////////////////
HRESULT CDataGrid::ReleaseHeldRows()
{
//Release previously fetched rows, (if user requested)
if(GetOptions()->m_dwRowsetOpts & ROWSET_ALWAYSRELEASEROWS)
{
return ReleaseRows(LV_ALLITEMS, TRUE/*fOnlyValidRows*/);
}
return S_OK;
}
////////////////////////////////////////////////////////////////
// CDataGrid::ReleaseRows
//
/////////////////////////////////////////////////////////////////
HRESULT CDataGrid::ReleaseRows(INDEX iIndex, BOOL fOnlyValidRows)
{
HRESULT hr = S_OK;
CRowset* pCRowset = (CRowset*)m_pCMDIChild->GetObject(eCRowset);
INDEX i,cRows = 0;
INDEX* rgItems = NULL;
HROW* rghRows = NULL;
ULONG* rgRefCounts = NULL;
//Release all rows
if(iIndex == LV_ALLITEMS)
{
//Find all Rows
LV_GetAllItems(m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
}
//Release all selected rows
else if(iIndex == LV_ALLSELITEMS)
{
//Find all Selected Rows
LV_GetSelItems(m_hWnd, &cRows, &rgItems, (LPARAM**)&rghRows);
}
//Release 1 Row
else
{
//First need to obtain the LPARAM (hRow) to Release it...
//TODO: Shouldn't dynamic allocation here!
cRows = 1;
SAFE_ALLOC(rgItems, INDEX, cRows);
SAFE_ALLOC(rghRows, HROW, cRows);
rgItems[0] = iIndex;
rghRows[0] = GetItemParam(iIndex);
}
//Release only valid rows
if(fOnlyValidRows)
{
//Loop over all rows...
ULONG iLastValid = 0;
for(i=0; i<cRows; i++)
{
//Compact out invalid row handles...
if(rghRows[i] == NULL)
continue;
//Inplace shift...
rghRows[iLastValid] = rghRows[i];
rgItems[iLastValid] = rgItems[i];
iLastValid++;
}
cRows = iLastValid;
}
//Now ReleaseRows in 1 pass
if(pCRowset && pCRowset->GetObjectType() != eCDataset)
{
if(cRows || !fOnlyValidRows)
{
SAFE_ALLOC(rgRefCounts, ULONG, cRows);
TESTC(hr = pCRowset->ReleaseRows(cRows, rghRows, rgRefCounts));
}
}
CLEANUP:
//If any rows have a refcount of 0, we should NULL the row handle
//so we can detect the error before GetData is called on a release row
for(i=0; i<cRows; i++)
{
if(rgRefCounts[i] == 0)
{
//Update the row handle, and the display
SetItemText(rgItems[i], 0, L"");
SetItemParam(rgItems[i], 0, DB_NULL_HROW);
}
}
SAFE_FREE(rgItems);
SAFE_FREE(rghRows);
SAFE_FREE(rgRefCounts);
return hr;
}
////////////////////////////////////////////////////////////////
// CDataGrid::AddRefRows
//
/////////////////////////////////////////////////////////////////
HRESULT CDataGrid::AddRefRows(INDEX iIndex)
{
HRESULT hr = S_OK;
CRowset* pCRowset = (CRowset*)m_pCMDIChild->GetObject(eCRowset);
INDEX cRows = 0;
HROW* rghRows = NULL;
ULONG* rgRefCounts = NULL;
//AddRefRows all Rows
if(iIndex == LV_ALLITEMS)
{
//Find all Rows
LV_GetAllItems(m_hWnd, &cRows, NULL, (LPARAM**)&rghRows);
}
//AddRefRows all selected rows
else if(iIndex == LV_ALLSELITEMS)
{
//Find all Selected Rows
LV_GetSelItems(m_hWnd, &cRows, NULL, (LPARAM**)&rghRows);
}
//AddRefRows 1 Row
else
{
//First need to obtain the LPARAM (hRow) to Release it...
cRows = 1;
rghRows[0] = GetItemParam(iIndex);
}
//Now AddRefRows in 1 pass
if(pCRowset && pCRowset->GetObjectType() != eCDataset)
{
SAFE_ALLOC(rgRefCounts, ULONG, cRows);
TESTC(hr = pCRowset->AddRefRows(cRows, rghRows, rgRefCounts));
}
CLEANUP:
SAFE_FREE(rghRows);
SAFE_FREE(rgRefCounts);
return hr;
}
////////////////////////////////////////////////////////////////
// CDataGrid::ScrollGrid
//
/////////////////////////////////////////////////////////////////
HRESULT CDataGrid::ScrollGrid(DBROWCOUNT cItems)
{
return GetNextRows(0, cItems, TRUE/*fRetry*/);
}
////////////////////////////////////////////////////////////////
// CDataGrid::ClearAll
//
/////////////////////////////////////////////////////////////////
BOOL CDataGrid::ClearAll(WCHAR* pwszEmptyName)
{
// Delete all of the items. (no need to release rows...)
DeleteAllItems();
// Delete all of the columns and their names.
while(DeleteColumn(0));
//Indicate no Rowset
if(pwszEmptyName)
{
InsertColumn(0, pwszEmptyName);
SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
}
return TRUE;
}