C# 串口模拟键盘输入

      最近遇到一个需求:需要在网站的文本输入栏上输入条码和回车; 查了一下资料,记录如下:

     最后的方案: 两台电脑用串口连接,从A机器发送信息到串口, B机器从串口读到信息,并模拟键盘输出。 

  

 public class CKeyController
    {
        [System.Runtime.InteropServices.DllImport("user32")]
        static extern void keybd_event(
            byte bVk,
            byte bScan,
            uint dwFlags,
            uint dwExtraInfo
            );
        const uint KEYEVENTF_EXTENDEDKEY = 0x1;
        const uint KEYEVENTF_KEYUP = 0x2;
        private static Dictionary keycode = new Dictionary();

        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
        [DllImport("User32.DLL")]
        public static extern int SendMessage(IntPtr hWnd,uint Msg, int wParam, string lParam);
        [DllImport("User32.DLL")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

        [DllImport("User32.DLL")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent,
            IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
        public const uint WM_SETTEXT = 0x000C;
        public const uint WM_CHAR = 0x0102;
        public static int WM_KEYDOWN = 0x0100;
        //释放一个键
        public static int WM_KEYUP = 0x0101;

        public void InitKey()
        {
            keycode = new Dictionary();
            keycode.Add("A", 65);
            keycode.Add("B", 66);
            keycode.Add("C", 67);
            keycode.Add("D", 68);
            keycode.Add("E", 69);
            keycode.Add("F", 70);
            keycode.Add("G", 71);
            keycode.Add("H", 72);
            keycode.Add("I", 73);
            keycode.Add("J", 74);
            keycode.Add("K", 75);
            keycode.Add("L", 76);
            keycode.Add("M", 77);
            keycode.Add("N", 78);
            keycode.Add("O", 79);
            keycode.Add("P", 80);
            keycode.Add("Q", 81);
            keycode.Add("R", 82);
            keycode.Add("S", 83);
            keycode.Add("T", 84);
            keycode.Add("U", 85);
            keycode.Add("V", 86);
            keycode.Add("W", 87);
            keycode.Add("X", 88);
            keycode.Add("Y", 89);
            keycode.Add("Z", 90);
            keycode.Add("0", 48);
            keycode.Add("1", 49);
            keycode.Add("2", 50);
            keycode.Add("3", 51);
            keycode.Add("4", 52);
            keycode.Add("5", 53);
            keycode.Add("6", 54);
            keycode.Add("7", 55);
            keycode.Add("8", 56);
            keycode.Add("9", 57);
            keycode.Add(".", 0x6E);
            keycode.Add("LEFT", 0x25);
            keycode.Add("UP", 0x26);
            keycode.Add("RIGHT", 0x27);
            keycode.Add("DOWN", 0x28);
            keycode.Add("-", 0x6D);
            keycode.Add("{ENTER}", 13);
        }

        public static void KeyBoardDo(string key)
        {
            keybd_event(keycode[key], 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0);
            keybd_event(keycode[key], 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
        }

        /// 
        /// 使用keybd_event发送。 缺点是不能指定接受的窗口名称;接受窗口必须为当前活动窗口。
        /// 
        /// 
        public void SendBarcode(string barcode)
        {
            for (int k = 0; k < barcode.Length; k++)
            {
                string ak = barcode.Substring(k, 1);
                KeyBoardDo(ak);
            }
            KeyBoardDo("{ENTER}");
        }


        /// 
        /// 
        /// 
        /// 
        public void SendKeys(string barcode)
        {
            System.Windows.Forms.SendKeys.Send(barcode);
            System.Windows.Forms.SendKeys.Send("{ENTER}");
        }


        /// 
        ///可以指定窗口,并且窗口可以为不活动状态; 即应用程序不在显示器最上层。
        /// 
        /// 
        public void SendKeyByMessage(string hello)
        {
            System.Diagnostics.Process[] GamesProcess = System.Diagnostics.Process.GetProcessesByName("notepad");
            if (GamesProcess.Length == 0) return;

            IntPtr hWnd = FindWindowEx(GamesProcess[0].MainWindowHandle,
            IntPtr.Zero, "Edit", null);           

            //SendMessage(hWnd, WM_SETTEXT, 0, hello); //清空记事本中内容;写入字符;并且光标回到第一行第一个位置。
            int key = 0;
            for (int k = 0; k < hello.Length; k++)
            {
                string ak = hello.Substring(k, 1);
                key = keycode[ak];
                SendMessage(hWnd, WM_CHAR, key, 0);
            }

            key = keycode["{ENTER}"];
            SendMessage(hWnd, WM_CHAR, key, 0);      //往记事本中添加内容。     
        }

    }


  类中有3中将字符串输出的功能:

1. 

keybd_event: 不能指定输出对象
2. 
SendMessage(hWnd, WM_CHAR, key, 0); 
输出一个字符到指定的窗口。
SendMessage(hWnd, WM_SETTEXT, 0, hello);
 清空记事本中内容;写入字符;并且光标回到第一行第一个位置。 

 
  
 
  
3. 
SendKeys
这个一直没有实验成功,一直会有软件不响应;除非使用手动激活其他窗口。 具体原因没有细查。

串口控制代码
 public class CComController
    {
        private SerialPort sp = null;

        /// 
        /// 打开串口
        /// 
        /// 串口号
        /// 波特率
        /// 数据位
        /// 停止位
        /// /// 校验位
        /// 
        public bool OpenCom(string protName, int baudRate, int dataBit, float stopBits, int parity)
        {
            bool flag = true;
            if (sp == null)
            {
                sp = new SerialPort();
            }
            sp.PortName = protName;//串口号
            sp.BaudRate = baudRate;//波特率
            sp.ReadTimeout = 10;
            float f = stopBits;//停止位
            if (f == 0)
            {
                sp.StopBits = StopBits.None;
            }
            else if (f == 1.5)
            {
                sp.StopBits = StopBits.OnePointFive;
            }
            else if (f == 1)
            {
                sp.StopBits = StopBits.One;
            }
            else
            {
                sp.StopBits = StopBits.Two;
            }

            sp.DataBits = dataBit;//数据位

            if (parity == 0)
            {
                sp.Parity = Parity.None;
            }
            else if (parity == 1)
            {
                sp.Parity = Parity.Odd;
            }
            else if (parity == 2)
            {
                sp.Parity = Parity.Even;
            }
            else
            {
                sp.Parity = Parity.None;
            }
           
            try
            {
                if (!sp.IsOpen)
                {
                    sp.Open();
                }
            }
            catch (Exception)
            {
                flag = false;
            }
            return flag;
        }

        /// 
        /// 关闭端口
        /// 
        /// 
        public bool CloseCom()
        {
            try
            {
                if (sp.IsOpen)
                {
                    sp.Close();
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public string ReadLine()
        {
            try
            {
                string receive = sp.ReadLine();
                return receive;
            }
            catch (Exception ex)
            {
                return "";
            }
        }

        public bool WriteLine(string barcode)
        {
            sp.WriteLine(barcode);
            return true;
        }
    }


 
  
客户端代码:
 public partial class Form1 : Form
    {
        CComController com;
        public Form1()
        {
            InitializeComponent();




            com = new CComController();
            com.OpenCom("COM1", 115200, 8, 1, 0);
        }


        public void SendBarcode()
        {


            
        }


        private void btnSend_Click(object sender, EventArgs e)
        {           
            string barcode = txtBarcode.Text;
            com.WriteLine(barcode);
        }
    }

服务端:
namespace ComServer
{
    public partial class Form1 : Form
    {
        CComController comController;
        CKeyController keyController;
        public Form1()
        {
            InitializeComponent();
            //textBox1.Focus();


            comController = new CComController();
            comController.OpenCom("COM1", 115200, 8, 1, 0);
            
            keyController = new CKeyController();
            keyController.InitKey();
            Thread readThread = new Thread(new ThreadStart(ThreadReadBarcode));
            readThread.Start();
        }


        public void ThreadReadBarcode()
        {
            while (true)
            {
                string barcode = comController.ReadLine();
                if (barcode != "" && barcode != null)
                {                    
                    keyController.SendKeyByMessage(barcode);                    
                }


                Thread.Sleep(200);
            }
        }
    }
}


点击打开链接;网上看到的资料
 
  
 
  


你可能感兴趣的:(C# 串口模拟键盘输入)