コンシューマーに返される列の動的な判断
PROVIDER_COLUMN_ENTRY マクロは通常、IColumnsInfo::GetColumnsInfo
呼び出しを処理します。 ただし、コンシューマーがブックマークの使用を選択する場合があるため、プロバイダーでは、コンシューマーがブックマークを要求しているかどうかに応じて、返された列を変更できる必要があります。
IColumnsInfo::GetColumnsInfo
呼び出しを処理するには、関数 GetColumnInfo
を定義する PROVIDER_COLUMN_MAP を CustomRS.h の CCustomWindowsFile
ユーザー レコードから削除し、それを独自の GetColumnInfo
関数の定義に置き換えます。
////////////////////////////////////////////////////////////////////////
// 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);
}
};
次に、下記のコードに示すように、CustomRS.cpp 内の GetColumnInfo
関数を実装します。
GetColumnInfo
は、まず OLE DB プロパティ DBPROP_BOOKMARKS
が設定されているかどうかを確認します。 プロパティを取得するために、GetColumnInfo
は行セット オブジェクトへのポインター (pRowset
) を使用します。 pThis
ポインターは、行セットを作成したクラスを表します。これは、プロパティ マップが格納されているクラスです。 GetColumnInfo
は、pThis
ポインターを RCustomRowset
ポインターに型キャストします。
DBPROP_BOOKMARKS
プロパティを確認するために、GetColumnInfo
は IRowsetInfo
インターフェイスを使用します。これは、pRowset
インターフェイスで QueryInterface
を呼び出すことによって取得できます。 代わりに、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;
}
この例では、列情報を格納する静的配列を使用します。 コンシューマーがブックマーク列を必要としない場合は、配列内の 1 つのエントリが不使用となります。 この情報を処理するには、2 つの配列マクロを作成します。ADD_COLUMN_ENTRY と ADD_COLUMN_ENTRY_EX です。 ADD_COLUMN_ENTRY_EX には、追加のパラメーター (フラグ) が必要です。これは、ブックマーク列を指定する場合に必要となります。
////////////////////////////////////////////////////////////////////////
// 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
関数では、ブックマーク マクロが次のように使用されます。
ADD_COLUMN_ENTRY_EX(ulCols, OLESTR("Bookmark"), 0, sizeof(DWORD),
DBTYPE_BYTES, 0, 0, GUID_NULL, CAgentMan, dwBookmark,
DBCOLUMNFLAGS_ISBOOKMARK)
これで、拡張されたプロバイダーをコンパイルして実行できるようになりました。 プロバイダーをテストするには、「単純なコンシューマーの実装」の説明に従って、テスト コンシューマーを変更します。 プロバイダーを使ってテスト コンシューマーを実行し、テスト コンシューマーがプロバイダーから適切な文字列を取得することを確認します。