IPaper::Load
次の C++ サンプル コードは、ストレージ内の既存のストリームを開き、 で新しいペーパー プロパティを読み取り、それらを COPaper の現在の値として設定する方法を示しています。
Paper.cpp の IPaper::Load メソッドを次に示します。
STDMETHODIMP COPaper::CImpIPaper::Load(
SHORT nLockKey,
IStorage* pIStorage)
{
HRESULT hr = E_FAIL;
IStream* pIStream;
INKDATA* paInkData;
ULONG ulToRead, ulReadIn;
LONG lNewArraySize;
PAPER_PROPERTIES NewProps;
if (OwnThis())
{
if (m_bLocked && m_cLockKey == nLockKey && NULL != pIStorage)
{
// Open the "PAPERDATA" stream where the paper data is stored.
hr = pIStorage->OpenStream(
STREAM_PAPERDATA_USTR,
0,
STGM_READ | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
0,
&pIStream);
if (SUCCEEDED(hr))
{
// Obtained paper data stream. Read the Paper Properties.
ulToRead = sizeof(PAPER_PROPERTIES);
hr = pIStream->Read(
&NewProps,
ulToRead,
&ulReadIn);
if (SUCCEEDED(hr) && ulToRead != ulReadIn)
hr = E_FAIL;
if (SUCCEEDED(hr))
{
// Handle the different versions of ink data format.
switch (NewProps.lInkDataVersion)
{
case INKDATA_VERSION10:
// Allocate an ample-sized ink data array.
lNewArraySize = NewProps.lInkArraySize +
INKDATA_ALLOC;
paInkData = new INKDATA[(LONG) lNewArraySize];
if (NULL != paInkData)
{
// Delete the old ink data array.
delete [] m_paInkData;
// Assign the new array.
m_paInkData = paInkData;
m_lInkDataMax = lNewArraySize;
// Read the complete array of Ink Data.
ulToRead = NewProps.lInkArraySize * sizeof(INKDATA);
hr = pIStream->Read(m_paInkData,
ulToRead, &ulReadIn);
if (SUCCEEDED(hr) && ulToRead != ulReadIn)
hr = E_FAIL;
if (SUCCEEDED(hr))
{
// Set COPaper to use the new PAPER_PROPERTIES
// data.
m_lInkDataEnd = NewProps.lInkArraySize-1;
m_crWinColor = NewProps.crWinColor;
m_WinRect.right = NewProps.WinRect.right;
m_WinRect.bottom = NewProps.WinRect.bottom;
// Copy the new properties into current
// properties.
memcpy(
&m_PaperProperties,
&NewProps,
sizeof(PAPER_PROPERTIES));
}
}
else
hr = E_OUTOFMEMORY;
break;
default:
hr = E_FAIL; // Bad version.
break;
}
}
// Release the stream.
pIStream->Release();
}
}
UnOwnThis();
}
// Notify other connected clients that Paper is now loaded.
// If Paper not loaded, then erase to a safe, empty ink data
// array.
if (SUCCEEDED(hr))
m_pBackObj->NotifySinks(PAPER_EVENT_LOADED, 0, 0, 0, 0);
else
Erase(nLockKey);
return hr;
}
次に、 IStorage::OpenStream メソッドを呼び出して、ストレージ内の "PAPERDATA" という名前の既存のストリームを開きます。 アクセス モード フラグは、読み取り専用、直接、および非共有排他アクセス用です。 ストリームを開くと、 IStream::Read メソッドが呼び出され、PAPER_PROPERTIES構造体が読み取られます。 実際に読み取られた量が要求された量と等しくない場合は、読み込み操作が中止され、E_FAILが返されます。 新しく読み取られたPAPER_PROPERTIESの形式バージョンが認識されない場合、読み込み操作は中止され、 Load はE_FAILを返します。
有効なインク データ形式バージョンでは、読み取られたPAPER_PROPERTIESの新しいインク データ配列のサイズを使用して、必要なサイズの新しいインク データ配列を割り当てます。 既存のインク データが削除され、そのデータが失われます。 このデータが重要な場合は、 Load が呼び出される前に保存されている必要があります。 新しい配列が割り当てられた後、 IStream::Read が再度呼び出され、ストリームから配列にデータが読み込まれます。 この呼び出しが成功すると、新しく読み取られた用紙プロパティの値が COPaper の現在の値として採用されます。
この読み込み操作中に、読み取られた新しいプロパティを保持するために、一時的なPAPER_PROPERTIES構造体 NewProps が使用されました。 読み込みですべてが成功した場合、NewProps は PAPER_PROPERTIES 構造体にコピー m_PaperProperties。 以前と同様に、読み込みが完了し、 IStream が不要になった後、 IStream ポインターが解放されます。
読み込みの最後にエラーが発生した場合、インク データ配列は破損したデータを含んでいる可能性があるため、消去されます。
Load の最後にエラーがない場合は、クライアント IPaperSink::Loaded メソッドが COPaper 内部 NotifySinks メソッドで呼び出され、読み込み操作が完了したことをクライアントに通知します。 これは、この新しく読み込まれたインク データを表示する必要があるため、クライアントにとって重要な通知です。 この通知では、COPaper で接続可能なオブジェクト機能を大幅に使用します。