Dynamicznie określanie kolumn zwracanych do konsumenta

Makra PROVIDER_COLUMN_ENTRY zwykle obsługują wywołanie IColumnsInfo::GetColumnsInfo . Jednak ze względu na to, że konsument może zdecydować się na używanie zakładek, dostawca musi mieć możliwość zmiany zwracanych kolumn w zależności od tego, czy użytkownik prosi o zakładkę.

Aby obsłużyć wywołanie IColumnsInfo::GetColumnsInfo , usuń PROVIDER_COLUMN_MAPelement , który definiuje funkcję GetColumnInfo, z rekordu CCustomWindowsFile użytkownika w pliku CustomRS.h i zastąp go definicją własnej GetColumnInfo funkcji:

////////////////////////////////////////////////////////////////////////
// CustomRS.H
class CCustomWindowsFile
{
public:
   DWORD dwBookmark;
   static const int iSize = 256;
   TCHAR szCommand[iSize];
   TCHAR szText[iSize];
   TCHAR szCommand2[iSize];
   TCHAR szText2[iSize];

   static ATLCOLUMNINFO* GetColumnInfo(void* pThis, ULONG* pcCols);
   bool operator==(const CCustomWindowsFile& am)
   {
      return (lstrcmpi(szCommand, am.szCommand) == 0);
   }
};

Następnie zaimplementuj GetColumnInfo funkcję w RS.cpp niestandardowych, jak pokazano w poniższym kodzie.

GetColumnInfo Najpierw sprawdza, czy właściwość DBPROP_BOOKMARKS OLE DB jest ustawiona. Aby uzyskać właściwość, GetColumnInfo użyj wskaźnika (pRowset) do obiektu zestawu wierszy. Wskaźnik pThis reprezentuje klasę, która utworzyła zestaw wierszy, czyli klasę, w której jest przechowywana mapa właściwości. GetColumnInfo typecasts pThis wskaźnik do RCustomRowset wskaźnika.

Aby sprawdzić, czy właściwość DBPROP_BOOKMARKS jest używana, GetColumnInfo używa interfejsu IRowsetInfo , który można uzyskać, wywołując QueryInterfacepRowset interfejs. Alternatywnie możesz użyć metody ATL CComQIPtr .

////////////////////////////////////////////////////////////////////
// CustomRS.cpp
ATLCOLUMNINFO* CCustomWindowsFile::GetColumnInfo(void* pThis, ULONG* pcCols)
{
   static ATLCOLUMNINFO _rgColumns[5];
   ULONG ulCols = 0;

   // Check the property flag for bookmarks; if it is set, set the zero
   // ordinal entry in the column map with the bookmark information.
   CCustomRowset* pRowset = (CCustomRowset*) pThis;
   CComQIPtr<IRowsetInfo, &IID_IRowsetInfo> spRowsetProps = pRowset;

   CDBPropIDSet set(DBPROPSET_ROWSET);
   set.AddPropertyID(DBPROP_BOOKMARKS);
   DBPROPSET* pPropSet = NULL;
   ULONG ulPropSet = 0;
   HRESULT hr;

   if (spRowsetProps)
      hr = spRowsetProps->GetProperties(1, &set, &ulPropSet, &pPropSet);

   if (pPropSet)
   {
      CComVariant var = pPropSet->rgProperties[0].vValue;
      CoTaskMemFree(pPropSet->rgProperties);
      CoTaskMemFree(pPropSet);

      if (SUCCEEDED(hr) && (var.boolVal == VARIANT_TRUE))
      {
         ADD_COLUMN_ENTRY_EX(ulCols, OLESTR("Bookmark"), 0, sizeof(DWORD),
         DBTYPE_BYTES, 0, 0, GUID_NULL, CCustomWindowsFile, dwBookmark,
         DBCOLUMNFLAGS_ISBOOKMARK)
         ulCols++;
      }
   }

   // Next, set the other columns up.
   ADD_COLUMN_ENTRY(ulCols, OLESTR("Command"), 1, 256, DBTYPE_STR, 0xFF, 0xFF,
      GUID_NULL, CCustomWindowsFile, szCommand)
   ulCols++;
   ADD_COLUMN_ENTRY(ulCols, OLESTR("Text"), 2, 256, DBTYPE_STR, 0xFF, 0xFF,
      GUID_NULL, CCustomWindowsFile, szText)
   ulCols++;

   ADD_COLUMN_ENTRY(ulCols, OLESTR("Command2"), 3, 256, DBTYPE_STR, 0xFF, 0xFF,
      GUID_NULL, CCustomWindowsFile, szCommand2)
   ulCols++;
   ADD_COLUMN_ENTRY(ulCols, OLESTR("Text2"), 4, 256, DBTYPE_STR, 0xFF, 0xFF,
      GUID_NULL, CCustomWindowsFile, szText2)
   ulCols++;

   if (pcCols != NULL)
      *pcCols = ulCols;

   return _rgColumns;
}

