日期:2014-06-10  浏览次数:20560 次

  相信大家都有过演讲的经历,当我们演讲时,一手拿着windows phone手机按按键就可以操作powerPoint幻灯片的播放,是不是显得比较高端?你如果想了解这种互动是怎么实现的,那么你可以继续往下看。

  使用windows phone操作PC的PPT播放并不是一件多难的事儿,同样是对于android和IOS移动端,主要涉及到两个方面:通信和调用PowerPoint 的API。对于第一方面,既然手机端可以控制PC端,那么他们之间必然有信息传递,你可以使用手机的蓝牙和电脑的蓝牙进行通信,不过考虑到现在的PC还有很多不支持蓝牙,再加上蓝牙传输可能并不稳定,所以在这里我们可以使用Socket进行通信;对于第二方面,也很简单,我们只需要在PC端去调用PowerPoint的API就OK,主要涉及的操作包括:切换幻灯片到第一张、切换幻灯片到下一张、切换幻灯片到上一张、切换幻灯片到最后一张。

  举个例子来说,我们当用手机点击上一页按钮时,会传递一个数字a到服务端,服务端会判断这个数字a是要执行切换到上一页操作的命令,所以我们就调用切换到上一页的API,就能成功实现切换,所以如果想实现这个功能不仅仅需要手机客户端,还需要一个PC的服务端用来接收手机端发来的消息并进行处理,当然手机端需要输入PC端IP和端口来和PC端通信,我在这里仅实现了最基本的功能,其他功能可以在此基础上进行扩展。

  下面首先介绍服务端调用PowerPoint API 的代码:(参考了貌似是一位微软工程师的博客)

  

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Runtime.InteropServices;
  5 using System.Text;
  6 using System.Threading.Tasks;
  7 using PPt = Microsoft.Office.Interop.PowerPoint;
  8 namespace ServerPPT
  9 {
 10     class PPTServer
 11     {
 12         // 定义PowerPoint应用程序对象
 13         PPt.Application pptApplication;
 14         // 定义演示文稿对象
 15         PPt.Presentation presentation;
 16         // 定义幻灯片集合对象
 17         PPt.Slides slides;
 18         // 定义单个幻灯片对象
 19         PPt.Slide slide;
 20 
 21         // 幻灯片的数量
 22         int slidescount;
 23         // 幻灯片的索引
 24         int slideIndex;
 25         //检查幻灯片是否已经打开
 26         public void CheckPPT()
 27         {
 28             // 必须先运行幻灯片,下面才能获得PowerPoint应用程序,否则会出现异常
 29             // 获得正在运行的PowerPoint应用程序
 30             try
 31             {
 32                 pptApplication = Marshal.GetActiveObject("PowerPoint.Application") as PPt.Application;
 33 
 34                 // 成功获取了PowerPoint程序时,使UI按钮可用
 35             }
 36             catch
 37             {
 38                 //  MessageBox.Show("请先启动遥控的幻灯片", "Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
 39             }
 40             if (pptApplication != null)
 41             {
 42                 //获得演示文稿对象
 43                 presentation = pptApplication.ActivePresentation;
 44                 // 获得幻灯片对象集合
 45                 slides = presentation.Slides;
 46                 // 获得幻灯片的数量
 47                 slidescount = slides.Count;
 48                 // 获得当前选中的幻灯片
 49                 try
 50                 {
 51                     // 在普通视图下这种方式可以获得当前选中的幻灯片对象
 52                     // 然而在阅读模式下,这种方式会出现异常
 53                     slide = slides[pptApplication.ActiveWindow.Selection.SlideRange.SlideNumber];
 54                 }
 55                 catch
 56                 {
 57                     // 在阅读模式下出现异常时,通过下面的方式来获得当前选中的幻灯片对象
 58                     slide = pptApplication.SlideShowWindows[1].View.Slide;
 59                 }
 60             }
 61         }
 62 
 63         //第一页
 64         public  void FirstPage()
 65         {
 66             try
 67             {
 68                 // 在普通视图中调用Select方法来选中第一张幻灯片
 69                 slides[1].Select();
 70                 slide = slides[1];
 71             }
 72             catch
 73             {
 74                 // 在阅读模式下使用下面的方式来切换到第一张幻灯片
 75                 pptApplication.SlideShowWindows[1].View.First();
 76                 slide = pptApplication.SlideShowWindows[1].View.Slide;
 77             }
 78         }
 79         //上一页
 80         public void PreviousPage()
 81         {
 82             slideIndex = slide.SlideIndex - 1;
 83             if (slideIndex >= 1)
 84             {
 85                 try
 86                 {
 87                     slide = slides[slideIndex];
 88                     slides[slideIndex].Select();
 89                 }
 90                 catch
 91                 {
 92                     // 在阅读模式下使用下面的方式来切换到上一张幻灯片
 93                     pptApplication.SlideShowWindows[1].View.Previous();
 94                     slide = pptApplication.SlideShowWindows[1].View.Slide;
 95                 }
 96             }
 97             else
 98             {
 99                 // MessageBox.Show("已经是第一页了");
100             }
101         }
102 
103         //下一页
104         public void NextPage()
105         {
106             slideIndex = slide.SlideIndex + 1;
107             if (slideIndex > slidescount)
108             {
109                 //MessageBox.Show("已经是最后一页了");
110             }
111             else
112             {
113                 try
114                 {
115                     slide = slides[slideIndex];
116                     slides[slideIndex].Select();
117                 }
118                 catch
119                 {
120                     // 在阅读模式下使用下面的方式来切换到下一张幻灯片
121                     pptApplication.SlideShowWindows[1].View.Next();
122                     slide = pptApplication.SlideShowWindows[1].View.Slide;
123                 }
124             }
125         }
126         //最后一页
127         public void LastPage()
128         {
129             try
130             {
131                 slides[slidescount].Select();
132                 slide = slides[slidescount];
133             }
134             catch
135             {
136                 // 在阅读模式下使用下面的方式来切换到最后幻灯片
137                 pptApplication.SlideShowWindows[1].View.Last();
138                 slide = pptApplication.SlideShowWindows[1].View.Slide;
139             }
140         }
141     }
142 }

    其次介绍服务端PC和和客户端(windows phone)使用Socket通信的代码,服务端等待接收消息代码如下所示:

 

 1         Socket listenner = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 2         private Control control = new Control();
 3         
 4         public Form1()
 5         {
 6             InitializeComponent();
 7             TextBox.CheckForIllegalCrossThreadCalls = false;
 8             
 9         }
