【原创】WIFI手机实现的PPT翻页器(1a)——PC端(C#实现)
近来智能手机非常流行,一个很久以前的idea在我的脑海里复活——用手机代替现有的PPT翻页器。众所周知,售前人员在给客户讲解PPT时,经常需要远离自己的电脑而走近投影屏幕。这时候讲解就需要用到无线翻页器。因此翻页器(Wireless Presenter)作为一款产品就开始热销了。我是没钱买的,不过既然我们的手机支持编程,支持WIFI,那为什么不自己DIY一个翻页器呢?Let’s Go!
WIFI手机PPT翻页器的原理很简单:手机上的客户端通过无线网络向PC上的服务端发送翻页命令,PC上的服务器程序根据命令,在当前正在播放的 PPT幻灯片上模拟键盘操作。
今天先来介绍服务端的实现,我曾经用Python实现过一个服务端的程序,请参考《【原创】WIFI手机实现的PPT翻页器(1)——PC端(Python实现)》。但是Python程序打包会出些意外的问题,最终我改为C#开发。程序流程基本如下:
1、启动后程序监听本地指定端口(默认80);
2、当有客户端连接监听端口并发送了指令则执行翻页操作;
3、翻页前通过枚举窗口找到PowerPoint幻灯片播放窗口,并将其设置为前端窗口;
4、程序将该窗口置顶(实际该步骤未实现),并执行相关键盘操作。如:向下翻页(N)、向前翻页(P)、首页(Home)、尾页(End)、退出(ESC)等;
5、程序循环运行。
关键技术:
1.C# WinForm编程
2.C# 调用Win32API枚举窗口、模拟键盘
3.C# Socket编程
4.C# 多线程编程
C#实现的WiFi PPT翻页器,主程序WirelessPresenter_PC.cs代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Net; using System.Net.Sockets; using System.Threading; namespace Wireless_Presenter_on_PC { public delegate bool CallBack(int hwnd, int lParam); public partial class frmWirelessPresenter : Form { [DllImport("user32")] public static extern int EnumWindows(CallBack x, int y); [DllImport("user32")] public static extern int GetWindowText(int hwnd, StringBuilder lptrstring, int nmaxcount); [DllImport("user32")] public static extern int GetParent(int hwnd); [DllImport("user32")] public static extern int SetForegroundWindow(int hwnd); private StringBuilder WindowTitles = new StringBuilder(); private int hwndPPT = 0; private System.Threading.Thread myThread = null; private TcpListener myTcpListener = null; public frmWirelessPresenter() { InitializeComponent(); } protected override CreateParams CreateParams { get { int CS_NOCLOSE = 0x200; CreateParams parameters = base.CreateParams; parameters.ClassStyle |= CS_NOCLOSE; return parameters; } } private void btnStart_Click(object sender, EventArgs e) { if (false == validationCheck()) return; btnStart.Enabled = false; //btnStop.Enabled = true; //System.Threading.Thread myThread; myThread = new System.Threading.Thread(new System.Threading.ThreadStart(CreateLitener)); myThread.Start(); //MessageBox.Show(WindowTitles.ToString()); } // 创建本地监听函数 private void CreateLitener() { try { int port = Int32.Parse(txtPort.Text); //TcpListener server = new TcpListener(IPAddress.Any, port); //server.Start(); myTcpListener = new TcpListener(IPAddress.Any, port); myTcpListener.Start(); while (true) { TcpClient client = myTcpListener.AcceptTcpClient(); NetworkStream stream = client.GetStream(); byte[] bytes = new byte[20]; int i; // Loop to receive all the data sent by the client. i = stream.Read(bytes, 0, bytes.Length); ppt_processCMD(Encoding.ASCII.GetString(bytes)); } } catch (SocketException e) { MessageBox.Show(e.Message); } } // 枚举系统窗口,找到幻灯片播放窗口 private bool ShowEmenuResult(int hwnd, int lParam) { //int hwndParent = GetParent(hwnd); //if (0 == hwndParent) return false; StringBuilder s = new StringBuilder(100); GetWindowText(hwnd, s, s.Capacity); if (s.ToString().ToLower().Contains("powerpoint") && s.ToString().Contains("幻灯片放映") && 0 == hwndPPT) { WindowTitles.Append(s.ToString()); SetForegroundWindow(hwnd); hwndPPT = hwnd; //MessageBox.Show(WindowTitles.ToString()); } return true; } private void btnStop_Click(object sender, EventArgs e) { if(null != myTcpListener) myTcpListener.Stop(); if(null != myThread) myThread.Abort(); this.Close(); } // 键盘模拟 private void ppt_sendkey(string key) { if (false == CheckWindow()) { CallBack myCallBack = new CallBack(ShowEmenuResult); EnumWindows(myCallBack, 0); if (false == CheckWindow()) { return; } else { SetForegroundWindow(hwndPPT); SendKeys.SendWait(key); } } else { SetForegroundWindow(hwndPPT); SendKeys.SendWait(key); //SendKeys.Flush(); } } // 解析命令 private void ppt_processCMD(string cmd) { //string cmd = cmd2.Trim(); if (cmd.Contains("UP")) { ppt_sendkey("{P}"); // "N" return; } if (cmd.Contains("DOWN")) { ppt_sendkey("{N}"); // "P" return; } if (cmd.Contains("BLACK")) { ppt_sendkey("{B}"); // "B" return; } if (cmd.Contains("WHITE")) { ppt_sendkey("{W}"); // "W" return; } if (cmd.Contains("HOME")) { ppt_sendkey("{HOME}"); // "HOME" return; } if (cmd.Contains("END")) { ppt_sendkey("{END}"); // "END" return; } if (cmd.Contains("QUIT")) { ppt_sendkey("{ESC}"); // "ESC" return; } } // 确认Windows窗口是否存在 private bool CheckWindow() { StringBuilder s = new StringBuilder(100) ; GetWindowText(hwndPPT, s, s.Capacity); return 0 < s.Length; } // 端口合法性检验 private bool validationCheck(){ return (0 < Int32.Parse(txtPort.Text) && 65535 > Int32.Parse(txtPort.Text)); } } } |
