说明

本项目参考了 https://github.com/yangzhongke/phoneasprompter 项目来完成实现,并对其进行了一些修改完善。

完整代码可以到 https://github.com/puzhiweizuishuai/ppt-remote-control 与 https://gitee.com/puzhiweizuishuai/ppt-remote-control 查看。

软件下载地址: https://gitee.com/puzhiweizuishuai/ppt-remote-control/releases/v1.0.0

另外,由于程序启动后会创建一个web服务器,用来显示ppt的操控界面,所以某些安全软件可能会报毒。但是程序本身是没有问题的。

截图

具体实现

通过在win form项目中内嵌一个kestrel web服务器,我们就可以通过浏览器向web服务器发送请求来接收远程操作指令。之后通过late binding的方式去操作ppt。

1、在 win form项目中内嵌http服务器

在form窗口启动时,我们新建一个kestrel服务器

this.webhost = new webhostbuilder()
                .usekestrel()
                .configure(configurewebapp)
                .useurls("http://*:" + port)
                .build();

            // 异步运行服务器
            this.webhost.runasync();

然后对其进行配置

private void configurewebapp(iapplicationbuilder app)
        {
            app.usedefaultfiles();
            app.usestaticfiles();
            app.run(async (context) =>
            {
                // 处理非静态请求 
                var request = context.request;
                var response = context.response;
                string path = request.path.value;
                response.contenttype = "application/json; charset=utf-8";
                bool hasrun = true;
                if (path == "/report")
                {
                    string value = request.query["value"];
                    this.begininvoke(new action(() => {
                        this.pagelabel.text = value;
                    }));
                    response.statuscode = 200;
                    await response.writeasync("ok");
                }
                else
                {
                    response.statuscode = 404;
                }
            });
            
        }

操作ppt

首先,由于涉及到了com编程,我们需要注意内存回收与释放,所以需要用到comreferencetracker类进行应用管理。

每一步用到com的地方,都要用t方法进行资源回收。

private dynamic t(dynamic comobj)
        {
            return this.comreference.t(comobj);
        }

以下操作使用dynamic进行操作,所有操作需要去查询vba文档了解具体用法,以下仅演示部分操作

打开一个ppt的操作实现

   private void button1_click(object sender, eventargs e)
        {
            // 文件选择框
            openfiledialog.filter = "ppt文件|*.ppt;*.pptx;*.pptm";
            if (openfiledialog.showdialog() != dialogresult.ok)
            {
                return;
            }
          
            string filename = openfiledialog.filename;
            this.clearcomrefs();
            // 创建 ppt 对象
            dynamic pptapp = t(powerpointhelper.createpowerpointapplication());
            // 显示 ppt
            pptapp.visible = true;
            dynamic presentations = t(pptapp.presentations);
            // 打开 ppt
            this.presentation = t(presentations.open(filename));
            // 全屏显示
            t(this.presentation.slideshowsettings).run();
        }

ppt上一个动画操作实现

t(t(presentation.slideshowwindow).view).previous();

下一步,与上一个操作类似,只需更换previous()方法为next()即可。

获取注释

首先我们需要一个方法去解析注释

private string getinnertext(dynamic part)
        {
            stringbuilder sb = new stringbuilder();
            dynamic shapes = t(t(part).shapes);
            int shapescount = shapes.count;
            for (int i = 0; i < shapescount; i++)
            {
                dynamic shape = t(shapes[i + 1]);
                var textframe = t(shape.textframe);
                // msotristate.msotrue==-1
                if (textframe.hastext == -1)
                {
                    string text = t(textframe.textrange).text;
                    sb.appendline(text);
                }
                sb.appendline();
            }
            return sb.tostring();
        }

之后通过

dynamic notespage = t(t(t(t(presentation.slideshowwindow).view).slide).notespage);
string notestext = getinnertext(notespage);

我们就可以获取具体每页的注释信息。

完善服务器

