Home | Delphi SWF SDK | SlideShow Engine | Free source samples | Code library | Forum | Contact

Code library

Load and play SWF from stream using ShockwaveFlashEx

How to open swf from the memory?

Unfortunately, the "standard" TShockwaveFlash does not contain any methods to play SWF from stream. Besides, a player does not load swf if its name is the same as a previous opened swf. So, quite often we have to use the following code:

var
  blankSWF, realSWF: string;
...
// create a blank temp file
  blankSWF := tempDir + '\' + {randomize name};
 
// create a real movie
  realSWF := tempDir + '\' + {randomize name};
 
  Player.Movie := blankSWF;
  Player.Movie := realSWF;

How to avoid that and open swf from the memory?
The property TShockwaveFlash.EmbedMovie was an incitement to me. If it is set to true then the file TShockwaveFlash.Movie is included to DFM as resource. DFM analyzing shows that swf is stored in the ControlData "section" together with other properties: Movie, ScaleMode, Quality, etc.

The first try was TStream.WriteComponent and TStream.ReadComponent using. After WriteComponent calling the saved data was analyzed and the swf was wrote to a required place. Unfortunately, ReadComponent calling did not give an expect result and the data relevant to ControlData was not updated. For example:

  player: TShockwaveFlash;
 
  mem: TMemoryStream;
...
  player.ScaleMode := 2; // exact fit
  mem.WriteComponent(Player); 
 
  player.ScaleMode := 0; // show all
  mem.Position := 0;
  mem.ReadComponent(player);
  mem.Free;
 
  ShowMessage('Scale mode is ' + IntToStr(player.ScaleMode));  // show 0,  not 2 !!!

Partly, it was fixed with the player control removing but it was not the best solution, because at least there was flickering.

  player: TShockwaveFlash;
 
  mem: TMemoryStream;
  OldParent: TWinControl;
...
  player.ScaleMode := 2; // exact fit
  mem.WriteComponent(Player); 
  OldParent := Player.Parent;
  Player.Free;
 
  mem.Position := 0;
  RegisterClass (TShockwaveFlash);
  Player := TShockwaveFlash (mem.ReadComponent(nil));
  Player.Parent := OldParent;
  Mem.Free;
  UnRegisterClass (TShockwaveFlash);
 
  ShowMessage('Scale mode is ' + IntToStr(player.ScaleMode));  // show 2, ok!

Analyzing the source TOleControl I came to a conclusion that after a control is created the ControlData is read but the value is not applied. To fix that the access to the field FObjectData is required but it is impossible because it is a private member. To avoid all these troubles I had to realize own method LoadMovieFromStream for an alternate way of data uploading.

Source ShockwaveEx.pas

