基于windowsphone7的控制ppt播放 第一部分 服务器端

最近突然想起了一个学长的一个利用手机控制ppt播放的一个创意,并想将其在windows phone7上实现一下。

经过几天的努力已经可以控制ppt的播放,暂停,上一张,下一张了,并且电脑会将当前ppt的截图发送到手机端这里。

在代码的编写过程中,参考了IT黄老邪Windows Phone开发(46):与Socket有个约会 进行服务端与wp客户端的socket通讯的编写,并加入了键盘消息模拟,服务端截屏,图片发送,与客户端的图片接受。

代码如下:

WP客户端

1、新建Windows Phone应用程序项目。(我这里的名称是叫PhoneApp2)

2、打开MainPage.xaml文件,输入以下代码。

<phone:PhoneApplicationPage 
    x:Class="PhoneApp2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">

    <!--LayoutRoot 是包含所有页面内容的根网格-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel 包含应用程序的名称和页标题-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="我的应用程序" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="PPT播放" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel - 在此处放置其他内容-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid Grid.Row="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0" VerticalAlignment="Center" Text="服务器IP:" />
                <TextBox Name="txtServerIP" Grid.Column="1" Text="" />
                <Button Grid.Column="2" Content="连接" Click="onConnect"/>
            </Grid>
          
                <Button Content="播放" Click="onPlay" Width="154" Margin="54,0,248,463" Grid.Row="1" />
                <Button Content="下一张" Click="onPlayNext" Margin="0,78,21,358" Grid.Row="1" HorizontalAlignment="Right" Width="197" />
            <Button Content="上一张" Click="onPlayBack" Margin="6,78,248,358" Grid.Row="1" />
                <Button Content="暂停" Click="onPause" Width="143" Margin="237,0,75,463" Grid.Row="1" />
                <TextBlock Name="txtbInfo"  Margin="6,475,0,6" Grid.Row="1" />
            <Image Grid.Row="1" Height="281" HorizontalAlignment="Left" Margin="12,170,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="423" Tap="image1_Tap" />
        </Grid>
    </Grid>

    <!--演示 ApplicationBar 用法的示例代码-->
    <!--<phone:PhoneApplicationPage.ApplicationBar>  
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">  
            <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="按钮 1"/>  
            <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="按钮 2"/>  
            <shell:ApplicationBar.MenuItems>  
                <shell:ApplicationBarMenuItem Text="菜单项 1"/>  
                <shell:ApplicationBarMenuItem Text="菜单项 2"/>  
            </shell:ApplicationBar.MenuItems>  
        </shell:ApplicationBar>  
    </phone:PhoneApplicationPage.ApplicationBar>-->

</phone:PhoneApplicationPage>  

3、打开MainPage.xaml.cs,输入以下代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.IO;
using System.Windows.Media.Imaging;

