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 结束时没有错误,则会在 COPaper 内部 NotifySinks 方法中调用客户端 IPaperSink::Loaded 方法,以通知客户端加载操作已完成。 这是客户端的重要通知,因为它必须显示此新加载的墨迹数据。 此通知大量使用 COPaper 中的可连接对象功能。