IPaper::Load
В следующем примере кода C++ показано, как открыть существующий поток в хранилище, считывать новые свойства бумаги в , а затем задавать их в качестве текущих значений для COPaper.
Ниже приведен метод IPaper::Load из Paper.cpp.
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 возникает ошибка, массив данных рукописного ввода удаляется, так как он может содержать поврежденные данные.
Если в конце load ошибки нет, вызывается клиентский метод IPaperSink::Loaded во внутреннем методе COPaper NotifySinks, чтобы уведомить клиента о завершении операции загрузки. Это важное уведомление для клиента, так как оно должно отображать новые загруженные данные рукописного ввода. Это уведомление обеспечивает значительное использование возможностей подключаемого объекта в COPaper.