Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Der Hauptfokus in diesem Beispielcode ist, wie COPaper seine Papierdaten in Verbunddateien laden und speichern kann. Die IPaper, Loadund Implementierungen der Save-Methoden werden ausführlich erläutert.
Es folgt die IPaper::Save-Methode aus Paper.cpp.
STDMETHODIMP COPaper::CImpIPaper::Save(
SHORT nLockKey,
IStorage* pIStorage)
{
HRESULT hr = E_FAIL;
IStream* pIStream;
ULONG ulToWrite, ulWritten;
if (OwnThis())
{
if (m_bLocked && m_cLockKey == nLockKey && NULL != pIStorage)
{
// Use the COM service to mark this compound file as one
// that is handled by our server component, DllPaper.
WriteClassStg(pIStorage, CLSID_DllPaper);
// Use the COM Service to write user-readable clipboard
// format into the compound file.
WriteFmtUserTypeStg(pIStorage, m_ClipBdFmt,
TEXT(CLIPBDFMT_STR));
// Create the stream to be used for the actual paper data.
// Call it "PAPERDATA".
hr = pIStorage->CreateStream(
STREAM_PAPERDATA_USTR,
STGM_CREATE | STGM_WRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
0,
0,
&pIStream);
if (SUCCEEDED(hr))
{
// Obtained a stream. Write data to it.
// First, write PAPER_PROPERTIES structure.
m_PaperProperties.lInkArraySize = m_lInkDataEnd+1;
m_PaperProperties.crWinColor = m_crWinColor;
m_PaperProperties.WinRect.right = m_WinRect.right;
m_PaperProperties.WinRect.bottom = m_WinRect.bottom;
ulToWrite = sizeof(PAPER_PROPERTIES);
hr = pIStream->Write(&m_Paper_Properties, ulToWrite,
&ulWritten);
if (SUCCEEDED(hr) && ulToWrite != ulWritten)
hr = STG_E_CANTSAVE;
if (SUCCEEDED(hr))
{
// Now, write the complete array of Ink Data.
ulToWrite = m_PaperProperties.lInkArraySize *
sizeof(INKDATA);
hr = pIStream->Write(m_paInkData, ulToWrite, &ulWritten);
if (SUCCEEDED(hr) && ulToWrite != ulWritten)
hr = STG_E_CANTSAVE;
}
// Release the stream.
pIStream->Release();
}
}
UnOwnThis();
}
// Notify all other connected clients that Paper is now saved.
if (SUCCEEDED(hr))
m_pBackObj->NotifySinks(PAPER_EVENT_SAVED, 0, 0, 0, 0);
return hr;
}
In dieser Client- und Serverbeziehung erstellt COPaper nicht die Verbunddatei, die zum Speichern von Papierdaten verwendet wird. Für die Methoden Save und Load übergibt der Client einen IStorage- Schnittstellenzeiger für eine vorhandene Verbunddatei. Anschließend wird die IStorage- verwendet, um Daten in dieser Verbunddatei zu schreiben und zu lesen. In IPaper::Save oben werden mehrere Datentypen gespeichert.
Die CLSID für DllPaper, CLSID_DllPaper, wird serialisiert und in einem speziellen COM-gesteuerten Datenstrom innerhalb des Speicherobjekts namens "\001CompObj" gespeichert. Die WriteClassStg--Dienstfunktion führt diesen Speicher aus. Diese gespeicherten CLSID-Daten können verwendet werden, um den Speicherinhalt der dllPaper-Komponente zuzuordnen, die erstellt und interpretiert werden kann. In diesem Beispiel wird der Stammspeicher von StoClienübergeben und somit die gesamte Verbunddatei der DllPaper-Komponente zugeordnet. Diese CLSID-Daten können später mit einem Aufruf der ReadClassStg--Dienstfunktion abgerufen werden.
Da DllPaper mit bearbeitbaren Daten arbeitet, ist es auch geeignet, ein Zwischenablageformat im Speicher aufzuzeichnen. Die WriteFmtUserTypeStg-Dienstfunktion wird aufgerufen, um sowohl eine Bezeichnung des Zwischenablageformats als auch einen benutzerdefinierten Namen für das Format zu speichern. Der benutzerlesbare Name ist für die GUI-Anzeige in Auswahllisten vorgesehen. Der oben übergebene Name verwendet ein Makro, CLIPBDFMT_STR, das in Paper.h als "DllPaper 1.0" definiert ist. Diese gespeicherten Zwischenablagedaten können später mit einem Aufruf der Dienstfunktion ReadFmtUserTypeStgabgerufen werden. Diese Funktion gibt einen Zeichenfolgenwert zurück, der mithilfe des Aufgabenspeicher-Allocators zugewiesen wird. Der Aufrufer ist für das Freigeben der Zeichenfolge verantwortlich.
Speichern erstellt als Nächstes einen Datenstrom im Speicher für die COPaper-Papierdaten. Der Datenstrom heißt "PAPERDATA" und wird mithilfe des STREAM_PAPERDATA_USTR Makros übergeben. Die IStorage::CreateStream-Methode erfordert, dass diese Zeichenfolge in Unicode enthalten ist. Da die Zeichenfolge zur Kompilierungszeit behoben ist, wird das Makro in Paper.h als Unicode definiert.
#define STREAM_PAPERDATA_USTR L"PAPERDATA"
Die "L" vor der Zeichenfolge, die LONG angibt, erreicht dies.
Die CreateStream--Methode erstellt und öffnet einen Datenstrom innerhalb des angegebenen Speichers. Ein IStream- Schnittstellenzeiger für den neuen Datenstrom wird in einer Zeigervariable der Aufruferschnittstelle übergeben. AddRef wird für diesen Schnittstellenzeiger innerhalb CreateStream-aufgerufen, und der Aufrufer muss diesen Zeiger nach der Verwendung freigeben. Die CreateStream-Methode wird wie folgt an zahlreiche Zugriffsmodusflags übergeben.
STGM_CREATE | STGM_WRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE
STGM_CREATE erstellt einen neuen Datenstrom oder überschreibt einen vorhandenen mit demselben Namen. STGM_WRITE öffnet den Datenstrom mit Schreibberechtigung. STGM_DIRECT öffnet den Datenstrom für den direkten Zugriff, im Gegensatz zu Transaktionen. STGM_SHARE_EXCLUSIVE öffnet die Datei für die exklusive, nicht gemeinsam genutzte Verwendung durch den Aufrufer.
Nachdem der PAPERDATA-Datenstrom erfolgreich erstellt wurde, wird die IStream--Schnittstelle verwendet, um in den Datenstrom zu schreiben. Die IStream::Write-Methode wird verwendet, um zuerst den Inhalt der PAPER_PROPERTIES Struktur zu speichern. Dies ist im Wesentlichen ein Eigenschaftenheader am Anfang des Datenstroms. Da die Versionsnummer das erste Element in der Datei ist, kann sie unabhängig gelesen werden, um zu bestimmen, wie die folgenden Daten behandelt werden. Wenn die tatsächlich geschriebene Datenmenge nicht der angeforderten Menge entspricht, wird die Save-Methode abgebrochen und gibt STG_E_CANTSAVE zurück.
Das Speichern des gesamten Arrays von Freihanddaten in den Datenstrom ist einfach.
// Now write the complete array of Ink Data.
ulToWrite = m_PaperProperties.lInkArraySize * sizeof(INKDATA);
hr = pIStream->Write(m_paInkData, ulToWrite, &ulWritten);
if (SUCCEEDED(hr) && ulToWrite != ulWritten)
hr = STG_E_CANTSAVE;
Da die IStream::Write-Methode auf einem Bytearray ausgeführt wird, wird die Anzahl der Bytes gespeicherter Freihanddaten im Array berechnet und der Schreibvorgang beginnt am Anfang des Arrays. Wenn die tatsächlich geschriebene Datenmenge nicht der angeforderten Menge entspricht, gibt die Save-Methode STG_E_CANTSAVE zurück.
Nachdem der Datenstrom geschrieben wurde, gibt die IPaper::Save-Methode den IStream- Zeiger frei, den er verwendet hat.
Die Save-Methode ruft auch den Client IPaperSink- (in der internen COPaper NotifySinks-Methode) auf, um den Client darüber zu benachrichtigen, dass der Speichervorgang abgeschlossen ist. An diesem Punkt gibt die Save-Methode an den aufrufenden Client zurück, wodurch in der Regel der IStorage Zeiger freigegeben wird.