namespace PhoneApp2
{
    public partial class MainPage : PhoneApplicationPage
    {
        Socket mySocket = null;
        ManualResetEvent MyEvent = null;
        Byte[] imgbyte = new Byte[262144];
        // 构造函数   
        public MainPage()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            if (mySocket == null)
            {
                mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                mySocket.ReceiveBufferSize = 262144;
               
            }
            if (MyEvent == null)
            {
                MyEvent = new ManualResetEvent(false);
            }
        }

        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            try
            {
                if (mySocket != null)
                {
                    mySocket.Shutdown(SocketShutdown.Both);
                    mySocket.Close();
                }
                base.OnNavigatedFrom(e);
            }
            catch 
            {
                base.OnNavigatedFrom(e);
            }
        }

        private void onConnect(object sender, RoutedEventArgs e)
        {
            if (mySocket != null)
            {
                SocketAsyncEventArgs connArg = new SocketAsyncEventArgs();
                if(this.txtServerIP.Text=="")
                {
                    txtbInfo.Text="请输入正确的ip";
                    return;
                 }
                // 要连接的远程服务器   
                connArg.RemoteEndPoint = new DnsEndPoint(this.txtServerIP.Text, 1377);
               
                // 操作完成后的回调   
                connArg.Completed += (sendObj, arg) =>
                {
                    if (arg.SocketError == SocketError.Success) //连接成功   
                    {
                        Dispatcher.BeginInvoke(() => txtbInfo.Text = "连接成功。");
                        
                        imgbyte = arg.Buffer;
                    }
                    else
                    {
                        Dispatcher.BeginInvoke(() =>
                        {
                            txtbInfo.Text = "连接失败,错误:" + arg.SocketError.ToString();
                        });
                    }
                    // 向调用线程报告操作结束   
                    MyEvent.Set();
                };
                // 重置线程等待事件   
                MyEvent.Reset();
                txtbInfo.Text = "正在连接,请等候……";
                // 开始异连接   
                mySocket.ConnectAsync(connArg);
                // 等待连接完成   
                MyEvent.WaitOne(6000);
            }
        }
        Byte[] imgInfo;
        private void onPlayNext(object sender, RoutedEventArgs e)
        {
            SendCommand("playNext");
            receiveImg();
          
        }
        private void receiveImg()
        {
            try
            {
                imgInfo = ReceiveInfo();
                MemoryStream ms = new MemoryStream(imgInfo);
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.SetSource(ms);
                WriteableBitmap writeableBitmap = new WriteableBitmap(bitmapImage);

                this.image1.Source = writeableBitmap;
            }
            catch
            {
                SendCommand("newimg");
            }
        }
        private void onPlayBack(object sender, RoutedEventArgs e)
        {
            SendCommand("playBack");
            receiveImg();
        }
        private void onPlay(object sender, RoutedEventArgs e)
        {
            SendCommand("play");
            receiveImg();
        }

        private void onPause(object sender, RoutedEventArgs e)
        {
            SendCommand("pause");
           receiveImg();
        }
        int i = 0;
        byte[] received = new Byte[1024 *9]; 
        private byte[] ReceiveInfo()
        {
          
            if (mySocket != null && mySocket.Connected)
            {
                SocketAsyncEventArgs receiveArg = new SocketAsyncEventArgs();
                
                byte[] buffer = new byte[1024];
                receiveArg.SetBuffer(buffer, 0, buffer.Length);
                receiveArg.Completed += new EventHandler<SocketAsyncEventArgs>(receiveArg_Completed);
                MyEvent.Reset();
                mySocket.ReceiveAsync(receiveArg);
                MyEvent.WaitOne(500);
            }
            return received;

        }

        void receiveArg_Completed(object sender, SocketAsyncEventArgs mArg)
        {
            
            if (mArg.SocketError == SocketError.Success)
            {
               if (i < 9)
                {
                    Buffer.BlockCopy(mArg.Buffer,0,received,i * 1024, 1024);

                    i++;
                    ReceiveInfo();
                }
                MyEvent.Set();
                mArg.Dispose();
            }
           
        }


        private void SendCommand(string txt)
        {
            i = 0;
            if (mySocket != null && mySocket.Connected)
            {
                SocketAsyncEventArgs sendArg = new SocketAsyncEventArgs();
           
                byte[] buffer = System.Text.Encoding.UTF8.GetBytes(txt);
                sendArg.SetBuffer(buffer, 0, buffer.Length);
                // 发送完成后的回调   
                sendArg.Completed += (objSender, mArg) =>
                {
                    // 如果操作成功                       
                    if (mArg.SocketError == SocketError.Success)
                    {
                        Dispatcher.BeginInvoke(() => txtbInfo.Text = "发送成功。");
                       
                    }
                  
                    else
                    {
                        Dispatcher.BeginInvoke(() =>
                        {
                            this.txtbInfo.Text = "发送失败,错误:" + mArg.SocketError.ToString();
                           
                        });
                    }
                    // 报告异步操作结束   
                    MyEvent.Set();
                };
                // 重置信号   
                MyEvent.Reset();
                txtbInfo.Text = "正在发送,请等候……";
                // 异步发送   
                mySocket.SendAsync(sendArg);
                // 等待操作完成   
                MyEvent.WaitOne(6000);
            }
        }


        private void image1_Tap(object sender, GestureEventArgs e)
        {
            SendCommand("newimg");
             receiveImg();
        }
    }
}

