This site is moving to The Zen Source Library
Please Update your bookmarks


Creating a stream and writing data to it

Now that we know how to open and create a DocFile, lets create a stream and save some data to it.

Step 1: Creating a Stream


      {Try to create the stream}
   Hr := RootStorage.CreateStream(  'MyStream',
                                    STGM_CREATE or STGM_READWRITE or
                                    STGM_DIRECT or STGM_SHARE_EXCLUSIVE,
                                    0,
                                    0,
                                    Stream
                                  );

As you can see CreateStream is a member function of IStorage. The STGM flags are the same as used with StgCreateDocFile. Dont forget to check the Hr result for success.

If successful this will create a stream called MyStream in the RootStorage.


Step 2: Write some data

Well lets first get some data to write! From this point on I'll be building a sample application that will demonstrate some of the more important DocFile concepts.

So create a new Delphi project in which you can test these examples.

For this first example drop a TMemo and a TButton on the form.


Control Caption Name
TMemo   mem_Text
TButton Save but_Save

What this simple application will do is save the text from the memo into a stream in the DocFile. Later on we'll read the data back from the stream.

Double click the button to start entering the OnClick code used to save the memo's text

There are as always a number of ways to accomplish anything in programming, I'll show you two methods here. There are probably quite a few more. Chose the method that best suits your needs.

Method 1:

Saving a string


   Stream.Write(  PChar(mem_Text.Text),
                  Length(  mem_Text.Text  ),
                  @iNumWritten
                );


      {Was all the data written?}
   if(  iNumWritten <> MemStream.Size  ) then
   begin
      MessageBeep(  -1  );
      ShowMessage(  'Not all of data was saved'  );
   end;

Here the text in the memo's Lines.Text property is used to get the text as a string.


Method 2: Using a TOleStream

This section origionally showed how to use a memory stream as a tempory stream before saving the data to the actual IStream. This method worked and was quite flexible... however there is a better way. There always is! In this case the better method is to use a TOleStream.
My thanks to Thaddy de Koning (thaddy@cyco.nl) for bringing this class to my attention.

TOleStream is defined in AxCtrls.pas. What it does is wrap a IStream and allow you to use the IStream just as you would any normal stream class (eg TStream, TMemoryStream, TFileStream etc..). This makes loading and saving data so much easier.

To use TOleStream you pass an open IStream as the only parameter to its constructor.
For example saving the text from a TMemo to a open IStream.


      {Create a memory OleStream}
   OleStream := TOleStream.Create(  Stream  );

      {Save the memo's text to the OleStream}
   mem_Text.Lines.SaveToStream(  OleStream  );

      {Finished with the OleStream}
   OleStream.Free;

I have noticed that TOleStream.Size does not work correctly for a TOleStream. It correctly returns the size of the stream, but changing the value has no effect at all! Use the normal API functions if you need to manualy resize an IStream.

The full source code (using method 2) follows, this is the procedure you would call from the button's OnClick Event


   procedure CreateAndSave;
   var
      Hr : HResult;
      Stream : IStream;
      OleStream : TOleStream;
      RootStorage : IStorage;
   begin
         {Try create the DocFile}
      Hr := StgCreateDocFile(  'c:\Temp\MyDocFile.ole',
                               STGM_CREATE or STGM_READWRITE or
                               STGM_DIRECT or STGM_SHARE_EXCLUSIVE,
                               0,
                               RootStorage
                             );


         {Was is created?}
      if(   not SUCCEEDED(  Hr  )   ) then
      begin
         (*  Fail  *)
         {D2}//RootStorage.Release;

         Exit;
      end;


         {Try to create the stream}
      Hr := RootStorage.CreateStream(  'MyStream',
                                       STGM_CREATE or STGM_READWRITE or
                                       STGM_DIRECT or STGM_SHARE_EXCLUSIVE,
                                       0,
                                       0,
                                       Stream
                                     );

         {Was is created?}
      if(   not SUCCEEDED(  Hr  )   ) then
      begin
         (*  Fail  *)
         {D2}//RootStorage.Release;

         Exit;
      end;

         {Create the OleStream}
      OleStream := TOleStream.Create(  Stream  );


         {Save the memo's text to the OleStream}
      mem_Text.Lines.SaveToStream(  OleStream  );
         {Finished with the OleStream}
      OleStream.Free;

      {D2}//Stream.Release;
      {D2}//RootStorage.Release;
   end;

I've included the .Release calls (comment out though) for the Delphi 2 users. If you're using Delphi 3 just ignore these lines.

From now on I'll be leaving out the Delphi 2 Release calls. If you are using Delphi 2 you must remember to call Release when you are finished with a IStorage or IStream.






All information on these www pages is copyright (©) 1997 Andre .v.d. Merwe And may not be copied or mirrored without my permission.