Also, you can free download FlashAX with ShockwaveEx.pas.

  1. //*******************************************************//
  2. // //
  3. // DelphiFlash.com //
  4. // Copyright (c) 2004-2007 FeatherySoft, Inc. //
  5. // info@delphiflash.com //
  6. // //
  7. //*******************************************************//
  8.  
  9. // Description: Extended ShockwaveFlash visual control
  10. // update: 20 July 2006 by Cga - added ShiftState
  11. // update: 23 oct 2006
  12. // Last date update: 2 may 2007 - added LoadMovieFromStream
  13.  
  14. unit ShockwaveEx;
  15.  
  16. interface
  17.  
  18. uses
  19. Windows, SysUtils, Classes, Controls, OleCtrls, ShockwaveFlashObjects_TLB,
  20. Messages{$IFNDEF VER130}, Types{$ENDIF}, Forms, ActiveX;
  21.  
  22. type
  23. TShockwaveFlashEx = class(TShockwaveFlash)
  24. private
  25. FOnMouseDown: TMouseEvent;
  26. FOnMouseUp: TMouseEvent;
  27. FOnMouseMove: TMouseMoveEvent;
  28. FOnClick: TNotifyEvent;
  29. fLockMouseClick: boolean;
  30. WasDown: boolean;
  31. FOleObject: IOleObject;
  32. protected
  33. procedure WndProc(var Message:TMessage); override;
  34. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  35. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  36. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  37. procedure Click; override;
  38. procedure InitControlInterface(const Obj: IUnknown); override;
  39. public
  40. Procedure CreateWnd; override;
  41. procedure LoadMovieFromStream(Src: TStream);
  42. published
  43. property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;
  44. property OnMouseUp: TMouseEvent read FOnMouseUp write FOnMouseUp;
  45. property OnMouseMove: TMouseMoveEvent read FOnMouseMove write FOnMouseMove;
  46. property OnClick: TNotifyEvent read FOnClick write FOnClick;
  47. property LockMouseClick: boolean read fLockMouseClick write fLockMouseClick default false;
  48. end;
  49.  
  50. procedure Register;
  51.  
  52. implementation
  53.  
  54. Uses
  55. ZLib;
  56.  
  57. Procedure TShockwaveFlashEx.CreateWnd;
  58. begin
  59. inherited;
  60. end;
  61.  
  62. procedure TShockwaveFlashEx.InitControlInterface(const Obj: IUnknown);
  63. begin
  64. FOleObject := Obj as IOleObject;
  65. end;
  66.  
  67. procedure TShockwaveFlashEx.LoadMovieFromStream(Src: TStream);
  68. var
  69. unCompress: TStream;
  70. Mem, Mem2: TMemoryStream;
  71. SRCSize: longint;
  72. PersistStream: IPersistStreamInit;
  73. SAdapt: TStreamAdapter;
  74. ISize: int64;
  75. B: byte;
  76. ASign: array [0..2] of char;
  77. isCompress: boolean;
  78. ZStream: TDeCompressionStream;
  79.  
  80. begin
  81. // prepare src movie
  82. Src.Read(ASign, 3);
  83. isCompress := ASign = 'CWS';
  84. if isCompress then
  85. begin
  86. unCompress := TMemoryStream.Create;
  87. ASign := 'FWS';
  88. unCompress.Write(ASign, 3);
  89. unCompress.CopyFrom(Src, 1); // version
  90. SRC.Read(SRCSize, 4);
  91. unCompress.Write(SRCSize, 4);
  92. ZStream := TDeCompressionStream.Create(Src);
  93. try
  94. unCompress.CopyFrom(ZStream, SRCSize - 8);
  95. finally
  96. ZStream.free;
  97. end;
  98. unCompress.Position := 0;
  99. end else
  100. begin
  101. Src.Position := Src.Position - 3;
  102. SRCSize := Src.Size - Src.Position;
  103. unCompress := Src;
  104. end;
  105.  
  106. // store "template"
  107. EmbedMovie := false;
  108. FOleObject.QueryInterface(IPersistStreamInit, PersistStream);
  109. PersistStream.GetSizeMax(ISize);
  110. Mem := TMemoryStream.Create;
  111. Mem.SetSize(ISize);
  112. SAdapt := TStreamAdapter.Create(Mem);
  113. PersistStream.Save(SAdapt, true);
  114. SAdapt.Free;
  115.  
  116. // insetr movie to "template"
  117. Mem.Position := 1;
  118. Mem2 := TMemoryStream.Create;
  119. B := $66; // magic flag: "f" - embed swf; "g" - without swf;
  120. Mem2.Write(B, 1);
  121. Mem2.CopyFrom(Mem, 3);
  122. Mem2.Write(SRCSize, 4);
  123. Mem2.CopyFrom(unCompress, SRCSize);
  124. Mem2.CopyFrom(Mem, Mem.Size - Mem.Position);
  125.  
  126. // load activeX data
  127. Mem2.Position := 0;
  128. SAdapt := TStreamAdapter.Create(Mem2);
  129. PersistStream.Load(SAdapt);
  130. SAdapt.Free;
  131.  
  132. // free all
  133. Mem2.Free;
  134. Mem.Free;
  135. PersistStream := nil;
  136. if isCompress then unCompress.Free;
  137. end;
  138.  
  139. procedure TShockwaveFlashEx.WndProc(var Message: TMessage);
  140. Var x,y: integer;
  141. xy: TPoint;
  142. ShiftState: TShiftState;//cga
  143. begin
  144. if (Message.Msg >= WM_MOUSEFIRST) and (Message.Msg <= WM_MOUSELAST) then//cga
  145. if not (csDesigning in ComponentState) then begin
  146. ShiftState:=KeysToShiftState(TWMMouse(Message).Keys);//cga
  147. x:=TSmallPoint(Message.LParam).x;
  148. y:=TSmallPoint(Message.LParam).y;
  149. case Message.Msg of
  150. CM_MOUSELEAVE: WasDown:=false;
  151. WM_LBUTTONDOWN:
  152. begin
  153. MouseDown(mbLeft,ShiftState,x,y);
  154. WasDown:=true;
  155. end;
  156. WM_RBUTTONDOWN: WasDown:=true;
  157. WM_RBUTTONUP:
  158. if (PopupMenu<>nil) and (WasDown) then begin
  159. WasDown:=false;
  160. xy.X:=x;
  161. xy.Y:=y;
  162. xy:=ClientToScreen(xy);
  163. PopupMenu.Popup(xy.X,xy.Y);
  164. end;
  165. WM_LBUTTONUP:
  166. begin
  167. MouseUp(mbLeft,ShiftState,x,y);
  168. WasDown:=false;
  169. end;
  170. WM_MOUSEMOVE: MouseMove(ShiftState,x,y);
  171. end;
  172. //
  173. if (((Message.Msg=WM_RBUTTONDOWN) or (Message.Msg=WM_RBUTTONDOWN)) and (not Menu)) or
  174. (((Message.Msg=WM_RBUTTONUP) or (Message.Msg=WM_LBUTTONUP) or (Message.Msg=WM_LBUTTONDOWN)
  175. or (Message.Msg=WM_LBUTTONDBLCLK))
  176. and fLockMouseClick)
  177. then
  178. Message.Result := 0
  179. else
  180. inherited WndProc(Message);
  181. Exit;
  182. end;
  183. inherited WndProc(Message);
  184. end;
  185.  
  186. procedure TShockwaveFlashEx.MouseDown(Button: TMouseButton; Shift:
  187. TShiftState; X, Y: Integer);
  188. begin
  189. if Assigned(FOnMouseDown) then
  190. begin
  191. FOnMouseDown(Self, Button, Shift, X, Y);
  192. end;
  193. end;
  194.  
  195. procedure TShockwaveFlashEx.MouseUp(Button: TMouseButton; Shift:
  196. TShiftState; X, Y: Integer);
  197. begin
  198. if Assigned(FOnMouseUp) then
  199. begin
  200. FOnMouseUp(Self, Button, Shift, X, Y);
  201. end;
  202. if WasDown Then Click;
  203. end;
  204.  
  205. procedure TShockwaveFlashEx.MouseMove(Shift: TShiftState; X, Y: Integer);
  206. begin
  207. if Assigned(FOnMouseMove) then FOnMouseMove(Self, Shift, X, Y);
  208. end;
  209.  
  210. procedure TShockwaveFlashEx.Click;
  211. begin
  212. if Assigned(FOnClick) then FOnClick(Self);
  213. end;
  214.  
  215. procedure Register;
  216. begin
  217. RegisterComponents('Flash', [TShockwaveFlashEx]);
  218. end;
  219.  
  220. initialization
  221. RegisterClass(TShockwaveFlashEx);
  222.  
  223. finalization
  224. UnRegisterClass(TShockwaveFlashEx);
  225.  
  226. end.
  227.  

I would like to notice that ControlData must contain an uncompressed movie. Please take account of that to avoid unnecessary Compress/UnCompress actions.

Sample of use

procedure TmDemo.bLoadClick(Sender: TObject);
var 
  mem: TMemoryStream;
begin
  with TOpenDialog.Create(self) do
  begin
    Filter := 'SWF|*.swf';
    if Execute then
    begin
      mem := TMemoryStream.Create;
      mem.LoadFromFile(FileName);
      mem.Position := 0; 
      Player.LoadMovieFromStream(mem);
      mem.Free;
    end;
    Free;
  end;
end;

to top

Copyright 2004-2008 FeatherySoft, Inc. All rights reserved
Delphi is a trademark of Borland Software Corporation
Macromedia and Shockwave Flash are trademarks of Macromedia, Inc