第一部分 服务器端

1、新建WPF应用程序项目。(我这里的名称是叫做WpfApplication4)

2、打开MainWindow.xaml文件,输入以下XAML代码。

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="服务器端" Height="350" Width="525">         
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        
        <TextBlock Name="txtDisplay2" Grid.Row="1" Margin="240,0,12,0" />
        <TextBlock Name="txtDisplay" Grid.Row="1" Margin="0,0,261,0" />
        <TextBlock Height="181" TextWrapping="Wrap" HorizontalAlignment="Left" Margin="88,60,0,0" Name="textBlock1"  VerticalAlignment="Top" FontSize="25" Width="319" >
            打开客户端,输入服务器ip后,将程序最小化,打开需要的ppt。
        </TextBlock>
    </Grid>
</Window>  

3.MainWindow.xaml.cs的代码如下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Forms;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;

namespace WpfApplication4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {


        Socket Server;
        Byte[] imgInfo=new Byte[1024*5];
        public MainWindow()
        {
            InitializeComponent();
            InitialTray();

            // 从资源中把Key为std的Storyboard读出来   
         
            // 声明用于监听连接请求的Socket   
           Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //
         
           string strHostName = Dns.GetHostName();
         
            //得到本机的主机名 
            IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
            ////取得本机IP 
            IPAddress strAddr = ipEntry.AddressList[7];//.ToString();
            txtDisplay2.Text = "服务器IP:" + strAddr.ToString();//假设本地主机为单网卡
            //
            IPEndPoint local = new IPEndPoint(IPAddress.Any, 1377); //监听所有网络接口上的地址   
            Server.Bind(local);// 绑定本地终结点   
            Server.Listen(100);// 侦听连接请求   
            // 开始异步接受传入的连接请求   
            Server.BeginAccept(new AsyncCallback(this.AcceptSocketCallback), Server);
        }
        private System.Windows.Forms.NotifyIcon notifyIcon = null;
        
         private void InitialTray()
        {

            //设置托盘的各个属性
            notifyIcon = new System.Windows.Forms.NotifyIcon();
            notifyIcon.BalloonTipText = "程序开始运行";
            notifyIcon.Text = "ppt服务端";
            notifyIcon.Icon = new System.Drawing.Icon("Downloads.ico");
            notifyIcon.Visible = true;
            notifyIcon.ShowBalloonTip(2000);
            notifyIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(notifyIcon_MouseClick);

         
            //退出菜单项
            System.Windows.Forms.MenuItem exit = new System.Windows.Forms.MenuItem("exit");
            exit.Click += new EventHandler(exit_Click);

            //关联托盘控件
            System.Windows.Forms.MenuItem[] childen = new System.Windows.Forms.MenuItem[] { exit };
            notifyIcon.ContextMenu = new System.Windows.Forms.ContextMenu(childen);

            //窗体状态改变时候触发
            this.StateChanged += new EventHandler(SysTray_StateChanged);
        }
        ///
        /// 窗体状态改变时候触发
        ///
        ///

        ///

        private void SysTray_StateChanged(object sender, EventArgs e)
        {
            if (this.WindowState == WindowState.Minimized)
            {
                this.Visibility = Visibility.Hidden;
            }
        }

        ///
        /// 退出选项
        ///
        ///

        ///

        private void exit_Click(object sender, EventArgs e)
        {
            if (System.Windows.MessageBox.Show("确定要关闭吗?",
                                               "退出",
                                                MessageBoxButton.YesNo,
                                                MessageBoxImage.Question,
                                                MessageBoxResult.No) == MessageBoxResult.Yes)
            {
                notifyIcon.Dispose();
                System.Windows.Application.Current.Shutdown();
            }
        }

