Page 1 of 2

Embedded Flash ActiveX

Posted: Mon Jun 28, 2004 3:52 pm
by Fred
Here is the skeleton of an embedded flash player. It uses the ATL dll for the activex container (which is Internet Explorer in fact) which is a common way to achieve this goal. As I've spend some time on it, I will describe step by step how I did it, if you want to do the same for another activex object (Excel, acrobat reader etc..).

- Create the container. The following code contains all the necessary steps, just change the name of the class to call (instead of "ShockwaveFlash.ShockwaveFlash")

- Look for the IID_xxxx: search on google when no doc is available for your component, else just look in the C header file (.h), it should be defined. It always look as 1 long, 2 words, and 8 bytes.

- Get the interface and constant definitions: use the excellent interface generator tool by aXend: http://home.planet.nl/~aXend/purebasic/ ... erator.zip
You will also have a quick doc for the all the interface methods, which is cool. BTW aXend, if you could put this definition in a comment near the interface method when exporting the file, it would be cool.

Here we go:

Code: Select all

;
; Embedded flash player example (ActiveX)
;
; By AlphaSND
;

; Flash ActiveX interface definition
;
Interface IShockwaveFlash Extends IDispatch
  get_ReadyState(a)
  get_TotalFrames(a)
  get_Playing(a)
  put_Playing(a)
  get_Quality(a)
  put_Quality(a)
  get_ScaleMode(a)
  put_ScaleMode(a)
  get_AlignMode(a)
  put_AlignMode(a)
  get_BackgroundColor(a)
  put_BackgroundColor(a)
  get_Loop(a)
  put_Loop(a)
  get_Movie(a)
  put_Movie(a)
  get_FrameNum(a)
  put_FrameNum(a)
  SetZoomRect(a,b,c,d)
  Zoom(a)
  Pan(a,b,c)
  Play()
  Stop()
  Back()
  Forward()
  Rewind()
  StopPlay()
  GotoFrame(a)
  CurrentFrame(a)
  IsPlaying(a)
  PercentLoaded(a)
  FrameLoaded(a,b)
  FlashVersion(a)
  get_WMode(a)
  put_WMode(a)
  get_SAlign(a)
  put_SAlign(a)
  get_Menu(a)
  put_Menu(a)
  get_Base(a)
  put_Base(a)
  get_scale(a)
  put_scale(a)
  get_DeviceFont(a)
  put_DeviceFont(a)
  get_EmbedMovie(a)
  put_EmbedMovie(a)
  get_BGColor(a)
  put_BGColor(a)
  get_Quality2(a)
  put_Quality2(a)
  LoadMovie(a,b)
  TGotoFrame(a,b)
  TGotoLabel(a,b)
  TCurrentFrame(a,b)
  TCurrentLabel(a,b)
  TPlay(a)
  TStopPlay(a)
  SetVariable(a,b)
  GetVariable(a,b)
  TSetProperty(a,b,c)
  TGetProperty(a,b,c)
  TCallFrame(a,b)
  TCallLabel(a,b)
  TSetPropertyNum(a,b,c)
  TGetPropertyNum(a,b,c)
  get_SWRemote(a)
  put_SWRemote(a)
  get_Stacking(a)
  put_Stacking(a)
EndInterface


Movie$ = "C:\Compare.swf"
  
