Udostępnij za pośrednictwem


Obsługa dostawców dla zakładek

W przykładzie w tym temacie dodano IRowsetLocate interfejsu CMyProviderRowset klasy.W prawie wszystkich przypadkach możesz uruchomić przez dodanie interfejsu do istniejącego obiektu COM.Można następnie sprawdzić dodając więcej połączeń z szablonów konsumenta.W przykładzie pokazano, jak:

  • Dodawanie interfejsu do dostawcy.

  • Dynamiczne określenie kolumn, aby powrócić do konsumenta.

  • Dodaj obsługę zakładek.

Interfejs IRowsetLocate dziedziczy z interfejsu IRowset.Aby dodać IRowsetLocate interfejs, dziedziczą CMyProviderRowset z IRowsetLocateImpl.

Dodawanie IRowsetLocate interfejs nieco różni się od większości interfejsów.Aby wprowadzić wiersz tablic metod wirtualnych w górę, OLE DB dostawca szablonów mieć parametr szablonu do obsługi interfejsu pochodnego.Poniższy kod przedstawia nową listę dziedziczenia:

////////////////////////////////////////////////////////////////////////
// MyProviderRS.h

// CMyProviderRowset
class CMyProviderRowset : public CRowsetImpl< CMyProviderRowset, 
      CTextData, CMyProviderCommand, CAtlArray<CTextData>, 
      CSimpleRow, 
          IRowsetLocateImpl<CMyProviderRowset, IRowsetLocate> >

Czwartej, piątej i szóstej parametrami wszystkie dodane.W tym przykładzie użyto wartości domyślne dla czwartego i piątego parametrów i określić IRowsetLocateImpl jako szósty parametr.IRowsetLocateImpljest to klasa szablon OLE DB, który przyjmuje dwa parametry szablonu: te podłączyć IRowsetLocate interfejs do CMyProviderRowset klasy.Aby dodać większość interfejsów, możesz pominąć ten krok i przejść do następnej.Tylko IRowsetLocate i IRowsetScroll interfejsy muszą być traktowane w ten sposób.

Następnie należy wskazać programowi CMyProviderRowset do wywołania QueryInterface dla IRowsetLocate interfejsu.Dodaj wiersz COM_INTERFACE_ENTRY(IRowsetLocate) do mapy.Mapa interfejs dla CMyProviderRowset powinien pojawić się jak pokazano w poniższym kodzie:

////////////////////////////////////////////////////////////////////////
// MyProviderRS.h

typedef CRowsetImpl< CMyProviderRowset, CTextData, CMyProviderCommand, CAtlArray<CTextData>, CSimpleRow, IRowsetLocateImpl<CMyProviderRowset, IRowsetLocate> > _RowsetBaseClass;

BEGIN_COM_MAP(CMyProviderRowset)
   COM_INTERFACE_ENTRY(IRowsetLocate)
   COM_INTERFACE_ENTRY_CHAIN(_RowsetBaseClass)
END_COM_MAP()

Trzeba także podłączyć mapę do CRowsetImpl klasy.Dodaj w makrze COM_INTERFACE_ENTRY_CHAIN hak w CRowsetImpl mapy.Ponadto, tworzenie aliasów o nazwie RowsetBaseClass zawiera informacje o dziedziczeniu.Ten element typedef jest dowolna i można go zignorować.

Wreszcie, obsługi IColumnsInfo::GetColumnsInfo zadzwonić.W tym celu byłyby normalnie używane makra PROVIDER_COLUMN_ENTRY.Jednakże konsument może chcesz używać zakładek.Musi być w stanie zmienić kolumny, które dostawca zwraca w zależności od tego, czy konsument zwraca się do zakładki.

Do obsługi IColumnsInfo::GetColumnsInfo zadzwonić, usuwanie PROVIDER_COLUMN Mapa w CTextData klasy.Makro PROVIDER_COLUMN_MAP definiuje funkcję GetColumnInfo.Musisz zdefiniować własne GetColumnInfo funkcji.Deklaracja funkcji powinna wyglądać następująco:

////////////////////////////////////////////////////////////////////////
// MyProviderRS.H

class CTextData
{
   ...
     // NOTE: Be sure you removed the PROVIDER_COLUMN_MAP!
   static ATLCOLUMNINFO* GetColumnInfo(CMyProviderRowset* pThis, 
        ULONG* pcCols);
   static ATLCOLUMNINFO* GetColumnInfo(CMyProviderCommand* pThis, 
        ULONG* pcCols);
...
};

Następnie należy zaimplementować GetColumnInfo działają w pliku MyProviderRS.cpp w następujący sposób:

////////////////////////////////////////////////////////////////////
// MyProviderRS.cpp

template <class TInterface>
ATLCOLUMNINFO* CommonGetColInfo(IUnknown* pPropsUnk, ULONG* pcCols)
{
   static ATLCOLUMNINFO _rgColumns[5];
   ULONG ulCols = 0;

   CComQIPtr<TInterface> spProps = pPropsUnk;

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

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

   // Check the property flag for bookmarks, if it is set, set the 
// zero ordinal entry in the column map with the bookmark 
// information.

   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, CAgentMan, dwBookmark,       
                        DBCOLUMNFLAGS_ISBOOKMARK)
         ulCols++;
      }

   }


   // Next set the other columns up.
   ADD_COLUMN_ENTRY_EX(ulCols, OLESTR("Field1"), 1, 16, DBTYPE_STR, 
          0xFF, 0xFF, GUID_NULL, CTextData, szField1)
   ulCols++;
   ADD_COLUMN_ENTRY_EX(ulCols, OLESTR("Field2"), 2, 16, DBTYPE_STR,
       0xFF, 0xFF, GUID_NULL, CTextData, szField2)
   ulCols++;

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

   return _rgColumns;
}


