使用C#實現(xiàn)一個PPT遙控器
說明
本項目參考了 https://github.com/yangzhongke/PhoneAsPrompter 項目來完成實現(xiàn),并對其進行了一些修改完善。
完整代碼可以到 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
另外,由于程序啟動后會創(chuàng)建一個WEB服務(wù)器,用來顯示PPT的操控界面,所以某些安全軟件可能會報毒。但是程序本身是沒有問題的。
截圖

具體實現(xiàn)
通過在Win Form項目中內(nèi)嵌一個Kestrel Web服務(wù)器,我們就可以通過瀏覽器向web服務(wù)器發(fā)送請求來接收遠程操作指令。之后通過Late Binding的方式去操作PPT。
1、在 Win Form項目中內(nèi)嵌HTTP服務(wù)器
在Form窗口啟動時,我們新建一個Kestrel服務(wù)器
this.webHost = new WebHostBuilder()
.UseKestrel()
.Configure(ConfigureWebApp)
.UseUrls("http://*:" + port)
.Build();
// 異步運行服務(wù)器
this.webHost.RunAsync();
然后對其進行配置
private void ConfigureWebApp(IApplicationBuilder app)
{
app.UseDefaultFiles();
app.UseStaticFiles();
app.Run(async (context) =>
{
// 處理非靜態(tài)請求
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編程,我們需要注意內(nèi)存回收與釋放,所以需要用到COMReferenceTracker類進行應(yīng)用管理。
每一步用到COM的地方,都要用T方法進行資源回收。
private dynamic T(dynamic comObj)
{
return this.comReference.T(comObj);
}
以下操作使用dynamic進行操作,所有操作需要去查詢VBA文檔了解具體用法,以下僅演示部分操作
打開一個PPT的操作實現(xiàn)
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();
// 創(chuàng)建 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上一個動畫操作實現(xiàn)
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);
我們就可以獲取具體每頁的注釋信息。
完善服務(wù)器
了解了以上的PPT操作之后,我們就需要去完善我們的Web服務(wù)器端配置。
用戶訪問相應(yīng)的地址,然后去執(zhí)行上面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");
}
完成前端
通過輪詢的方式,不斷的向服務(wù)端發(fā)送請求,獲取最新的消息,這樣我們就可以實現(xiàn)通過瀏覽器去操作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>
到此這篇關(guān)于使用C#實現(xiàn)一個PPT遙控器的文章就介紹到這了,更多相關(guān)C#實現(xiàn)PPT遙控器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
WinForm通過操作注冊表實現(xiàn)限制軟件使用次數(shù)的方法
這篇文章主要介紹了WinForm通過操作注冊表實現(xiàn)限制軟件使用次數(shù)的方法,結(jié)合實例形式分析了WinForm操作注冊表的原理、步驟與相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2017-06-06
C#?BitArray(點矩陣)轉(zhuǎn)換成int和string的方法實現(xiàn)
BitArray?類管理一個緊湊型的位值數(shù)組,它使用布爾值來表示,本文主要介紹了C#?BitArray(點矩陣)轉(zhuǎn)換成int和string的方法實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2022-05-05
DevExpress實現(xiàn)自定義GridControl中按鈕文字內(nèi)容的方法
這篇文章主要介紹了DevExpress實現(xiàn)自定義GridControl中按鈕文字內(nèi)容的方法,需要的朋友可以參考下2014-08-08
asp.net實現(xiàn)遍歷Request的信息操作示例
這篇文章主要介紹了asp.net實現(xiàn)遍歷Request的信息操作,涉及asp.net針對請求信息相關(guān)操作打印操作技巧,需要的朋友可以參考下2020-03-03

