Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1282
  • Last Modified:

Load a TOleContainer from a stream which contains a file image, without using CreateObjectFromFile

Hi,
I have a database which contains blobs loaded from file of various MS doc types such as Word and Excel.  I'm trying to load these into a TOleContainer in much the same way that CreateObjectFromFile() works, however, without having to write the contents out to disk, etc.  I've tried a number of combinations to no avail.  Below is a code snippet which may at least help in conveying what I am trying to accomplish.

Any help would be greatly appreciated!

...
      try
        Stream:=TMemoryStream.Create; {Creation memory stream and saving content from database}
        TBlobField(FDataLink.Field).SaveToStream(Stream);
        Stream.Seek(0,soFromBeginning);
        S := GetAssociatedClassname(ExtractFileExt(aOriginalFileName));  // Returns, for example, "Excel.Sheet.8" or "Word.Document.8"
        CreateObject(S, False);
        // LoadFromStream(Stream);  // doesn't work!!!!  ...Invalid Stream format
        if Assigned(Stream) then
          begin
            Stream.Free;
            Stream:=nil;
          end;
      except
        on E:exception do begin
          if Assigned(Stream) then Stream.Free;
          Raise;
        end;
      end;
...
0
WBread
Asked:
WBread
  • 2
1 Solution
 
JaccoCommented:
If you add this method to the OleCntrs unit

procedure TOleContainer.LoadAsDocument(const Stream: TStream);
var
  DataHandle: HGLOBAL;
  Buffer: Pointer;
begin
  DataHandle := GlobalAlloc(GMEM_MOVEABLE, Stream.Size);
  if DataHandle = 0 then OutOfMemoryError;
  try
    Buffer := GlobalLock(DataHandle);
    try
      Stream.Read(Buffer^, Stream.Size);
    finally
      GlobalUnlock(DataHandle);
    end;
    OleCheck(CreateILockBytesOnHGlobal(DataHandle, True, FLockBytes));
    DataHandle := 0;
    OleCheck(StgOpenStorageOnILockBytes(FLockBytes, nil, STGM_READWRITE or
      STGM_SHARE_EXCLUSIVE, nil, 0, FStorage));
    OleCheck(OleLoad(FStorage, IOleObject, self, FOleObject));
    FDrawAspect := DVASPECT_CONTENT;
    InitObject;
    FOleObject.SetExtent(DVASPECT_CONTENT, PixelsToHimetric(Point(ClientWidth, ClientHeight)));
    SetDrawAspect(False, 0);
    UpdateView;
  except
    if DataHandle <> 0 then GlobalFree(DataHandle);
    DestroyObject;
    raise;
  end;
end;

the following code will work:

  lContainer := TOleContainer.Create(Self);
  with lContainer do
  begin
    Parent := Form1;
    lFS := TFileStream.Create('test.doc', fmOpenRead);
    try
      LoadAsDocument(lFS);
      DoVerb(ovPrimary);
    finally
      lFS.Free;
    end;
  end;

I don't like pathcing the VCL but sometimes you can't do things otherwise. You can also make a copy of the whole unit.

Regards Jacco
0
 
WBreadAuthor Commented:
Hi Jacco,
This works great.  Thanks!!

I'm still trying to figured out how to make the document show up in the "viewing" mode, i.e. visible but without the toolbars/menus, that I initially see using CreateObjectFromFile.  If you happen to know this, I'd be glad to see it :)

Either way, this answer is complete and very welcome.

Thanks again
-Todd
0
 
JaccoCommented:
I have tried getting that result but was not able to find it. I added the GetVerb(...) to have something similar...

Regards Jacco
0

Featured Post

[Webinar] Database Backup and Recovery

Does your company store data on premises, off site, in the cloud, or a combination of these? If you answered “yes”, you need a data backup recovery plan that fits each and every platform. Watch now as as Percona teaches us how to build agile data backup recovery plan.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now