5

I want to be able to embed a powerpoint presentation into a C# form (WinForms). Basically we have a 52' monitor, and the idea is that in one corner we will have a PPT on loop, and then the other 3 corners will be displaying information from the program itself.

I had expected this to be straightforward, but it seems I am mistaken.

I had been advised to use the WebBrowser control, but this doesn't work and instead treats the powerpoint file as a download, i.e. gives me a "Save, Open" dialog.

Any suggestions?

AK

KingCronus
  • 4,509
  • 1
  • 24
  • 49
  • 1
    does your application have to interact with the presentation? you may be able to make do with running ppt in a virtual machine otherwise... – Adam Jul 09 '12 at 08:12
  • 1
    See http://stackoverflow.com/questions/10955496/powerpoint-2010-multiple-instances/11737090#11737090 – TFD Aug 02 '12 at 23:42

4 Answers4

8

You can just run PowerPoint, get the windows handle, and set a new parent window using the SetParent function.


All you need is the name of the window class of the PowerPoint window, but thanks to Spy++, this is no big deal.

spy++


Here's a screenshot of PowerPoint running 'inside' of a custom application:

PowerPoint


Full example (taken from here and modified for PowerPoint):

public partial class Form1 : Form
{
    public Form1()
    {
        this.Size = new System.Drawing.Size(800, 600);
        this.TopMost = true;
        this.Text = "My Application";
        this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
        Func<bool> run = () =>
            Window.Find(hwnd =>
            {
                var cn = Window.GetClassName(hwnd);
                var res = (cn == "PPTFrameClass");
                if (res)
                {
                    this.Controls.Clear();
                    Window.SetParent(hwnd, this.Handle);
                    Window.SetWindowPos(hwnd, new IntPtr(0), -8, -30, this.Width + 10, this.Height + 37, 0x0040);
                }
                return res;
            });

        new Button { Parent = this, Text = "Start" }
            .Click += (s, e) =>
            {
                if (run() == false)
                    MessageBox.Show("Open PowerPoint");
            };
    }
}

public static class Window
{
    public static bool Find(Func<IntPtr, bool> fn)
    {
        return EnumWindows((hwnd, lp) => !fn(hwnd), 0) == 0;
    }
    public static string GetClassName(IntPtr hwnd)
    {
        var sb = new StringBuilder(1024);
        GetClassName(hwnd, sb, sb.Capacity);
        return sb.ToString();
    }
    public static uint GetProcessId(IntPtr hwnd)     // {0:X8}
    {
        uint pid;
        GetWindowThreadProcessId(hwnd, out pid);
        return pid;
    }
    public static string GetText(IntPtr hwnd)
    {
        var sb = new StringBuilder(1024);
        GetWindowText(hwnd, sb, sb.Capacity);
        return sb.ToString();
    }

    delegate bool CallBackPtr(IntPtr hwnd, int lParam);

    [DllImport("user32.dll")]
    static extern int EnumWindows(CallBackPtr callPtr, int lPar);

    [DllImport("user32.dll")]
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

    [DllImport("User32", CharSet = CharSet.Auto, ExactSpelling = true)]
    public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndParent);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int W, int H, uint uFlags);
}
sloth
  • 99,095
  • 21
  • 171
  • 219
  • This is great, but would there be a similar way to only run the slideshow , rather than the entire environment? – KingCronus Jul 09 '12 at 09:25
  • There's a setting in PowerPoint to run a slideshow in windowed mode instead of fullscreen. Then it will look like [this](http://imagebin.org/220050). Maybe that's enough to make you happy :-) – sloth Jul 09 '12 at 09:41
  • I believe you could also display only the slide part of the PowerPoint window. You would have to use [GetDlgItem](http://msdn.microsoft.com/en-us/library/ms645481(VS.85).aspx) to get the `MDIClient` child control of the PowerPoint window, and then get the `"Slide" paneClassDC` control from that control. But I didn't test this. – sloth Jul 09 '12 at 09:47
  • I have used what you provided as a basis, but I have modified it slightly as I am going to try to use .pps files. That way when the powerpoint runs it launches straight into a fullscreen mode with the window class "screenClass". This seems to be working of sorts (auto-timings only work when the screen has focus etc). Thanks for setting me on the right track, assuming all goes well I'll credit you the bounty. – KingCronus Jul 09 '12 at 10:21
2

A PowerPoint viewer that is an embeddable Active/X control should be the way to go - you can try this (apparently it does not work - see comments) or this

See this for embedding Active/X controls in Windows Forms applications

If the window where you plan to display the PowerPoint does not change size you could also convert the PowerPoint slides into bitmaps, and then just display the bitmaps

MiMo
  • 11,793
  • 1
  • 33
  • 48
  • Try as I might, I have been unable to get that ActiveX control to work. It is dated 2007 and I wonder if it works at all. As for Bitmaps, that would be a pain as the idea is that the end user will be able to update the Powerpoint without too much trouble. – KingCronus Jul 09 '12 at 10:42
  • I did not try that Active/X control myself - it seems the way to go to me, have you tried to look for other ones (Googling it returns some hits - I added a link to my answer)? Concerning the bitmap 'trick' it should be possible to script PowerPoint to generate the bitmaps automatically. – MiMo Jul 09 '12 at 11:04
  • thanks for the assist, but every control I have found either a) doesn't work with Powerpoint 07 onwards, or costs a prohibitive amount. Aside from that, I don't really want to have to use ActiveX if I can help it. – KingCronus Jul 09 '12 at 12:21
0

I really have no idea wether it is possible to embed a ppt-viewer in winforms. I do have one other suggestion for you: Use the browser control (or download one for webkit if you want better html5 support) and use a js library like impress.js to present the presentation. Just a thought.

  • Unfortunately for me in this case the client is providing the powerpoint, and they need to be able to change it frequently and easily with powerpoint. – KingCronus Jul 06 '12 at 11:19
  • Impress.js looks fun though, I may have to try it for something else! – KingCronus Jul 06 '12 at 11:20
0

Originally posted by @danish, here.

See this link. You can also display the ppt in a WebBrowser control. This might also be useful.

Basically it allows you to open ppt as well, in a WebBrowser Control that you can embed easily. Let me know if you need more information about it.

Community
  • 1
  • 1
Guy
  • 5,370
  • 6
  • 25
  • 30