月巴月巴白勺合鸟月半

月巴月巴白勺合鸟月半

需求

导出PPT到MP4,并记录每页,每个动作的时间线。通过 MP4+时间线 就可以在页面上很方便的放映PPT的内容,并支持翻页点击。

一种导出PPT到MP4的方法-LMLPHP

代码

保存每一页的图像信息,用做播放器的缩略图

public void SaveThumbnail(string ppt_filepath, string targetdir)

记录下时间线

public void ResetTimeline(string ppt_filepath,string targetdir)

 打开PPT并绑定事件

            presentation = PPT.Presentations.Open(fn, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoTrue);
            PPT.SlideShowBegin += SlideShowBeginEvent;//开始运行PPT
            PPT.SlideShowEnd += SlideShowEndEvent;//开始运行PPT
            PPT.SlideShowNextSlide += SlideShowNextSlideEvent;//PPT翻页事件 
            PPT.SlideShowNextClick += SlideShowNextClickEvent;
            PPT.WindowActivate += WindowActivateEvent;

开始播放

            presentation.SlideShowSettings.AdvanceMode = PpSlideShowAdvanceMode.ppSlideShowRehearseNewTimings;
            presentation.SlideShowSettings.ShowWithNarration = MsoTriState.msoFalse;
            presentation.SlideShowSettings.ShowMediaControls = MsoTriState.msoTrue;
            presentation.SlideShowSettings.Run();

保存MP4文件

 presentation.CreateVideo(fn_mp4, true, 1, 720);

保存时间线json

            string json = Newtonsoft.Json.JsonConvert.SerializeObject(list_TimeRec);
            string json_fn = Path.ChangeExtension(fn_mp4,".json");
            File.WriteAllText(json_fn, json); 

