Embeding Powerpoint

by Al Hospers

Microsoft Powerpoint is a very popular program used by small and large businesses for creating and playing back standard slideshow-style presentations. It is generally thought of as being easier to use by the average person, than Director. While Director is more powerful, PowerPoint is certainly more ubiquitous. With version 6.5 Macromedia created an Xtra which allows you to convert a Powerpoint presentation  to a Director movie. However it only works with version 4 Powerpoint files and it has a variety of other problems. Unfortunately these problems have not really been addressed in the latest upgrade to Director 7. While you can simply launch a Powerpoint presentation from Director, this brings up a number of other issues that we need not go into here. Therefore, for most purposes it would be much more elegant to be able to integrate a Powerpoint presentation into Director, and to control that presentation directly from buttons on the stage.

This code we are going to discuss in this article uses the BUDAPI Xtra to launch the Powerpoint Viewer and manipulate the Windows system in order to embed the Powerpoint presentation right on the stage. It uses a lot of calls to BUD, so you won't be able to run it from a projector unless you purchase the full version, but you should be fine running it in Director authoring mode.

I've wrapped the code in a behavior to make it easy to use. You simply drop it onto the button you use to launch the presentation. It pops up some questions, which you answer, and away you go. The example movie (PC format only), contains everything you need to get started, including a sample Powerpoint presentation.   Most of the code is commented, but here are some notes on the more interesting sections.

The BeginSprite handler contains a bunch of stuff, but the meat is in the following routines.

  -- we find the Powerpoint Viewer
  set pPptExe = FindViewer()

We find it we try to open it, and if successful, we embed the Viewer on the stage.

  if OpenFile(me, pPptFile) then
    pp_Wait -- wait a bit
    EmbedViewer()
  end if

Now let's look at a part of the FindViewer handler. Since we don't know where the Powerpoint Viewer is on the user's machine, we have to find it. First we look in the system registry. If it's not there, we try to get the system to tell us where it is.

  -- check for a viewer in the registry
  if baFileExists( pptExe ) = 0 then
    set pptExe = baReadRegString¬
                 ("software\microsoft\windows\currentversion¬
                 \app paths\ppview32.exe","","",¬
                 "HKEY_LOCAL_MACHINE" )
  end if

If you want to do much of this kind of stuff in Windows you will want to spend some time getting a handle on the system registry. It really is the only way to find out this kind of information.

  -- if we don't find it, try for the PowerPoint
  --
app instead
  if baFileExists( pptExe ) = 0 then
    set pptExe = baFindApp( "ppt" )
   
  -- we found it, now add "/s" to run it
  -- as a slideshow
    if pptExe <> EMPTY then set pptExe = pptExe & " /s"
    end if

  end if

Now that we know where the Powerpoint Viewer is, we can open it in the OpenFile handler. Of course we need to pass it the path that we got in FindViewer. The cool things here is the repeat loop that checks to see if the program has actually opened and waits till the actual window is open (or 15 seconds) until it does. If not it pops up an error message, using BUD to do it in real Windows style, and then sets the return value. This takes care of running the Viewer on really slow machines that tale a loooong time to open Viewer.

  -- did it open OK?
  if baRunProgram( pPptExe && pPptFile, "normal",
¬
          FALSE )> 32 then

    startTimer
    repeat while FindWindow() = VOID

      if the timer > 60 * 15 then
        set result = FALSE
        return result
        end if

    end repeat

    -- return successful open
    set result = TRUE
   else

    baMsgBox( "Couldn't open file!", "File error",
¬
          
"Exclamation", "OK", 1 )
    set result = FALSE -- unsuccessful open
  end if


We've opened the Powerpoint Viewer, so now we need a handle to the Viewer window so that we can  control it. The FindWindow handler deals with this and it's really neat. We use BUD to get a list of the windows matching the Powerpoint Viewer window "class." This is real system-level stuff. .

  set wndList = baWindowList( "screenClass",¬
                  "PowerPoint", false )
  if count( wndList ) > 0 then¬
                   set hWnd = getAt( wndList,1)

Once we've got the handle to the window of the Powerpoint Viewer, we can put it where we want it. And of course that's on the stage. The EmbedViewer handler does this work and the key code is in the following three lines:

  -- move the window to the correct location
  baMoveWindow( ppWindow, leftPosition, topPosition,¬
                   Width, Height, FALSE )

  -- set the stage so it won't stay on top
  baSetWindowState( baWinhandle(), "DontStayOnTop" )

  -- make the Powerpoint window stay on top of the stage
  baSetWindowState( ppWindow, "StayOnTop" )

Now that the Viewer is "embeded" on the stage we need to control it, right? I mean, it's no fun if it just sits there <grin>. Since there are unfortunately no "hooks" to the Viewer to control it directly, we have to use the kluge of passing it keystrokes to make it do what we want. The following two handlers illustrate how this is done. First the general landler that sends the key commands.

  on SendKeys me, keys
    -- sends keys to the powerpoint viewer
    -- makes the viewer the active window,
    -- waits a bit, then sends the keys

    -- make the Viewer the active window so
    -- it will accept the keys

    ActivateViewer()
    pp_Wait me

    baSendKeys(keys)

  end

This handler actually gets called by a On MouseUp handler that is attached to the NEXT> button on the stage. If you poke around in the behavior you'll notice that we put the handle to the behavior object in the global variable gPowerpointBehavior at the end of the BeginSprite handler. Without this we would not be able to access the handlers in the PowerpointBehavior object.

  on NextSlide me
  -- go to the next slide

    SendKeys(me, "{RIGHT}" )

  end

Those are the hilights. Now for the recap...


Summary

So that's pretty much the whole thing. Of course there are other handlers, so take the time look through the code yourself. Try this same concept with other applications. It should work with Acrobat, Word, Excel, and lots of other programs. Just give them a try.

Also this is just a demo, a proof-of-concept. While I have used it in commercial applications, you may find various anomalies on different machines that I have not personally tested it on. This code is provided to you as-is, with absolutely no warranties of any kind and WE ARE UNABLE TO PROVIDE FREE SUPPORT.


Additional Notes and Links

If you don't already have them, you'll need 2 additional programs to run this demo, the Microsoft Powerpoint Viewer '97 and the BuddyAPI Xtra. Here's where you get them:

    Powerpoint Viewer
    BuddyAPI

You may want to check out a good article on DOUG (The Director OnLine User's Group) site by Fred Bals, of Quantic Communications. It gives a slightly different viewpoint to this whole process and discusses the option of using an ActiveX control to accomplish the same thing. The article is in the Techniques section and is called PowerPoint in a Window.

The Powerpoint Viewer supports a number of command-line parameters that are sometimes useful to use when you launch the viewer. Here they are:

Automatic advance /A or /a
Slide range /R=n-m or /r=n-m where n<=m
Loop continuously /L or /l
Print /P or /p for printing file
Kiosk password /K or /k for setting a kiosk mode for file
Macro virus dialog box /V or /v for showing the macro virus dialog box