If OpenLibrary(0, "ATL.dll") ; Use the ATL DLL for our container
  CoInitialize_(0) 

  If OpenWindow(0, 100, 100, 300, 315, #PB_Window_SystemMenu, "ATL test")

    CreateGadgetList(WindowID())  
      ContainerGadget(0, 10, 10, 280, 270) ; This will be our container window, where the ActiveX will be rendered
      CloseGadgetList()
      
      ButtonGadget(1, 10, 285, 70, 25, "Stop")
      ButtonGadget(2, 90, 285, 70, 25, "Play")
      
    If CallFunction(0,"AtlAxWinInit")
      
      CallFunction(0, "AtlAxCreateControl", Ansi2Uni("ShockwaveFlash.ShockwaveFlash"), GadgetID(0), 0, @Container.IUnknown) ; It always create the IE control even if flash isn't found
      If Container
        CallFunction(0,"AtlAxGetControl", GadgetID(0), @oFlash.IShockwaveFlash)
        If oFlash
          If oFlash\QueryInterface(?IID_ShockwaveFlash, @oFlash) = 0 ; Be sure it's a flash object in the IE container
          
            oFlash\LoadMovie(0, Ansi2Uni(Movie$))
            oFlash\Get_ReadyState(@State)   ; Seems to return 4 when the movie is ready to play, 3 else.
            If State = 4
              oFlash\Play()
              oFlash\FlashVersion(@Version)
              Debug "Flash Version: "+Hex(Version)
              oFlash\Put_BackgroundColor($0000FF)
              oFlash\Get_BackgroundColor(@BackColor)
              Debug "BackColor: "+Hex(BackColor)
            Else
              MessageRequester("Error", "The movie can't be loaded ("+Movie$+")")
            EndIf
            
            Repeat
              Event = WaitWindowEvent()
              
              If Event = #PB_Event_Gadget
              
                Select EventGadgetID()
                  Case 1
                    oFlash\Stop()
                    
                  Case 2
                    oFlash\Play()
                EndSelect
              EndIf
              
            Until Event = #PB_Event_CloseWindow
            
            oFlash\Release()
          EndIf
          oFlash\Release()
        EndIf
      EndIf
    EndIf
        
    CloseWindow(0)   ; Don't forget this one, else the program will crash
  EndIf    

  CoUninitialize_() 
EndIf  
  
End
  
DataSection
  IID_ShockwaveFlash:
    Data.l $D27CDB6C
    Data.w $AE6D, $11CF
    Data.b $96, $B8, $44, $45, $53, $54, $00, $00
  

Posted: Mon Jun 28, 2004 4:32 pm
by GedB
The missing Ansi2Uni procedure can be found here:

viewtopic.php?t=10908

Posted: Mon Jun 28, 2004 4:40 pm
by thefool
ahh. i though it was me that did something wrong :D

Posted: Mon Jun 28, 2004 5:28 pm
by Paul
Doesn't work here.

Line:
If Container

always returns 0 :(

Posted: Mon Jun 28, 2004 5:34 pm
by GedB
I'm finding the same problem.

Perhaps it is the wrong version fo Ansi2Uni?

Posted: Mon Jun 28, 2004 5:40 pm
by Nico
Same problem :(

Posted: Mon Jun 28, 2004 8:55 pm
by Fred
I'm using the Ansi2Uni from the aXend 'com' library. Of course you need to have flash installed :twisted:

Posted: Tue Jun 29, 2004 3:19 pm
by bingo
http://msdn.microsoft.com/library/defau ... ontrol.asp

"ShockwaveFlash.ShockwaveFlash" is a LPCOLESTR - maybe needed CoTaskMemAlloc ?

...

HRESULT __fastcall AnsiToUnicode(LPCSTR pszA, LPOLESTR* ppszW)
{

ULONG cCharacters;
DWORD dwError;

// If input is null then just return the same.
if (NULL == pszA)
{
*ppszW = NULL;
return NOERROR;
}

// Determine number of wide characters to be allocated for the
// Unicode string.
cCharacters = strlen(pszA)+1;

// Use of the OLE allocator is required if the resultant Unicode
// string will be passed to another COM component and if that
// component will free it. Otherwise you can use your own allocator.
*ppszW = (LPOLESTR) CoTaskMemAlloc(cCharacters*2);
if (NULL == *ppszW)
return E_OUTOFMEMORY;

// Covert to Unicode.
if (0 == MultiByteToWideChar(CP_ACP, 0, pszA, cCharacters,
*ppszW, cCharacters))
{
dwError = GetLastError();
CoTaskMemFree(*ppszW);
*ppszW = NULL;
return HRESULT_FROM_WIN32(dwError);
}

return NOERROR;
/*
* UnicodeToAnsi converts the Unicode string pszW to an ANSI string
* and returns the ANSI string through ppszA. Space for the
* the converted string is allocated by UnicodeToAnsi.
*/

Re: Embedded Flash ActiveX

Posted: Tue Jun 29, 2004 3:52 pm
by Dare2
Fred wrote:Here is the skeleton of an embedded flash player.
Oh man!

**** kissy **** kissy ****

Thank you. It works perfectly for me.

(That was purely platonic kissy-ing, BTW :P )

Re: Embedded Flash ActiveX

Posted: Wed Jun 30, 2004 8:35 am
by aXend
Fred wrote: BTW aXend, if you could put this definition in a comment near the interface method when exporting the file, it would be cool.
Thanks Fred for your recommendation for the Interface Generator. :oops:
Your suggestion: It is possible to add the comments, but it migth cause string memory problems. I already increased the string memory to 500 kb. There are some methods that have a lot of parameters, it would make it unreadable. I will see what I can do.

Posted: Wed Jun 30, 2004 9:59 am
by bingo
@Paul,Nico,GedB

insert (if any ansi2uni-procedure and no comlib)

If OpenLibrary(0, "ATL.dll") ; Use the ATL DLL for our container
CoInitialize_(0)
...
CoUninitialize_()
EndIf

thanks to aXend !

Posted: Wed Jun 30, 2004 11:50 am
by Fred
I've modified the code accordingly.

Posted: Wed Jun 30, 2004 11:51 am
by Nico
Too cool, thank you very much bingo! :D

Posted: Wed Jun 30, 2004 11:52 pm
by Dare2
This works on my box both ways (using and not using coinitialize_(0)). I have comlib in the userlibraries.

How does comlib come into it?

confused

Posted: Wed Jul 14, 2004 6:04 pm
by chio
Ok can someone give me a step-by-step to do this please.

I can't get this done.

I want to use a SWF file in my app, this is for that right? :lol:

Thanks.