Laien's

成功 自在 健康 好状态

【原创】WIFI手机实现的PPT翻页器(1a)——PC端(C#实现)

without comments

  近来智能手机非常流行,一个很久以前的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代码如下:

?Download download.txt
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));
        }
 
 
    }
}

程序界面预览如下:

Written by Laien

February 27th, 2010 at 5:48 am

Posted in C#, Programming