了解了以上的ppt操作之后,我们就需要去完善我们的web服务器端配置。

用户访问相应的地址,然后去执行上面ppt操作部分的代码即可。

   else if (path == "/getnote")
                {
                    string notestext = null;
                    this.invoke(new action(() => {
                        if (this.presentation == null)
                        {
                            return;
                        }
                        try
                        {
                            dynamic notespage = t(t(t(t(presentation.slideshowwindow).view).slide).notespage);
                            notestext = getinnertext(notespage);
                        }
                        catch (comexception ex)
                        {
                            notestext = "";
                        }
                    }));
                    await response.writeasync(notestext);
                }
                else if (path == "/next")
                {
                    response.statuscode = 200;
                    this.invoke(new action(() => {
                        if (this.presentation == null)
                        {
                            return;
                        }
                        try
                        {
                            t(t(this.presentation.slideshowwindow).view).next();
                            hasrun = true;
                        } catch (comexception e)
                        {
                            hasrun = false;
                        }
                        
                    }));

                    if (hasrun)
                    {
                        await response.writeasync("ok");
                    }
                    else
                    {
                        await response.writeasync("no");
                    }
                }
                else if (path == "/previous")
                {
                    response.statuscode = 200;
                    this.invoke(new action(() => {
                        if (this.presentation == null)
                        {
                            return;
                        }
                        try
                        {
                            t(t(this.presentation.slideshowwindow).view).previous();
                            hasrun = true;
                        }
                        catch (comexception e)
                        {
                            hasrun = false;
                        }
                        
                    }));
                    if (hasrun)
                    {
                        await response.writeasync("ok");
                    }
                    else
                    {
                        await response.writeasync("no");
                    }

完成前端

通过轮询的方式,不断的向服务端发送请求,获取最新的消息,这样我们就可以实现通过浏览器去操作ppt了。

<!doctype html>

<html lang="zh-cn">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="renderer" content="webkit" />
    <title>操作你的ppt</title>
    <link rel="icon" href="/logo.ico" rel="external nofollow" >
    <style>
        div {
            font-size: 25px
        }
    </style>
</head>
<body>
    <div id="main" style="width:100vw;height:100vh;">
        <p id="note"></p>
    </div>
    <script src="hammer.min.js"></script>
    <script>
        function httpget(url, cb) {
            fetch(url, {
                headers: {
                    'content-type': 'application/json; charset=utf-8'
                },
                method: 'get'
            }).then(response => response.text())
                .then(text => {
                    cb(text)
                })
                .catch(e => {
                    return null
                })
        }

        const note = document.queryselector("#note");

        let hasrun = true
        let getnotes = setinterval(() => {
            httpget('/getnote', (text) => {
                note.innertext = text
            })
        }, 500)

        function nextpage() {
            httpget('/next', (text) => {
                if (text == 'no') {
                    clearinterval(getnotes)
                    note.innertext = "幻灯片播放完毕!"
                    hasrun = false
                } else {
                    if (!hasrun) {
                        getnotes = setinterval(() => {
                            httpget('/getnote', (text) => {
                                note.innertext = text
                            })
                        }, 500)
                        hasrun = true
                    }
                }
            })
        }

        function previouspage() {
            httpget('/previous', (text) => {
                if (text == 'no') {
                    clearinterval(getnotes)
                    note.innertext = "幻灯片播放完毕!"
                    hasrun = false
                } else {
                    if (!hasrun) {
                        getnotes = setinterval(() => {
                            httpget('/getnote', (text) => {
                                note.innertext = text
                            })
                        }, 500)
                        hasrun = true
                    }
                }
            })
        }

        var hammer = new hammer(document.queryselector("#main"));
        hammer.on("swipeleft", function () {
            nextpage();
        });
        hammer.on("swiperight", function () {
            previouspage();
        });
    </script>
</body>
</html>

到此这篇关于使用c#实现一个ppt遥控器的文章就介绍到这了,更多相关c#实现ppt遥控器内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!