5.6.2 Saving a Document

To save a document, a client application should do the following:

Save the data for the document in the document's file.

For each object in the document, call the OleSaveToStream function (which in turn, calls the client application's Put callback function).

After all objects have been saved, call the OleSavedClientDoc function to inform the client DLL that all objects have been saved.

A client application can call the OleQuerySize function to determine the size of the buffer required to store an object before calling OleSaveToStream.

Note When saving objects in a container document, be careful not to save any presentation formats other than those needed to recreate the object—file size can grow dramatically saving needless formats. When saving embedded objects, only the Native data and the presentation data need to be stored in the container document. For linked objects, only the OwnerLink and presentation formats need to be stored.

CLIDEMO.EXE initiates the saving of a document by calling the SaveFile function. SaveFile displays a dialog box asking the user to save changes. If the user chooses to save the document, then SaveFile calls the WriteToFile function, which in turn calls ObjWrite. ObjWrite makes the necessary call to OleSaveToStream. After the data has been saved, SaveFile calls OleSavedClientDoc to notify the client DLL of the status.

/*

* SaveFile()

*

* Save a compound document file. If the file is untitled, ask the

* user for a name and save the document to that file.

*/

static BOOL SaveFile // ENTRY:

(PSTR pFileName, // file to save document to

LHCLIENTDOC lhcDoc, // OLE document handle

LPAPPSTREAM lpStream) // pointer to app. stream

// struct

{ // LOCAL:

char szNewFile[CBPATHMAX]; // New file name strings

char szOemFileName[2*CBPATHMAX];

static char szUntitled[CBMESSAGEMAX] = "";

HANDLE fh; // file handle

*szNewFile = NULL;

if (!(*szUntitled))

LoadString(hInst, IDS_UNTITLED, (LPSTR)szUntitled,CBMESSAGEMAX);

if (!lstrcmp(szUntitled, pFileName)) // get filename for the

// untitled case

{

if (!OfnGetName(hwndFrame, szNewFile, IDM_SAVEAS))

return FALSE; // CANCEL return

lstrcpy(pFileName,szNewFile);

SetTitle(pFileName);

}

AnsiToOem(pFileName, szOemFileName);

if ((fh =_lcreat((LPSTR)szOemFileName, 0)) <= 0)

{

ErrorMessage(E_INVALID_FILENAME);

return FALSE; // ERROR return

}

lpStream->fh = fh;

// save file on disk

if (!WriteToFile(lpStream))

{

_lclose(fh);

ErrorMessage(E_FAILED_TO_SAVE_FILE);

return FALSE; // ERROR return

}

_lclose(fh);

if (Error(OleSavedClientDoc(lhcDoc)))

{

ErrorMessage(W_FAILED_TO_NOTIFY);

return FALSE; // ERROR return

}

Dirty(DOC_CLEAN);

return TRUE; // SUCCESS return

}

/*

* WriteToFile()

*

* Write current document to a file.

*

* returns BOOL - TRUE if file successfully written

*/

BOOL FAR WriteToFile // ENTRY:

(LPAPPSTREAM lpStream) // application stream pointer

{ // LOCAL:

int iObjectsWritten=0; // counter of objects written

// to file

APPITEMPTR pItem; // application Item pointer

UpdateFromOpenServers();

_llseek(lpStream->fh, 0L, 0);

Hourglass(TRUE);

if (_lwrite(lpStream->fh, (LPSTR)&iObjects,

sizeof(int)) < sizeof(int))

goto Error;

for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))

{

if (!ObjWrite(lpStream, pItem))

goto Error;

iObjectsWritten++;

}

if (iObjectsWritten != iObjects)

goto Error;

Dirty(DOC_CLEAN);

Hourglass(FALSE);

return(TRUE); // SUCCESS return

Error: // ERROR Tag

Hourglass(FALSE);

return(FALSE); // ERROR return

}

/*

* ObjWrite()

*

* This function writes an object to the specified

* file. The file pointer will be advanced past the end of

* the written object.

* Returns BOOL - TRUE if object written successfully

*/

BOOL FAR ObjWrite // ENTRY:

(LPAPPSTREAM lpStream, // application stream pointer

APPITEMPTR pItem) // application item pointer

{ // LOCAL:

POINT pt; // center of rec point

RECT rc; // bounding rectangle

int cbTmp;

char szTmp[PROTOCOL_STRLEN];// protocol string

cbTmp = CBOBJNAMEMAX;

OleQueryName(pItem->lpObject, szTmp, &cbTmp);

if (_lwrite(lpStream->fh, szTmp, CBOBJNAMEMAX) < CBOBJNAMEMAX )

return FALSE;

if (pItem->otObject == OT_STATIC)

wsprintf(szTmp, "%-15s", STATICP);

else

wsprintf(szTmp, "%-15s", STDFILEEDITING);

if (_lwrite(lpStream->fh, szTmp,PROTOCOL_STRLEN) < PROTOCOL_STRLEN )

return FALSE;

if (Error(OleSaveToStream(pItem->lpObject,

(LPOLESTREAM)&(lpStream->olestream))))

return FALSE;

GetClientRect(pItem->hwnd, (LPRECT)&rc);

pt = *(LPPOINT)&rc;

ClientToScreen(pItem->hwnd, (LPPOINT)&pt);

ScreenToClient(hwndFrame, (LPPOINT)&pt);

OffsetRect(&rc, pt.x - rc.left - GetSystemMetrics(SM_CXFRAME),

pt.y - rc.top - GetSystemMetrics(SM_CYFRAME));

if (_lwrite(lpStream->fh, (LPSTR)&rc, sizeof(RECT)) < sizeof(RECT)

|| _lwrite(lpStream->fh, (LPSTR)&(pItem->otObject),

sizeof(long)) < sizeof(long))

return FALSE;

return TRUE; // SUCCESS return

}