//----------------------------------------------------------------------------- // Microsoft OLE DB RowsetViewer // Copyright (C) 1994 - 1999 By Microsoft Corporation. // // @doc // // @module CMDICHILD.CPP // //----------------------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////////// // Includes // ////////////////////////////////////////////////////////////////////////////// #include "Headers.h" #ifdef MTSTXN #include #include #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 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; iDisplayData(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 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 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 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 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 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 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 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 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 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 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; iGetBookmark(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; im_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; iGetBookmark(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; iDisplayData(rghRows[i], rgSelItems[i]); } //Cleanup for(i=0; im_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; iDisplayData(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; iDisplayData(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; iDisplayData(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; iDisplayData(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; iDisplayData(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; iDisplayData(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 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; im_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; iSetItemImage(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; iSetItemImage(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; iSetColumnData(&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; iBindm_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; im_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; im_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; iGetItemParam(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; iGetItemParam(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; iAxiscDimensions); 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; iDimcDimensions; 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; iDimFreeAxisInfo(&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; iAxisFreeAxisInfo(&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 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; iGetColumnImage(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; iFlagdwFlags & g_rgColFlagsMaps[iFlag].lItem ? IMAGE_CHECKED : IMAGE_UNCHECKED); } //AutoSize all columns for(i=0; i 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; im_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 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; im_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; im_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; iCreateAccessor(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"); 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""); //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 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; im_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; ipwszName, 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 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; ilt == (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 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 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; iSetupTransactionCombo(::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 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; im_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; im_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 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; ieKind = 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; ieKind) 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; im_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; im_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; im_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; im_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; im_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; im_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; im_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 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; iSelDelete(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; iSelm_idSource == IDM_ISCOPEDOPERATIONS_MOVE) { ::SetWindowText(hWnd, "IScopedOperations::Move"); for(ULONG i=0; i 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; iSelm_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 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; im_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; im_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 ", 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; im_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 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; im_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; im_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 && iIndexm_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; im_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 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; iGetObjectType() != 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; iGetObject(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; }