        ///
        /// 鼠标单击
        ///
        ///

        ///

        private void notifyIcon_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (this.Visibility == Visibility.Visible)
                {
                    this.Visibility = Visibility.Hidden;
                   
                }
                else
                {
                    this.Visibility = Visibility.Visible;
                   
                    this.Activate();
                }
            }
        }

        //
        /// <summary>   
        /// 接受传入的Socket的回调   
        /// </summary>   
        private void AcceptSocketCallback(IAsyncResult ia)
        {
            Socket _socket = ia.AsyncState as Socket;
            Socket accptSocket = _socket.EndAccept(ia);
            try
            {
                IPEndPoint remote = (IPEndPoint)accptSocket.RemoteEndPoint;
                // 显示客户端的IP   
                Dispatcher.BeginInvoke(new Action<string>(this.SetIPForText), remote.Address.ToString());
                StateObject so = new StateObject();
                so.theSocket = accptSocket;
                // 开始异步接收消息   
                accptSocket.BeginReceive(so.Buffer, 0, so.Buffer.Length, SocketFlags.None, new AsyncCallback(this.ReceiveCallback), so);
            }
            catch
            {

            }
            // 继续接受连接请求   
            _socket.BeginAccept(new AsyncCallback(this.AcceptSocketCallback), _socket);
        }
        /// <summary>   
        /// 接收消息的回调   
        /// </summary>   
        private void ReceiveCallback(IAsyncResult ia)
        {
            StateObject _so = ia.AsyncState as StateObject;
            Socket _socket = _so.theSocket;
            try
            {
                int n = _socket.EndReceive(ia);//n就是接收到的字节数   
                string msg = Encoding.UTF8.GetString(_so.Buffer, 0, n);
                
                // 判断客户端发送了啥命令   
                switch (msg)
                {
                    case "playNext":
                       
                        System.Windows.Forms.SendKeys.SendWait("{Right}");
                        SendCommand(_socket, CatchScreen());
                        break;
                    case "playBack":
                       
                        System.Windows.Forms.SendKeys.SendWait("{Left}");
                        SendCommand(_socket, CatchScreen());
                        break;
                    case "pause":
                       
                        System.Windows.Forms.SendKeys.SendWait("{B}");
                        SendCommand(_socket, CatchScreen());
                        break;
                    case "play":
                       
                        System.Windows.Forms.SendKeys.SendWait("{F5}");
                        SendCommand(_socket, CatchScreen());
                        break;
                    case "newimg":
                        SendCommand(_socket, CatchScreen());
                        break;
                    default:
                        break;
                }
            }
            catch
            {
            }
            _so = new StateObject();
            _so.theSocket = _socket;
            // 继续接收消息   
            _socket.BeginReceive(_so.Buffer,
                                0,
                                _so.Buffer.Length,
                                SocketFlags.None,
                                new AsyncCallback(this.ReceiveCallback),
                                _so);
        }

        
        private void SendCommand(Socket handler,byte[] imginfo)
        {
           
            try
            {
                handler.BeginSend(imginfo, 0, imginfo.Length, 0, new AsyncCallback(SendCallBack), handler);
            }
            catch
            {
            }
      
        }
        private void SendCallBack(IAsyncResult ar)
        {
            try
            {
                Socket handler = (Socket)ar.AsyncState;
                int bytesSend = handler.EndSend(ar);
                if (bytesSend > 0)
                {
                    Console.WriteLine("Succeed");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

        }
        private byte[]  CatchScreen()
        {
            Screen scr = Screen.PrimaryScreen;
            System.Drawing.Rectangle rc = scr.Bounds;
            int iWidth = rc.Width;
            int iHeight = rc.Height;
            //创建一个和屏幕一样大的Bitmap
            System.Drawing.Image myImage = new Bitmap(iWidth, iHeight);
           
            //从一个继承自Image类的对象中创建Graphics对象
            Graphics g = Graphics.FromImage(myImage);
          
            g.CopyFromScreen(new System.Drawing.Point(0, 0), new System.Drawing.Point(0, 0), new System.Drawing.Size(iWidth, iHeight));   
            return ImgToByt(myImage.GetThumbnailImage(iWidth / 6, iHeight/6, new System.Drawing.Image.GetThumbnailImageAbort(CallBack), IntPtr.Zero));
        }
        private static bool CallBack()
        {
            return false;
            
        }

        public  byte[] ImgToByt(System.Drawing.Image img)
        {
            MemoryStream ms = new MemoryStream();
            byte[] imagedata = new Byte[1024 * 9];// null;
            byte[] imagedata2 = null;
            img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
             imagedata2 = ms.GetBuffer();
             Buffer.BlockCopy(imagedata2, 0, imagedata, 0, imagedata2.Length);
            return imagedata;
        }
        /// <summary> 
        /// 字节流转换成图片 
        /// </summary> 
        /// <param name="byt">要转换的字节流</param> 
        /// <returns>转换得到的Image对象</returns> 
        public System.Drawing.Image BytToImg(byte[] byt)
        {
            MemoryStream ms = new MemoryStream(byt);
            System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
            return img;
        } 
        /// <summary>   
        /// 显示客户端的IP   
        /// </summary>   
        private void SetIPForText(string ip)
        {
            this.txtDisplay.Text = "客户端IP:" + ip;
        }

      
    }

    /// <summary>   
    /// 用于异步Socket操作传递的状态对象   
    /// </summary>   
    public class StateObject
    {
        private const int BUFFER_SIZE = 512;

        public byte[] Buffer { get; set; }

        public Socket theSocket { get; set; }

        /// <summary>   
        /// 构造函数   
        /// </summary>   
        public StateObject()
        {
            this.Buffer = new byte[BUFFER_SIZE];
        }
    }
}

