📄 occsite.cpp
字号:
const IID CLSID_DataAdapter = {0x3A08E130L,0x8F65,0x11D0,{0x94,0x84,0x00,0xA0,0xC9,0x11,0x10,0xED}};
HRESULT CDataSourceControl::Initialize()
{
// The following is a work around for RDC behaviour when on an invisible dlg
// When the dlg is invisible it cannot display the ODBC connect dialog
// So check if visible, if not make it so and move it to the center
// of the screen with null size. Then do the connect dialog
// Finally put it all back like it was.
CWnd* pParent = m_pClientSite->m_pWndCtrl->GetTopLevelParent();
BOOL bHidden = !pParent->IsWindowVisible();
CRect rcParent;
if (bHidden)
{
CRect rcDesktop;
CWnd::GetDesktopWindow()->GetWindowRect(&rcDesktop);
pParent->GetWindowRect(&rcParent);
pParent->MoveWindow((rcDesktop.right - rcDesktop.left)/2, (rcDesktop.bottom - rcDesktop.top)/2, 0, 0, FALSE);
pParent->ShowWindow(SW_SHOWNORMAL);
}
IVBDSC* pDSC;
HRESULT hRes;
hRes = m_pClientSite->m_pObject->QueryInterface(IID_IDataSource, (void**)&m_pDataSource);
if (SUCCEEDED(hRes))
{
hRes = m_pDataSource->GetDataMember(NULL, &IID_IRowPosition, (IUnknown**)&m_pRowPosition);
if (m_pRowPosition == NULL)
hRes = E_POINTER;
if (FAILED(hRes))
{
if (bHidden)
{
pParent->MoveWindow(rcParent.left, rcParent.top, rcParent.right - rcParent.left, rcParent.bottom - rcParent.top, FALSE);
pParent->ShowWindow(SW_HIDE);
}
return hRes;
}
}
else
{
hRes = m_pClientSite->m_pObject->QueryInterface(IID_IVBDSC, (void**)&pDSC);
if (FAILED(hRes))
return hRes;
ICursor* pCursor;
pDSC->CreateCursor(&pCursor);
pDSC->Release();
if (!pCursor)
return E_FAIL;
hRes = pCursor->QueryInterface(IID_ICursorMove,
(LPVOID *)&m_pCursorMove);
pCursor->Release();
if (FAILED(hRes))
return hRes;
hRes = m_pCursorMove->QueryInterface(IID_ICursorUpdateARow,
(LPVOID *)&m_pCursorUpdateARow);
}
hRes = GetMetaData();
if (bHidden)
{
pParent->MoveWindow(rcParent.left, rcParent.top, rcParent.right - rcParent.left, rcParent.bottom - rcParent.top, FALSE);
pParent->ShowWindow(SW_HIDE);
}
return hRes;
}
IUnknown* CDataSourceControl::GetCursor()
{
ASSERT(m_pClientSite != NULL);
if (m_pDataSource != NULL)
{
if(m_pRowset != NULL)
return m_pDataSource;
return NULL;
}
ICursor* pCursor;
if (!m_pCursorMove)
{
IVBDSC* pDSC;
HRESULT hRes;
hRes = m_pClientSite->m_pObject->QueryInterface(IID_IVBDSC, (void**)&pDSC);
if (FAILED(hRes))
return NULL;
pDSC->CreateCursor(&pCursor);
pDSC->Release();
if (!pCursor)
return NULL;
return pCursor;
}
if (SUCCEEDED(m_pCursorMove->QueryInterface(IID_ICursor, (LPVOID *) &pCursor)))
return pCursor;
ASSERT(FALSE); // DSC Cursor Not Found
return NULL;
}
HRESULT CDataSourceControl::GetMetaData()
{
HRESULT hRes;
METAROWTYPE* pOldMetaData = m_pMetaRowData;
int nOldColumns = m_nColumns;
if (m_pDataSource != NULL)
{
IRowset* pRowset;
hRes = m_pRowPosition->GetRowset(IID_IRowset, reinterpret_cast<IUnknown**>(&pRowset));
if (FAILED(hRes))
return hRes;
{
LPCONNECTIONPOINTCONTAINER pConnPtCont;
if (SUCCEEDED(pRowset->QueryInterface(IID_IConnectionPointContainer,
(LPVOID*)&pConnPtCont)))
{
ASSERT(pConnPtCont != NULL);
LPCONNECTIONPOINT pConnPt = NULL;
if (SUCCEEDED(pConnPtCont->FindConnectionPoint(IID_IRowsetNotify, &pConnPt)))
{
ASSERT(pConnPt != NULL);
pConnPt->Advise(&m_pClientSite->m_xRowsetNotify, &m_dwRowsetNotify);
pConnPt->Release();
}
pConnPtCont->Release();
}
}
m_pRowset = new CRowset(pRowset);
pRowset->Release();
m_pRowset->SetupOptionalRowsetInterfaces();
m_pDynamicAccessor = new CDynamicAccessor;
m_pDynamicAccessor->BindColumns(m_pRowset->m_spRowset);
m_pRowset->SetAccessor(m_pDynamicAccessor);
m_nColumns = m_pDynamicAccessor->GetColumnCount();
m_pMetaRowData = (METAROWTYPE*)::CoTaskMemAlloc(sizeof(METAROWTYPE) * m_nColumns);
ASSERT(m_pMetaRowData);
memset(m_pMetaRowData, 0, sizeof(METAROWTYPE) * m_nColumns);
m_pRowset->MoveFirst();
m_pRowset->ReleaseRows();
}
else
{
ULONG nRows;
ICursor* pCursor = (LPCURSOR)m_pCursorMove;
ICursor* pColumnCursor;
if (pCursor == NULL)
return S_OK;
hRes = pCursor->GetColumnsCursor(IID_ICursor, (IUnknown **) &pColumnCursor, &nRows);
if (FAILED(hRes))
return hRes;
DBCOLUMNBINDING MetaColumns[2];
CopyColumnID(&MetaColumns[0].columnID, &COLUMN_COLUMNID);
MetaColumns[0].obData = offsetof(METAROWTYPE, idColumnID);
MetaColumns[0].cbMaxLen = DB_NOMAXLENGTH;
MetaColumns[0].obInfo = offsetof(METAROWTYPE, dwColumnID);
MetaColumns[0].obVarDataLen = DB_NOVALUE;
MetaColumns[0].dwBinding = DBBINDING_DEFAULT;
MetaColumns[0].dwDataType = DBTYPE_COLUMNID;
CopyColumnID(&MetaColumns[1].columnID, &COLUMN_NAME);
MetaColumns[1].obData = offsetof(METAROWTYPE, lpstrName);
MetaColumns[1].cbMaxLen = DB_NOMAXLENGTH;
MetaColumns[1].obInfo = offsetof(METAROWTYPE, dwName);
MetaColumns[1].obVarDataLen = DB_NOVALUE;
MetaColumns[1].dwBinding = DBBINDING_DEFAULT;
MetaColumns[1].dwDataType = VT_LPSTR;
hRes = pColumnCursor->SetBindings(2, MetaColumns, sizeof(METAROWTYPE),
DBCOLUMNBINDOPTS_REPLACE);
if (FAILED(hRes))
{
pColumnCursor->Release();
return hRes;
}
DBFETCHROWS FetchRows;
FetchRows.cRowsRequested = nRows;
FetchRows.dwFlags = DBROWFETCH_CALLEEALLOCATES;
FetchRows.pData = NULL;
FetchRows.pVarData = NULL;
FetchRows.cbVarData = 0;
LARGE_INTEGER dlZero;
LISet32(dlZero, 0);
hRes = pColumnCursor->GetNextRows(dlZero, &FetchRows);
if (FAILED(hRes))
{
pColumnCursor->Release();
return hRes;
}
m_pMetaRowData = (METAROWTYPE *)FetchRows.pData;
ASSERT(m_pMetaRowData);
nRows = FetchRows.cRowsReturned; // in case it changed
m_pVarData = FetchRows.pVarData;
m_nColumns = nRows;
pColumnCursor->Release();
}
for (int nCol=0; nCol<m_nColumns; nCol++)
m_pMetaRowData[nCol].m_pClientList = new CPtrList;
// re-establish all bound property sites and then delete old meta-data
if (pOldMetaData != NULL)
{
for (int nCol=0; nCol<nOldColumns; nCol++)
{
POSITION pos = pOldMetaData[nCol].m_pClientList->GetHeadPosition();
while (pos)
{
COleControlSite* pSite = (COleControlSite *)
m_pMetaRowData[nCol].m_pClientList->GetNext(pos);
BindProp(pSite, TRUE);
}
pOldMetaData[nCol].m_pClientList->RemoveAll();
delete pOldMetaData[nCol].m_pClientList;
}
::CoTaskMemFree(pOldMetaData);
}
return hRes;
}
BOOL CDataSourceControl::CopyColumnID(
DBCOLUMNID* pcidDst, DBCOLUMNID const *pcidSrc)
{
pcidDst->dwKind = pcidSrc->dwKind;
switch (pcidSrc->dwKind)
{
case DBCOLKIND_GUID_NUMBER:
pcidDst->guid = pcidSrc->guid;
pcidDst->lNumber = pcidSrc->lNumber;
break;
case DBCOLKIND_GUID_NAME:
pcidDst->guid = pcidSrc->guid;
// fall through
case DBCOLKIND_NAME:
pcidDst->lpdbsz = (LPDBSTR) ::CoTaskMemAlloc(sizeof(DBCHAR) * (ldbstrlen(pcidSrc->lpdbsz) + 1));
if (!pcidDst->lpdbsz)
return FALSE;
ldbstrcpy(pcidDst->lpdbsz, pcidSrc->lpdbsz);
break;
}
return TRUE;
}
// Make a bound control/bound property a consumer to a particular column in this DSC
void CDataSourceControl::BindProp(COleControlSite* pClientSite, BOOL bBind)
{
ASSERT(pClientSite);
if (bBind)
{
BindProp(pClientSite, FALSE);
ASSERT(pClientSite->m_pDSCSite == m_pClientSite);
if (m_pDataSource != NULL)
{
for (int nCol=0; nCol<m_nColumns; nCol++)
{
if (pClientSite->m_strDataField == m_pDynamicAccessor->GetColumnName(nCol + 1))
{
m_pMetaRowData[nCol].m_pClientList->AddTail(pClientSite);
return;
}
}
}
else
{
for (int nCol=0; nCol<m_nColumns; nCol++)
{
if (m_pMetaRowData[nCol].lpstrName == NULL)
continue;
if (pClientSite->m_strDataField == m_pMetaRowData[nCol].lpstrName)
{
m_pMetaRowData[nCol].m_pClientList->AddTail(pClientSite);
return;
}
}
}
pClientSite->m_pDSCSite = NULL;
return;
}
UpdateCursor();
// UnBind
for (int nCol=0; nCol<m_nColumns; nCol++)
{
POSITION pos = m_pMetaRowData[nCol].m_pClientList->GetHeadPosition();
POSITION prev;
while (pos)
{
prev = pos;
COleControlSite* pSite = (COleControlSite *)
m_pMetaRowData[nCol].m_pClientList->GetNext(pos);
if (pSite == pClientSite)
{
m_pMetaRowData[nCol].m_pClientList->RemoveAt(prev);
return;
}
}
}
}
// Make a cursor bound control property a client to this control
void CDataSourceControl::BindProp(CDataBoundProperty* pProperty, BOOL bBind)
{
ASSERT(pProperty);
if (bBind)
{
BindProp(pProperty, FALSE);
m_CursorBoundProps.AddTail(pProperty);
}
else
{
UpdateCursor();
POSITION pos = m_CursorBoundProps.Find(pProperty);
if (pos != NULL)
m_CursorBoundProps.RemoveAt(pos);
}
}
void CDataSourceControl::BindColumns()
{
if (m_pDataSource != NULL)
{
// this is done automatically by CDynamicAccessor
GetBoundClientRow();
UpdateControls();
return;
}
if (m_pValues)
{
for (int i=0; i<m_nBindings; i++)
::VariantClear(&m_pValues[i]);
if (m_nBindings > 0)
{
delete[] m_pValues;
delete[] m_pColumnBindings;
}
m_pValues = NULL;
}
m_nBindings = 0;
for (int nCol=0; nCol<m_nColumns; nCol++)
{
m_nBindings += m_pMetaRowData[nCol].m_pClientList->GetCount();
}
if (m_nBindings > 0)
m_pColumnBindings = new DBCOLUMNBINDING[m_nBindings];
int nItem = 0;
for (nCol=0; nCol<m_nColumns; nCol++)
{
POSITION pos = m_pMetaRowData[nCol].m_pClientList->GetHeadPosition();
while (pos)
{
COleControlSite* pSite = (COleControlSite *)
m_pMetaRowData[nCol].m_pClientList->GetNext(pos);
CopyColumnID(&m_pColumnBindings[nItem].columnID, &m_pMetaRowData[nCol].idColumnID);
m_pColumnBindings[nItem].obData = sizeof(VARIANT) * nItem;
m_pColumnBindings[nItem].cbMaxLen = DB_NOMAXLENGTH;
m_pColumnBindings[nItem].obInfo = DB_NOVALUE;
m_pColumnBindings[nItem].obVarDataLen = DB_NOVALUE;
m_pColumnBindings[nItem].dwBinding = DBBINDING_VARIANT;
m_pColumnBindings[nItem].dwDataType = pSite->m_dwType;
nItem++;
}
}
m_pCursorMove->SetBindings(m_nBindings, m_pColumnBindings,
sizeof(VARIANT) * m_nBindings, DBCOLUMNBINDOPTS_REPLACE);
if (m_nBindings)
m_pValues = new VARIANT[m_nBindings];
for (int i=0; i<m_nBindings; i++)
{
memset(&m_pValues[i], 0, sizeof(VARIANT));
m_pValues[i].vt = VT_EMPTY;
}
GetBoundClientRow();
UpdateControls();
}
HRESULT CDataSourceControl::GetBoundClientRow()
{
DBFETCHROWS FetchRows;
if (m_pDataSource != NULL)
{
if(m_pRowset == NULL)
return S_OK;
if(m_pRowset->m_hRow == NULL)
return S_OK;
return m_pRowset->GetData();
}
if (m_nBindings == 0)
return S_OK;
FetchRows.pData = m_pValues;
FetchRows.pVarData = NULL;
FetchRows.cbVarData = NULL;
FetchRows.cRowsRequested = 1;
FetchRows.dwFlags = 0;
LARGE_INTEGER dl = { 0, 0};
return m_pCursorMove->Move(1, (LPVOID)&DBBMK_CURRENT, dl, &FetchRows);
}
COleVariant CDataSourceControl::ToVariant(int nCol)
{
ASSERT(m_pDataSource != NULL);
ASSERT(m_pDynamicAccessor != NULL);
COleVariant vt;
DBSTATUS dbStatus;
DBTYPE dbType;
m_pDynamicAccessor->GetStatus(nCol, &dbStatus);
if(dbStatus == DBSTATUS_S_ISNULL)
return vt; // just return a blank variant
if(!m_pDynamicAccessor->GetColumnType(nCol, &dbType))
return vt;
switch (dbType)
{
case DBTYPE_VARIANT:
vt = COleVariant((LPCVARIANT)m_pDynamicAccessor->GetValue(nCol));
break;
case DBTYPE_STR:
vt = COleVariant(CString((LPCSTR)m_pDynamicAccessor->GetValue(nCol)), VT_BSTR);
break;
case DBTYPE_WSTR:
case DBTYPE_BSTR:
vt = COleVariant(CString((LPCWSTR)m_pDynamicAccessor->GetValue(nCol)), VT_BSTR);
break;
case DBTYPE_I1:
case DBTYPE_UI1:
vt = COleVariant(*((BYTE*)m_pDynamicAccessor->GetValue(nCol)));
break;
case DBTYPE_I2:
case DBTYPE_UI2:
vt = COleVariant(*((short*)m_pDynamicAccessor->GetValue(nCol)));
break;
case DBTYPE_I4:
case DBTYPE_UI4:
vt = COleVariant(*((long*)m_pDynamicAccessor->GetValue(nCol)));
break;
case DBTYPE_R4:
vt = COleVariant(*((float*)m_pDynamicAccessor->GetValue(nCol)));
break;
case DBTYPE_R8:
vt = COleVariant(*((double*)m_pDynamicAccessor->GetValue(nCol)));
break;
case DBTYPE_BOOL:
vt = COleVariant((short)*(BOOL*)m_pDynamicAccessor->GetValue(nCol), VT_BOOL);
break;
case DBTYPE_DATE:
{
COleDateTime dt(*((DATE*)m_pDynamicAccessor->GetValue(nCol)));
vt = COleVariant(dt);
}
break;
case DBTYPE_CY:
{
COleCurrency cy(*((CURRENCY*)m_pDynamicAccessor->GetValue(nCol)));
vt = COleVariant(cy);
}
break;
case DBTYPE_NUMERIC:
{
DB_NUMERIC num;
if(m_pDynamicAccessor->GetValue(nCol, &num))
{
double dbl;
dbl = (double)*((__int64*)num.val);
while(num.scale-- > 0)
dbl /= 10;
if(num.sign == 0)
dbl = -dbl;
vt = COleVariant(dbl);
}
}
break;
case DBTYPE_DBDATE:
{
DBDATE dbDate;
if(m_pDynamicAccessor->GetValue(nCol, &dbDate))
{
COleDateTime dt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -