Sdílet prostřednictvím


Podpora zprostředkovatele pro záložky

Příklad v tomto tématu přidá IRowsetLocate rozhraní do CCustomRowset třídy. V téměř všech případech začnete přidáním rozhraní do existujícího objektu COM. Pak ho můžete otestovat přidáním dalších volání ze šablon příjemců. Příklad ukazuje, jak:

  • Přidejte rozhraní k poskytovateli.

  • Dynamicky určete sloupce, které se mají vrátit příjemci.

  • Přidejte podporu záložek.

Rozhraní IRowsetLocate dědí z IRowset rozhraní. Chcete-li přidat IRowsetLocate rozhraní, dědí CCustomRowset z IRowsetLocateImpl.

IRowsetLocate Přidání rozhraní se trochu liší od většiny rozhraní. Chcete-li vytvořit řádek VTABLEs, šablony zprostředkovatele OLE DB mají parametr šablony pro zpracování odvozeného rozhraní. Nový seznam dědičnosti ukazuje následující kód:

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

// CCustomRowset
class CCustomRowset : public CRowsetImpl< CCustomRowset,
      CTextData, CCustomCommand, CAtlArray<CTextData>,
      CSimpleRow,
          IRowsetLocateImpl<CCustomRowset, IRowsetLocate>>

Všechny přidané čtvrté, páté a šesté parametry. Tento příklad používá výchozí hodnoty pro čtvrtý a pátý parametr, ale jako IRowsetLocateImpl šestý parametr. IRowsetLocateImpl je třída šablony OLE DB, která přebírá dva parametry šablony: tyto připojují IRowsetLocate rozhraní ke CCustomRowset třídě. Pokud chcete přidat většinu rozhraní, můžete tento krok přeskočit a přejít na další. IRowsetLocate IRowsetScroll Tímto způsobem je potřeba zpracovat pouze rozhraní.

Pak musíte říct CCustomRowset , aby volal QueryInterface IRowsetLocate pro rozhraní. Přidejte čáru COM_INTERFACE_ENTRY(IRowsetLocate) do mapy. Mapa rozhraní by CCustomRowset se měla zobrazit, jak je znázorněno v následujícím kódu:

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

typedef CRowsetImpl< CCustomRowset, CTextData, CCustomCommand, CAtlArray<CTextData>, CSimpleRow, IRowsetLocateImpl<CCustomRowset, IRowsetLocate>> _RowsetBaseClass;

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

Musíte také zavěsit mapu do CRowsetImpl třídy. Přidejte do COM_INTERFACE_ENTRY_CHAIN makra pro připojení k mapě CRowsetImpl . Vytvořte také typedef, RowsetBaseClass který se skládá z informací o dědičnosti. Tento typovýef je libovolný a lze jej ignorovat.

Nakonec zařizte IColumnsInfo::GetColumnsInfo hovor. Obvykle byste k tomu použili PROVIDER_COLUMN_ENTRY makra. Spotřebitel ale může chtít používat záložky. V závislosti na tom, jestli příjemce požádá o záložku, musíte být schopni změnit sloupce, které poskytovatel vrátí.

Pokud chcete volání zpracovat IColumnsInfo::GetColumnsInfo , odstraňte PROVIDER_COLUMN mapování ve CTextData třídě. Makro PROVIDER_COLUMN_MAP definuje funkci GetColumnInfo. Definujte vlastní GetColumnInfo funkci. Deklarace funkce by měla vypadat takto:

////////////////////////////////////////////////////////////////////////
// CustomRS.H

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

Pak implementujte GetColumnInfo funkci v souboru CustomRS.cpp následujícím způsobem:

////////////////////////////////////////////////////////////////////
// CustomRS.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(CCustomCommand* pThis,
     ULONG* pcCols)
{
   return CommonGetColInfo<ICommandProperties>(pThis->GetUnknown(),
        pcCols);
}

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

GetColumnInfonejprve zkontroluje, zda je nastavena vlastnost.DBPROP_IRowsetLocate OLE DB má vlastnosti pro každé volitelné rozhraní mimo objekt sady řádků. Pokud chce příjemce použít jedno z těchto volitelných rozhraní, nastaví vlastnost na true. Zprostředkovatel pak může tuto vlastnost zkontrolovat a na základě ní provést zvláštní akci.

V implementaci získáte vlastnost pomocí ukazatele na objekt příkazu. Ukazatel pThis představuje sadu řádků nebo třídu příkazů. Protože tady používáte šablony, musíte ho předat jako void ukazatel nebo kód se nekompiluje.

Zadejte statické pole pro uložení informací o sloupci. Pokud příjemce nechce sloupec záložky, položka v poli je nevyužitá. Toto pole můžete dynamicky přidělit, ale musíte ho správně zničit. Tento příklad definuje a používá makra ADD_COLUMN_ENTRY a ADD_COLUMN_ENTRY_EX k vložení informací do pole. Makra můžete přidat do vlastního rs. Soubor H, jak je znázorněno v následujícím kódu:

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

Pokud chcete otestovat kód v příjemci, musíte v obslužné rutině OnRun provést několik změn. První změnou funkce je, že přidáte kód pro přidání vlastnosti do sady vlastností. Kód nastaví DBPROP_IRowsetLocate vlastnost na true, čímž zprostředkovateli říká, že chcete sloupec záložky. Kód OnRun obslužné rutiny by se měl zobrazit takto:

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

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

   if (source.Open("Custom.Custom.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);
}

Smyčka while obsahuje kód pro volání Compare metody v IRowsetLocate rozhraní. Kód, který jste měli mít, by měl vždy projít, protože porovnáváte úplně stejné záložky. Uložte také jednu záložku do dočasné proměnné, abyste ji mohli použít po while dokončení smyčky pro volání MoveToBookmark funkce v šablonách příjemců. Funkce MoveToBookmark volá metodu GetRowsAt v IRowsetLocate.

Musíte také aktualizovat záznam uživatele v příjemci. Přidejte do třídy položku pro zpracování záložky a položky v 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 aktualizaci kódu byste měli být schopni sestavit a spustit zprostředkovatele pomocí IRowsetLocate rozhraní.

Viz také

Pokročilé techniky zprostředkování