4.新建一个叫做KeyboardToolkit.cs的类,用于模拟键盘消息,代码如下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.ComponentModel;

namespace WpfApplication4
{
    class KeyboardToolkit
    {
        internal static class NativeMethods
        {
            #region User32
            // Various Win32 constants
            internal const int KeyeventfKeyup = 0x0002;
            internal const int KeyeventfScancode = 0x0008;
            internal const int InputKeyboard = 1;

            // Various Win32 data structures
            [StructLayout(LayoutKind.Sequential)]
            internal struct INPUT
            {
                internal int type;
                internal INPUTUNION union;
            };

            [StructLayout(LayoutKind.Explicit)]
            internal struct INPUTUNION
            {
                [FieldOffset(0)]
                internal MOUSEINPUT mouseInput;
                [FieldOffset(0)]
                internal KEYBDINPUT keyboardInput;
            };

            [StructLayout(LayoutKind.Sequential)]
            internal struct MOUSEINPUT
            {
                internal int dx;
                internal int dy;
                internal int mouseData;
                internal int dwFlags;
                internal int time;
                internal IntPtr dwExtraInfo;
            };

            [StructLayout(LayoutKind.Sequential)]
            internal struct KEYBDINPUT
            {
                internal short wVk;
                internal short wScan;
                internal int dwFlags;
                internal int time;
                internal IntPtr dwExtraInfo;
            };

            // Importing various Win32 APIs that we need for input
            [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
            internal static extern int GetSystemMetrics(int nIndex);

            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            internal static extern int MapVirtualKey(int nVirtKey, int nMapType);

            [DllImport("user32.dll", SetLastError = true)]
            internal static extern int SendInput(int nInputs, ref INPUT mi, int cbSize);

            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            internal static extern short VkKeyScan(char ch);

            #endregion User32
        }

        public static class Keyboard
        {
            /// <summary>
            /// Presses down a key.
            /// </summary>
            /// <param name="key">The key to press.</param>
            public static void Press(Key key)
            {
                SendKeyboardInput(key, true);
            }

            /// <summary>
            /// Releases a key.
            /// </summary>
            /// <param name="key">The key to release.</param>
            public static void Release(Key key)
            {
                SendKeyboardInput(key, false);
            }