W tym przykładzie użyto tablicy statycznej do przechowywania informacji o kolumnie. Jeśli użytkownik nie chce, aby kolumna zakładki nie została wykorzystana, jeden wpis w tablicy jest nieużywany. Aby obsłużyć te informacje, należy utworzyć dwa makra tablicowe: ADD_COLUMN_ENTRY i ADD_COLUMN_ENTRY_EX. ADD_COLUMN_ENTRY_EX pobiera dodatkowy parametr , flagsktóry jest potrzebny w przypadku wyznaczenia kolumny zakładki.

////////////////////////////////////////////////////////////////////////
// CustomRS.h

#define ADD_COLUMN_ENTRY(ulCols, name, ordinal, colSize, type, precision, scale, guid, dataClass, member) \
   _rgColumns[ulCols].pwszName = (LPOLESTR)name; \
   _rgColumns[ulCols].pTypeInfo = (ITypeInfo*)NULL; \
   _rgColumns[ulCols].iOrdinal = (ULONG)ordinal; \
   _rgColumns[ulCols].dwFlags = 0; \
   _rgColumns[ulCols].ulColumnSize = (ULONG)colSize; \
   _rgColumns[ulCols].wType = (DBTYPE)type; \
   _rgColumns[ulCols].bPrecision = (BYTE)precision; \
   _rgColumns[ulCols].bScale = (BYTE)scale; \
   _rgColumns[ulCols].cbOffset = offsetof(dataClass, member);

#define ADD_COLUMN_ENTRY_EX(ulCols, name, ordinal, colSize, type, precision, scale, guid, dataClass, member, flags) \
   _rgColumns[ulCols].pwszName = (LPOLESTR)name; \
   _rgColumns[ulCols].pTypeInfo = (ITypeInfo*)NULL; \
   _rgColumns[ulCols].iOrdinal = (ULONG)ordinal; \
   _rgColumns[ulCols].dwFlags = flags; \
   _rgColumns[ulCols].ulColumnSize = (ULONG)colSize; \
   _rgColumns[ulCols].wType = (DBTYPE)type; \
   _rgColumns[ulCols].bPrecision = (BYTE)precision; \
   _rgColumns[ulCols].bScale = (BYTE)scale; \
   _rgColumns[ulCols].cbOffset = offsetof(dataClass, member); \
   memset(&(_rgColumns[ulCols].columnid), 0, sizeof(DBID)); \
   _rgColumns[ulCols].columnid.uName.pwszName = (LPOLESTR)name;

GetColumnInfo W funkcji makro zakładki jest używane w następujący sposób:

ADD_COLUMN_ENTRY_EX(ulCols, OLESTR("Bookmark"), 0, sizeof(DWORD),
   DBTYPE_BYTES, 0, 0, GUID_NULL, CAgentMan, dwBookmark,
   DBCOLUMNFLAGS_ISBOOKMARK)

Teraz możesz skompilować i uruchomić rozszerzonego dostawcę. Aby przetestować dostawcę, zmodyfikuj użytkownika testowego zgodnie z opisem w temacie Implementowanie prostego konsumenta. Uruchom użytkownika testowego z dostawcą i sprawdź, czy użytkownik testowy pobiera odpowiednie ciągi od dostawcy.

Zobacz też

Udoskonalanie prostego dostawcy tylko do odczytu