ATLCOLUMNINFO* CTextData::GetColumnInfo(CMyProviderCommand* pThis, 
     ULONG* pcCols)
{
   return CommonGetColInfo<ICommandProperties>(pThis->GetUnknown(),
        pcCols);
}


ATLCOLUMNINFO* CAgentMan::GetColumnInfo(RUpdateRowset* pThis, ULONG* pcCols)
{
   return CommonGetColInfo<IRowsetInfo>(pThis->GetUnknown(), pcCols);
}

GetColumnInfopierwsze sprawdza, czy właściwość o nazwie DBPROP_IRowsetLocate jest ustawiona.OLE DB ma właściwości dla każdej z opcjonalnych interfejsów off obiektu zestawu wierszy.Jeśli konsument chce skorzystać z jednej z tych opcjonalnych interfejsów, ustawia właściwość na wartość true.Dostawca może następnie sprawdzić tę właściwość i podejmować żadnych specjalnych czynności na jej podstawie.

W danej implementacji pobrać właściwości za pomocą wskaźnika do obiektu command.pThis Wskaźnik reprezentuje klasę wierszy lub polecenia.Ponieważ tutaj użyć szablonów, musisz przekazać go jako void wskaźnik lub kod nie kompiluje się.

Określić statyczny tablicy musi zawierać informacje kolumny.Jeśli konsument nie chce kolumnę zakładki, marnuje się wpis w tablicy.Można dynamicznie przydzielić tej tablicy, ale trzeba upewnić się, zniszczyć ją poprawnie.W tym przykładzie definiuje i używa makra ADD_COLUMN_ENTRY i ADD_COLUMN_ENTRY_EX do wstawienia informacji do tablicy.Makra można dodać do pliku MyProviderRS.H, jak pokazano w poniższym kodzie:

////////////////////////////////////////////////////////////////////////
// MyProviderRS.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;

Aby przetestować kod w konsumenta, należy wprowadzić kilka zmian do OnRun obsługi.Pierwsza zmiana do funkcji jest dodać kod, aby dodać właściwości do zestawu właściwości.Zestawy kodów DBPROP_IRowsetLocate właściwości na wartość true, w ten sposób Narrator dostawca ma kolumnę zakładki.OnRun Kod obsługi powinna wyglądać następująco:

//////////////////////////////////////////////////////////////////////
// TestProv Consumer Application in TestProvDlg.cpp

void CTestProvDlg::OnRun() 
{
   CCommand<CAccessor<CProvider> > table;
   CDataSource source;
   CSession   session;

   if (source.Open("MyProvider.MyProvider.1", NULL, NULL, NULL, 
          NULL) != S_OK)
      return;

   if (session.Open(source) != S_OK)
      return;

   CDBPropSet propset(DBPROPSET_ROWSET);
   propset.AddProperty(DBPROP_IRowsetLocate, true);
   if (table.Open(session, _T("c:\\public\\testprf2\\myData.txt"), 
          &propset) != S_OK)
      return;

   CBookmark<4> tempBookmark;
   ULONG ulCount=0;
   while (table.MoveNext() == S_OK)
   {

      DBCOMPARE compare;
      if (ulCount == 2)
         tempBookmark = table.bookmark;
      HRESULT hr = table.Compare(table.dwBookmark, table.dwBookmark,
                 &compare);
      if (FAILED(hr))
         ATLTRACE(_T("Compare failed: 0x%X\n"), hr);
      else
         _ASSERTE(compare == DBCOMPARE_EQ);

      m_ctlString1.AddString(table.szField1);
      m_ctlString2.AddString(table.szField2);
      ulCount++;
   }

   table.MoveToBookmark(tempBookmark);
   m_ctlString1.AddString(table.szField1);
   m_ctlString2.AddString(table.szField2);
}

While pętli zawiera kod do wywoływania Compare metoda w IRowsetLocate interfejsu.Kod, który masz zawsze powinien przejść, ponieważ porównujesz dokładnie te same zakładki.Również, przechowywać jedną zakładkę w zmiennej tymczasowej, tak, aby można go było używać po czasie pętli wykończeń do wywoływania MoveToBookmark funkcji w szablonach konsumenta.MoveToBookmark Wywołania funkcji GetRowsAt metoda w IRowsetLocate.

Należy również zaktualizować rekord użytkownika w programie konsumenta.Dodaj wpis w klasie obsługi zakładki i wpis w COLUMN_MAP:

///////////////////////////////////////////////////////////////////////
// TestProvDlg.cpp

class CProvider
{
// Attributes
public:
   CBookmark<4>    bookmark;  // Add this line
   char   szCommand[16];
   char   szText[256];

   // Binding Maps
BEGIN_ACCESSOR_MAP(CProvider, 1)
   BEGIN_ACCESSOR(0, true)   // auto accessor
      BOOKMARK_ENTRY(bookmark)  // Add this line
      COLUMN_ENTRY(1, szField1)
      COLUMN_ENTRY(2, szField2)
   END_ACCESSOR()
END_ACCESSOR_MAP()
};

Po zaktualizowaniu kod można do budowania i wykonać dostawcy z IRowsetLocate interfejsu.

Zobacz też

Koncepcje

Zaawansowane techniki dostawcy