10         //打印提示信息
11         public void showMessage(String strMsg)
12         {
13            output.AppendText(strMsg + "\r\n");
14         }
15         private static AutoResetEvent _flipFlop = new AutoResetEvent(false);
16         private void start_Click(object sender, EventArgs e)
17         {
18             
19             
20             IPAddress address = IPAddress.Parse(iptext.Text.Trim());//创建IP对象
21 
22             IPEndPoint localEP = new IPEndPoint(address,int.Parse(porttext.Text.Trim()));
23 
24           //  MessageBox.Show("运行中");
25                  showMessage("本地IP地址和端口是"+localEP);
26                 listenner.Bind(localEP);
27                 listenner.Listen(10);
28                 Thread threadlisten;//定义监听线程
29                 threadlisten = new Thread(startlisten);
30                 threadlisten.IsBackground = true;//创建线程时默认false,为false时,主线程退出,仍然执行,直到结束
31                 threadlisten.Start();
32 
33         }
34         private void startlisten() {
35             while (true)
36             {
37                 // Console.WriteLine("等待windows phone客户端的连接。。。。");
38                 showMessage("等待windows phone客户端的连接");
39                 listenner.BeginAccept(AcceptCallback, listenner);
40                 _flipFlop.WaitOne();
41             }
42         }
43         private void AcceptCallback(IAsyncResult ar)
44         {
45             Socket listener = (Socket)ar.AsyncState;
46             Socket socket = listener.EndAccept(ar);
47            // Console.WriteLine("连接到windows phone 客户端");
48             showMessage("连接到windows phone 客户端");
49             _flipFlop.Set();
50             var state = new StateObject();
51             state.Socket = socket;
52             socket.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReceiveCallback, state);
53         }
54 
55         private void ReceiveCallback(IAsyncResult ar)
56         {
57             StateObject state = (StateObject)ar.AsyncState;
58             Socket socket = state.Socket;
59             int read = socket.EndReceive(ar);
60             if (read > 0)
61             {
62                 string chunk = Encoding.UTF8.GetString(state.Buffer, 0, read);
63                 state.StringBuilder.Append(chunk);
64                 if (state.StringBuilder.Length > 0)
65                 {
66                     string result = state.StringBuilder.ToString();
67                   //  Console.WriteLine("收到客户端传来的消息:{0}", result);
68                     control.Dispatcher(int.Parse(result));
69                     //showMessage("收到客户端传来的消息:"+result);
70                     //Send(socket, "s" + result);
71                     //Console.WriteLine("发给客户端的消息:{0}", "s" + result);
72                     //showMessage("发给客户端的消息"+result);
73                 }
74             }
75         }

  客户端发起连接的代码如下:

  

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Net;
  5 using System.Windows;
  6 using System.Windows.Controls;
  7 using System.Windows.Navigation;
  8 using Microsoft.Phone.Controls;
  9 using Microsoft.Phone.Shell;
 10 using SocketClient.Resources;
 11 using System.Net.Sockets;
 12 using System.Text;
 13 
 14 namespace SocketClient
 15 {
 16     public partial class MainPage : PhoneApplicationPage
 17     {
 18        
 19         public MainPage()
 20         {
 21             InitializeComponent();
 22 
 23         }
 24 
 25         private void Send(string str)
 26         {
 27             if (string.IsNullOrEmpty(Host.Text) || string.IsNullOrEmpty(Port.Text)) {
 28                 MessageBox.Show("请输入以下主机IP和端口号,谢谢");
 29                 return;
 30             }
 31 
 32             string host = Host.Text.Trim();
 33 
 34             int port = Convert.ToInt32(Port.Text.Trim());
 35 
 36             DnsEndPoint hostEntry = new DnsEndPoint(host, port);
 37             Socket sock = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
 38 
 39             SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
 40             byte[] buffer = Encoding.UTF8.GetBytes(str);
 41             socketEventArg.SetBuffer(buffer, 0, buffer.Length);
 42             socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(SocketAsyncEventArgs_Completed);
 43             socketEventArg.RemoteEndPoint = hostEntry;
 44             socketEventArg.UserToken = sock;
 45             try
 46             {
 47                 sock.ConnectAsync(socketEventArg);
 48             }
 49             catch (SocketException ex) {
 50                 throw new SocketException((int)ex.ErrorCode);
 51             }
 52 
 53 
 54         }
 55         private void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
 56         {
 57             if(e.SocketError!=SocketError.Success){
 58                 if (e.SocketError == SocketError.ConnectionAborted) { 
 59                     Dispatcher.BeginInvoke(()=>MessageBox.Show("连接超时请重试"+e.SocketError));
 60                 }
 61                 else if (e.SocketError == SocketError.ConnectionRefused)
 62                 {
 63                     Dispatcher.BeginInvoke(() => MessageBox.Show("服务器端启动" + e.SocketError));
 64                 }
 65                 else {
 66                     Dispatcher.BeginInvoke(() => MessageBox.Show("出错了" + e.SocketError));
 67                 }
 68 
 69                 if (e.UserToken != null) {
 70                     Socket sock = e.UserToken as Socket;
 71                     sock.Shutdown(SocketShutdown.Both);
 72                     sock.Close();
 73                 }
 74                 return;
 75             }
 76 
 77             switch (e.LastOperation) { 
 78                 case SocketAsyncOperation.Connect:
 79                     if (e.UserToken != null) {
 80                         Socket sock = e.UserToken as Socket;
 81                         bool completeAsynchronously = sock.SendAsync(e);
 82                         if (!completeAsynchronously) {
 83                             SocketAsyncEventArgs_Completed(e.UserToken, e);
 84                         }
 85                     };
 86                     break;
 87                 case SocketAsyncOperation.Send:
 88                     Dispatcher.BeginInvoke(()=>{
 89                         //listBox1.Items.Add("客户端"+DateTime.Now.ToShortTimeString()+"发送的消息:"+Message.Text);
 90                     }
 91                 );
 92                     if (e.UserToken != null)
 93                     {
 94                         Socket sock = e.UserToken as Socket;
 95                         bool completesAsynchronously = sock.ReceiveAsync(e);
 96                         if (!completesAsynchronously) {
 97                             SocketAsyncEventArgs_Completed(e.UserToken,e);
 98                         }
 99                     }
100                     break;
101                 case SocketAsyncOperation.Receive:
102                     if (e.UserToken != null) {
103                         string dataFromServer = Encoding.UTF8.GetString(e.Buffer,0,e.BytesTransferred);
104                         Socket sock = e.UserToken as Socket;
105                         Dispatcher.BeginInvoke(() =>
106                         {
107 
108 
109                           //  listBox1.Items.Add("服务器端" + DateTime.Now.ToShortTimeString() + "传过来的消息:" + dataFromServer);
110                         });
111                      }
112                     break;
113                     }
114 
115             }
116 
117         private void check_Click(object sender, RoutedEventArgs e)
118         {
119             Send("1");
120         }
121 
122         private void First_Click(object sender, RoutedEventArgs e)
123         {
124             Send("2");
125         }
126 
127         private void previous_Click(object sender, RoutedEventArgs e)
128         {
129             Send("3");
130         }
131 
132         private void next_Click(object sender, RoutedEventArgs e)
133         {
134             Send("4");
135         }
136 
137         private void last_Click(object sender, RoutedEventArgs e)
138         {
139             Send("5");
140         }
141         
142     }
143 
144         
145 
146     
147 }

   源代码我已经上传到百度网盘链接: http://pan.baidu.com/s/1mg5HAsS 密码: i4a9,欢迎大家学习,并进行二次开发。