            /// <summary>
            /// Resets the system keyboard to a clean state.
            /// </summary>
            public static void Reset()
            {
                foreach (Key key in Enum.GetValues(typeof(Key)))
                {
                    if (key != Key.None && (System.Windows.Input.Keyboard.GetKeyStates(key) & KeyStates.Down) > 0)
                    {
                        Release(key);
                    }
                }
            }

            /// <summary>
            /// Performs a press-and-release operation for the specified key, which is effectively equivallent to typing.
            /// </summary>
            /// <param name="key">The key to press.</param>
            public static void Type(Key key)
            {
                Press(key);
                System.Threading.Thread.Sleep(100);
                Release(key);
            }



            [PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
            private static void SendKeyboardInput(Key key, bool press)
            {
                PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted);
                permissions.Demand();

                NativeMethods.INPUT ki = new NativeMethods.INPUT();
                ki.type = NativeMethods.InputKeyboard;
                ki.union.keyboardInput.wVk = (short)KeyInterop.VirtualKeyFromKey(key);
                ki.union.keyboardInput.wScan = (short)NativeMethods.MapVirtualKey(ki.union.keyboardInput.wVk, 0);

                int dwFlags = 0;

                if (ki.union.keyboardInput.wScan > 0)
                {
                    dwFlags |= NativeMethods.KeyeventfScancode;
                }

                if (!press)
                {
                    dwFlags |= NativeMethods.KeyeventfKeyup;
                }

                ki.union.keyboardInput.dwFlags = dwFlags;

                ki.union.keyboardInput.time = 0;
                ki.union.keyboardInput.dwExtraInfo = new IntPtr(0);

                if (NativeMethods.SendInput(1, ref ki, Marshal.SizeOf(ki)) == 0)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }

        }
    }
}

先打开服务端

在手机客户端,输入服务器端的IP地址,点击连接,连接成功后就可以进行操作了

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小巫技术博客

Retrofit2 &amp; RxJava2实现单文件和多文件上传

4884
来自专栏跟着阿笨一起玩NET

C# TreeView使用技巧

代码中对事件参数e.Action的判断,可以避免在改变节点的Checked的状态时,再次进入AfterCheck(),这样当在AfterCheck()中有其他逻...

1152
来自专栏王磊的博客

LINQ能不能用系列(二)LINQ to SQL 效率比对

前言 很多人听说过LINQ TO SQL与ADO.NET传统方式用于不同的环境,LINQ TO SQL与ADO.NET传统方式也没有可比性,就像公交车与私家车一...

2885
来自专栏菩提树下的杨过

ExtJs学习笔记(6)_可分页的GridPanel

一.WCF部分 1.通过查看官方的示例得知,分页数据源需要一个记录总数值,为保持通用性,这里借鉴jillZhang的文章,把他写的通用类PageData拿过来...

2148
来自专栏進无尽的文章

关于-performSelector的使用

在ARC项目中使用 performSelector: 函数出现“performSelector may cause a leak because its sel...

1404
来自专栏Kubernetes

kube-proxy源码分析

##kube-proxy介绍 请参考我的另一篇博文:kube-proxy工作原理 ##源码目录结构分析 cmd/kube-proxy //负责kub...

6515
来自专栏ShaoYL

自欺欺人的使用 NSTimer 销毁

1666
来自专栏码匠的流水账

聊聊spring cloud gateway的RetryGatewayFilter

本文主要研究一下spring cloud gateway的RetryGatewayFilter

1552
来自专栏c#开发者

在DataGrid中创建一个弹出式Details窗口

在DataGrid中创建一个弹出式Details窗口 这篇文章来自DotNetJunkie的提议。他最初写信要求我们提供一个关于如何创建在DataGrid 中...

3808
来自专栏AhDung

【C#】分享基于Win32 API的服务操作类(解决ManagedInstallerClass.InstallHelper不能带参数安装的问题)

------------------201508250915更新------------------

1352

扫码关注云+社区