Embedded Flash ActiveX

Share your advanced PureBasic knowledge/code with the community.
Fred
Administrator
Administrator
Posts: 18153
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Embedded Flash ActiveX

Post 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
  
Last edited by Fred on Wed Jun 30, 2004 11:51 am, edited 1 time in total.
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post by GedB »

The missing Ansi2Uni procedure can be found here:

viewtopic.php?t=10908
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

ahh. i though it was me that did something wrong :D
User avatar
Paul
PureBasic Expert
PureBasic Expert
Posts: 1282
Joined: Fri Apr 25, 2003 4:34 pm
Location: Canada
Contact:

Post by Paul »

Doesn't work here.

Line:
If Container

always returns 0 :(
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post by GedB »

I'm finding the same problem.

Perhaps it is the wrong version fo Ansi2Uni?
Nico
Enthusiast
Enthusiast
Posts: 274
Joined: Sun Jan 11, 2004 11:34 am
Location: France

Post by Nico »

Same problem :(
Fred
Administrator
Administrator
Posts: 18153
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

I'm using the Ansi2Uni from the aXend 'com' library. Of course you need to have flash installed :twisted:
User avatar
bingo
Enthusiast
Enthusiast
Posts: 210
Joined: Fri Apr 02, 2004 12:21 pm
Location: germany/thueringen
Contact:

Post 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.
*/
["1:0>1"]
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Re: Embedded Flash ActiveX

Post 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 )
@}--`--,-- A rose by any other name ..
aXend
Enthusiast
Enthusiast
Posts: 103
Joined: Tue Oct 07, 2003 1:21 pm
Location: Netherlands

Re: Embedded Flash ActiveX

Post 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.
User avatar
bingo
Enthusiast
Enthusiast
Posts: 210
Joined: Fri Apr 02, 2004 12:21 pm
Location: germany/thueringen
Contact:

Post 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 !
["1:0>1"]
Fred
Administrator
Administrator
Posts: 18153
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

I've modified the code accordingly.
Nico
Enthusiast
Enthusiast
Posts: 274
Joined: Sun Jan 11, 2004 11:34 am
Location: France

Post by Nico »

Too cool, thank you very much bingo! :D
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post 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?
@}--`--,-- A rose by any other name ..
chio
User
User
Posts: 30
Joined: Thu Jun 24, 2004 1:55 pm
Location: New York City
Contact:

confused

Post 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.
chio
Post Reply