全部代码

    public class PPTTools
    {
        public static void ClosePPT()
        {
            Process[] powerPointProcesses = Process.GetProcessesByName("powerpnt");
            foreach (Process powerPointProcess in powerPointProcesses)
            {
                try
                {
                    // 尝试关闭进程,并等待一段时间
                    powerPointProcess.CloseMainWindow();
                    powerPointProcess.WaitForExit(1000);
                    // 如果进程仍然没有关闭,强制结束
                    if (!powerPointProcess.HasExited)
                    {
                        powerPointProcess.Kill();
                    }
                }
                catch (Exception ex)
                {
                    //无法关闭PowerPoint进程
                }
            }
        }

        public void SaveThumbnail(string ppt_filepath, string targetdir)
        {
            ClosePPT();

            string tmpdir = get_tmpdir();
            string fn = Path.GetFileNameWithoutExtension(ppt_filepath) + "_tmp" + Path.GetExtension(ppt_filepath);
            fn = Path.Combine(tmpdir, fn);
            File.Copy(ppt_filepath, fn, true);

            list_TimeRec.Clear();
            will_next = false;
            PPT = new Microsoft.Office.Interop.PowerPoint.Application();
            presentation = null;
            presentation = PPT.Presentations.Open(fn, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoTrue);

            for (int i = 1; i <= presentation.Slides.Count; i++)
            {
                string thumbnail_fn = presentation.Slides[i].SlideNumber.ToString() + ".jpg";
                thumbnail_fn = Path.Combine(targetdir, thumbnail_fn);
                presentation.Slides[i].Export(thumbnail_fn, "JPG",1280);

            }

            PPT.Quit();
            ClosePPT();
        }

        public static string exefilename()
        {
            return System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
        }
        public static string get_tmpdir()
        {
            string dir = Path.GetDirectoryName(exefilename());
            dir = Path.Combine(dir, "temp");
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);
            return dir;
        }
        private bool is_Timeline = false;
        private bool is_Completed = false;
        private DateTime SlideShowNextSlideEvent_Time;
        private bool will_next = false;
        private Microsoft.Office.Interop.PowerPoint.Application PPT = null;
        private Presentation presentation = null;
        private SlideShowWindow CurrShowWindow;
        private List<TimeRec> list_TimeRec = new List<TimeRec>();
        public void ResetTimeline(string ppt_filepath,string targetdir)
        {
            if (is_Timeline)
                return;
            is_Timeline = true;
            is_Completed = false;
            ClosePPT();
           
            string tmpdir = get_tmpdir();
            string fn = Path.GetFileNameWithoutExtension(ppt_filepath )+ "_tmp" + Path.GetExtension(ppt_filepath);
            fn = Path.Combine(tmpdir, fn);
            File.Copy(ppt_filepath, fn, true);

            list_TimeRec.Clear();
            will_next = false;
            PPT = new Microsoft.Office.Interop.PowerPoint.Application();
            presentation = null;
            presentation = PPT.Presentations.Open(fn, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoTrue);
            PPT.SlideShowBegin += SlideShowBeginEvent;//开始运行PPT
            PPT.SlideShowEnd += SlideShowEndEvent;//开始运行PPT
            PPT.SlideShowNextSlide += SlideShowNextSlideEvent;//PPT翻页事件 
            PPT.SlideShowNextClick += SlideShowNextClickEvent;
            PPT.WindowActivate += WindowActivateEvent;

            //presentation.SlideShowSettings.LoopUntilStopped = MsoTriState.msoFalse;
            presentation.SlideShowSettings.AdvanceMode = PpSlideShowAdvanceMode.ppSlideShowRehearseNewTimings;
            presentation.SlideShowSettings.ShowWithNarration = MsoTriState.msoFalse;
            presentation.SlideShowSettings.ShowMediaControls = MsoTriState.msoTrue;
            presentation.SlideShowSettings.Run();
            System.Windows.Forms.Application.DoEvents();

            while (!is_Completed)
            { 
                System.Windows.Forms.Application.DoEvents();
                System.Threading.Thread.Sleep(10);
                if (will_next)
                {                   
                    if ((DateTime.Now - SlideShowNextSlideEvent_Time).TotalMilliseconds > 1000 * 8)
                    {
                        will_next = true;
                        SlideShowNextSlideEvent_Time = DateTime.Now;
                        int ClickCount = CurrShowWindow.View.GetClickCount();
                        int ClickIndex = CurrShowWindow.View.GetClickIndex();
                        if (ClickCount <= 0)
                        {
                            if (CurrShowWindow.View.Slide.SlideIndex == presentation.Slides.Count  )
                            {
                                break;
                            }
                            CurrShowWindow.View.Next();
                        }
                        else
                        {
                            if (ClickIndex <= (ClickCount -1))
                            {
                                CurrShowWindow.View.GotoClick(ClickIndex + 1);
                                //add_rec(ShowWindow);
                                SlideShowNextSlideEvent_Time = DateTime.Now; 
                            }
                            else
                            {
                                if (CurrShowWindow.View.Slide.SlideIndex == presentation.Slides.Count  )
                                {
                                    break;
                                }
                                else
                                {
                                    CurrShowWindow.View.Next();
                                }
                            }
                        }
                    }
                }
            }
            exited = false;
            Thread trd = new Thread( this.thread_proc );
            trd.Start();
            CurrShowWindow.View.Exit();
            exited = true;

            presentation.Save();
            if (!System.IO.Directory.Exists(targetdir))
                System.IO.Directory.CreateDirectory(targetdir);

            string fn_mp4 =Path.ChangeExtension( Path.Combine(targetdir, Path.GetFileName(ppt_filepath)),".mp4");

            presentation.CreateVideo(fn_mp4, true, 1, 720);
            for (int i = 0; i < 20; i++)
            {
                System.Windows.Forms.Application.DoEvents();
                System.Threading.Thread.Sleep(100);
            }
            while (presentation.CreateVideoStatus == PpMediaTaskStatus.ppMediaTaskStatusInProgress)
            {
                System.Windows.Forms.Application.DoEvents();
                System.Threading.Thread.Sleep(10);
            }
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(list_TimeRec);
            string json_fn = Path.ChangeExtension(fn_mp4,".json");
            File.WriteAllText(json_fn, json); 
             
            ClosePPT();
            is_Timeline = false;
        }
        private bool exited = false;
        public void thread_proc()
        {
            while (!exited)
            {
                try
                {

                    System.Threading.Thread.Sleep(100);
                    IntPtr h = IntPtr.Zero;
                    h = FindWindow(null, "Microsoft PowerPoint");
                    if (h != IntPtr.Zero)
                    {
                        ForceWindowIntoForeground(h);//置顶   
                        SendKeys.SendWait("\r");
                        SendKeys.SendWait(" ");
                    }
                    else
                    {
                    }
                }
                catch (Exception err)
                {

                }
                Thread.Sleep(500);
            }
        }
        public void SlideShowBeginEvent(SlideShowWindow Wn)
        {
        }
        public void SlideShowEndEvent(Presentation Pres)
        {
            is_Completed = true;
        }
        public void add_rec(SlideShowWindow Wn,string Event)
        {
            Slide slide = Wn.View.Slide;
            TimeRec rec = new TimeRec();
            rec.Event = Event;
            rec.ShowPosition = Wn.View.CurrentShowPosition;
            rec.PresentationElapsedTime = Wn.View.PresentationElapsedTime;
            rec.SlideElapsedTime = Wn.View.SlideElapsedTime;
            rec.SlideIndex = slide.SlideIndex;
            rec.SlideNumber = slide.SlideNumber;
            rec.ClickCount = Wn.View.GetClickCount();
            rec.ClickIndex = Wn.View.GetClickIndex();
            list_TimeRec.Add(rec);
        }

        public void SlideShowNextSlideEvent(SlideShowWindow Wn)
        {
            add_rec(Wn, "NextSlide");
            CurrShowWindow = Wn;
            SlideShowNextSlideEvent_Time = DateTime.Now ;
            will_next = true;
        }
        public void SlideShowNextClickEvent(SlideShowWindow Wn, Effect nEffect) {
            add_rec(Wn, "NextClick");
            CurrShowWindow = Wn;
            SlideShowNextSlideEvent_Time = DateTime.Now;
            will_next = true;
        }
        public void WindowActivateEvent(Presentation Pres, DocumentWindow Wn)
        { 
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
        //I'd double check this constant, just in case
        static uint WM_CLOSE = 0x10;
        public void CloseWindow(IntPtr hWindow)
        {
            SendMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        }
        [DllImport("USER32.DLL")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        public const int HWND_TOP = 0;
        public const int HWND_BOTTOM = 1;
        public const int HWND_TOPMOST = -1;
        public const int HWND_NOTOPMOST = -2;
        public struct WindowRect
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
        private const int SW_HIDE = 0;
        private const int SW_SHOWNORMAL = 1;
        private const int SW_NORMAL = 1;
        private const int SW_SHOWMINIMIZED = 2;
        private const int SW_SHOWMAXIMIZED = 3;
        private const int SW_MAXIMIZE = 3;
        private const int SW_SHOWNOACTIVATE = 4;
        private const int SW_SHOW = 5;
        private const int SW_MINIMIZE = 6;
        private const int SW_SHOWMINNOACTIVE = 7;
        private const int SW_SHOWNA = 8;
        private const int SW_RESTORE = 9;
        private const int SW_SHOWDEFAULT = 10;
        private const int SW_MAX = 10;

        private const int SPI_GETFOREGROUNDLOCKTIMEOUT = 0x2000;
        private const int SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001;
        private const int SPIF_SENDCHANGE = 0x2; 
       

        [DllImport("user32.dll", SetLastError = true)]
        static extern bool SystemParametersInfo(int uiAction, int uiParam, ref uint pvParam, int fWinIni);

        [DllImport("user32.dll")]
        private static extern IntPtr AttachThreadInput(IntPtr idAttach, IntPtr idAttachTo, Boolean fAttach);

        [DllImport("user32", EntryPoint = "GetWindowThreadProcessId")]
        private static extern IntPtr GetWindowThreadProcessId(IntPtr hwnd, out IntPtr lpdwProcessId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();

        [DllImport("kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
        public static extern IntPtr GetCurrentThreadId();

        [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);//设置此窗体为活动窗体

        [DllImport("user32.dll")]
        public static extern IntPtr SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint wFlags);


        [DllImport("user32.dll")]
        public static extern bool GetWindowRect(IntPtr hWnd, out WindowRect lpRect);
        [DllImport("user32", CharSet = CharSet.Auto)]
        public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        public static void SetTopomost(IntPtr hWnd)
        {
            WindowRect rect = new WindowRect();
            GetWindowRect(hWnd, out rect);
            SetWindowPos(hWnd, (IntPtr)HWND_TOPMOST, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, 0);
        }
        public static void ForceWindowIntoForeground(IntPtr window)
        {
            try
            {
                SetTopomost(window);
                IntPtr currentThread = GetCurrentThreadId();

                IntPtr activeWindow = GetForegroundWindow();
                IntPtr activeProcess;
                IntPtr activeThread = GetWindowThreadProcessId(activeWindow, out activeProcess);

                IntPtr windowProcess;
                IntPtr windowThread = GetWindowThreadProcessId(window, out windowProcess);

                if (currentThread != activeThread)
                    AttachThreadInput(currentThread, activeThread, true);
                if (windowThread != currentThread)
                    AttachThreadInput(windowThread, currentThread, true);

                uint oldTimeout = 0, newTimeout = 0;
                SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, ref oldTimeout, 0);
                SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, ref newTimeout, 0);
                // LockSetForegroundWindow(LSFW_UNLOCK);
                // AllowSetForegroundWindow(ASFW_ANY);

                SetForegroundWindow(window);
                ShowWindow(window, SW_RESTORE);

                SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, ref oldTimeout, 0);

                if (currentThread != activeThread)
                    AttachThreadInput(currentThread, activeThread, false);
                if (windowThread != currentThread)
                    AttachThreadInput(windowThread, currentThread, false);

                SetTopomost(window);

            }
            catch (Exception e)
            {


            }

        }

    }

    public class TimeRec
    { 
        public string Event = "";
        public int ShowPosition = 0;
        public float PresentationElapsedTime = 0;
        public float SlideElapsedTime = 0;
        public int SlideIndex = 0;
        public int SlideNumber = 0;
        public int ClickCount = 0;
        public int ClickIndex = 0;
    }
09-01 22:13