1. 程式人生 > >C#:小工具專案-軟鍵盤實現

C#:小工具專案-軟鍵盤實現

0.

之前有篇文章是講鍵盤改鍵,即把一個鍵盤鍵的功能改成另一種功能或組合功能。https://blog.csdn.net/qq_38261174/article/details/84952878

這篇文章主要是講在沒有物理鍵盤的情況下,如何用軟體替代物理鍵盤的功能,從而實現軟鍵盤。

Windows提供了一個模擬鍵盤API函式Keybd_event(),該函式能觸發一個按鍵事件,也就是說會產生一個WM_KEYDOWN或WM_KEYUP訊息。 
    
   [DllImport("user32.dll", EntryPoint = "keybd_event")]
        public static extern void keybd_event(
            byte bVk,    //虛擬鍵值
            byte bScan,// 一般為0
            int dwFlags,  //這裡是整數型別  0 為按下,2為釋放
            int dwExtraInfo  //這裡是整數型別 一般情況下設成為 0
        );

介面設計如下:

程式碼如下:

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace SoftKeyBoard {
    public partial class Form1 : Form {

        #region 把當前窗體設定為浮動工具條。不會影響其它程序的窗體的游標焦點。雖然這個窗體現在為當前啟用的前臺窗體,但游標仍然停在其他程序的窗體上
        private const int WS_EX_TOOLWINDOW = 0x00000080;
        private const int WS_EX_NOACTIVATE = 0x08000000;
        //重寫該方法實現窗體變為浮動工具條,不獲取游標焦點
        protected override CreateParams CreateParams {
            get {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= (WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW);
                cp.Parent = IntPtr.Zero;
                return cp;
            }
        }
        #endregion

        public Form1() {
            this.TopMost = true;
            InitializeComponent();
        }

        //模擬鍵盤API  鍵值用byte最準確
        [DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true)]
        public static extern void keybd_event1(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
        #region 系統全域性 大小寫按鍵
        bool isCapitalization = false; //是否大寫,預設小寫
        private void 大小寫_Click(object sender, EventArgs e) {
            const int KEYEVENTF_EXTENDEDKEY = 0x1;
            const int KEYEVENTF_KEYUP = 0x2;
            keybd_event1(0x14, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
            keybd_event1(0x14, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
            if (!isCapitalization) {
                this.label1.Text = "目前:大寫";
                isCapitalization = true;
                this.大小寫.BackColor = Color.Blue;
            }
            else {
                this.label1.Text = "目前:小寫";
                isCapitalization = false;
                this.大小寫.BackColor = Color.White;
            }
        }


        #endregion

        //模擬鍵盤API  和上面的API引數型別有區別   鍵值用Keys,大部分準確
        [DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true)]
        public static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
        #region 系統全域性 windows鍵
        private void Windows_Click(object sender, EventArgs e) {
            keybd_event(Keys.LWin, 0, 0, 0);
            keybd_event(Keys.LWin, 0, 2, 0);

            //注意點:一定要按下,再釋放,有些功能才會有果(ctrl   shift   等)。 0代表按下,2代表釋放
            //下面2行程式碼同樣可以做到 系統全域性-大小寫
            //keybd_event(Keys.CapsLock,0,0,0);
            //keybd_event(Keys.CapsLock, 0, 2, 0);
        }
        #endregion

        #region Ctrl 是否按下
        bool isCtrl = false;
        private void CtrlClick(object sender, EventArgs e) {
            if (!isCtrl) {
                isCtrl = true;
                this.label2.Text = "ctrl已按下";
                this.button80.BackColor = Color.Blue;
            }
            else {
                isCtrl = false;
                this.label2.Text = "ctrl未按下";
                this.button80.BackColor = Color.White;
            }
        }
        #endregion
        
        #region 數字鍵   多個虛擬數字鍵按鈕-統一監聽
        private void NUmberClick(object sender, EventArgs e) {
            int number = Convert.ToInt32(((Button)sender).Text); //0 1 2 3 4 5 6 7 8 9
            switch (number) {
                case 0:
                    keybd_event(Keys.D0, 0, 0, 0);
                    break;
                case 1:
                    keybd_event(Keys.D1, 0, 0, 0);
                    break;
                case 2:
                    keybd_event(Keys.D2, 0, 0, 0);
                    break;
                case 3:
                    keybd_event(Keys.D3, 0, 0, 0);
                    break;
                case 4:
                    keybd_event(Keys.D4, 0, 0, 0);
                    break;
                case 5:
                    keybd_event(Keys.D5, 0, 0, 0);
                    break;
                case 6:
                    keybd_event(Keys.D6, 0, 0, 0);
                    break;
                case 7:
                    keybd_event(Keys.D7, 0, 0, 0);
                    break;
                case 8:
                    keybd_event(Keys.D8, 0, 0, 0);
                    break;
                case 9:
                    keybd_event(Keys.D9, 0, 0, 0);
                    break;
            }
        }
        #endregion

        #region 字母鍵,組合鍵   多個虛擬字母鍵按鈕-統一監聽
        private void CharClick(object sender, EventArgs e) {
            String cr = ((Button)sender).Text;
            switch (cr) {
                case "a":
                    if (isCtrl) { //組合鍵 ctrl + a   示例:其它組合鍵,自行摸索
                        keybd_event(Keys.ControlKey, 0, 0, 0);
                        keybd_event(Keys.A, 0, 0, 0);
                        keybd_event(Keys.ControlKey, 0, 2, 0);
                        keybd_event(Keys.A, 0, 2, 0);
                    }
                    else {
                        keybd_event(Keys.A, 0, 0, 0);
                    }
                    break;
                case "b":
                    keybd_event(Keys.B, 0, 0, 0);
                    break;
                case "c":
                    keybd_event(Keys.C, 0, 0, 0);
                    break;
                case "d":
                    keybd_event(Keys.D, 0, 0, 0);
                    break;
                case "e":
                    keybd_event(Keys.E, 0, 0, 0);
                    break;
                case "f":
                    keybd_event(Keys.F, 0, 0, 0);
                    break;
                case "g":
                    keybd_event(Keys.G, 0, 0, 0);
                    break;
                case "h":
                    keybd_event(Keys.H, 0, 0, 0);
                    break;
                case "i":
                    keybd_event(Keys.I, 0, 0, 0);
                    break;
                case "j":
                    keybd_event(Keys.J, 0, 0, 0);
                    break;
                case "k":
                    keybd_event(Keys.K, 0, 0, 0);
                    break;
                case "l":
                    keybd_event(Keys.L, 0, 0, 0);
                    break;
                case "m":
                    keybd_event(Keys.M, 0, 0, 0);
                    break;
                case "n":
                    keybd_event(Keys.N, 0, 0, 0);
                    break;
                case "o":
                    keybd_event(Keys.O, 0, 0, 0);
                    break;
                case "p":
                    keybd_event(Keys.P, 0, 0, 0);
                    break;
                case "q":
                    keybd_event(Keys.Q, 0, 0, 0);
                    break;
                case "r":
                    keybd_event(Keys.R, 0, 0, 0);
                    break;
                case "s":
                    keybd_event(Keys.S, 0, 0, 0);
                    break;
                case "t":
                    keybd_event(Keys.T, 0, 0, 0);
                    break;
                case "u":
                    keybd_event(Keys.U, 0, 0, 0);
                    break;
                case "v":
                    keybd_event(Keys.V, 0, 0, 0);
                    break;
                case "w":
                    keybd_event(Keys.W, 0, 0, 0);
                    break;
                case "x":
                    keybd_event(Keys.X, 0, 0, 0);
                    break;
                case "y":
                    keybd_event(Keys.Y, 0, 0, 0);
                    break;
                case "z":
                    keybd_event(Keys.Z, 0, 0, 0);
                    break;
             }
        }
        #endregion

        #region F1-F12  虛擬鍵統一監聽
        private void FnClick(object sender, EventArgs e) {
            String fn = ((Button)sender).Text;
            switch (fn) {
                case "F1":
                    keybd_event(Keys.F1, 0, 0, 0);
                    break;
                case "F2":
                    keybd_event(Keys.F2, 0, 0, 0);
                    break;
                case "F3":
                    keybd_event(Keys.F3, 0, 0, 0);
                    break;
                case "F4":
                    keybd_event(Keys.F4, 0, 0, 0);
                    break;
                case "F5":
                    keybd_event(Keys.F5, 0, 0, 0);
                    break;
                case "F6":
                    keybd_event(Keys.F6, 0, 0, 0);
                    break;
                case "F7":
                    keybd_event(Keys.F7, 0, 0, 0);
                    break;
                case "F8":
                    keybd_event(Keys.F8, 0, 0, 0);
                    break;
                case "F9":
                    keybd_event(Keys.F9, 0, 0, 0);
                    break;
                case "F10":
                    keybd_event(Keys.F10, 0, 0, 0);
                    break;
                case "F11":
                    keybd_event(Keys.F11, 0, 0, 0);
                    break;
                case "F12":
                    keybd_event(Keys.F12, 0, 0, 0);
                    break;
            }
        }
        #endregion

        #region 右邊符號鍵   統一監聽 未完成全部程式碼
        private void LeftOtherClick(object sender, EventArgs e) {
            String otherChar = ((Button)sender).Text;
            switch (otherChar) {
                case "BackSpace":
                    keybd_event(Keys.Back, 0, 0, 0);
                    break;
                case "Enter":
                    keybd_event(Keys.Enter, 0, 0, 0);
                    break;
                case " ":
                    keybd_event(Keys.Space, 0, 0, 0);
                    break;
                //case "#":
                //    break;
                //case "$":
                //    break;
                //case "%":
                //    break;
                //case "^":
                //    break;
                //case "&&":
                //    break;
                //case "*":
                //    break;
                //case "(":
                //    break;
                //case ")":
                //    break;
                //case "":
                //    break;
                //case "":
                //    break;
                //todo   other

            }
        }
        #endregion

        //除了呼叫 user32.dll 實現模擬按鍵外,還有另外一種 SendKeys
        //組合鍵:Ctrl = ^    Shift = +    Alt = %
        private void button1_Click(object sender, EventArgs e) {
            //括號中的內容就是虛擬按鍵的內容,可以有如下值:
            //ENTER  BACKSPACE  END  HOME  DELETE   +   -   *   /   \\     等...
            SendKeys.Send("^+");  //ctrl + shift     由於用上面的user32.dll 我沒解決 ctrl +shift組合鍵的問題,所以這裡可以解決
            //SendKeys.Send("a"); //a  區分大小寫
            //SendKeys.Send("^{A}");  //ctrl + A

        }

    }
}

實現軟鍵盤,有幾個需要注意的地方:

  1. 窗體要設定為浮動工具條,不獲取其它窗體的游標焦點。不然的話,虛擬按鍵不知道在哪裡輸出
  2. 有一些特殊的鍵用user32.dll方法模擬時一定要 按下(0)和釋放(2)兩行程式碼才起作用。

 

完!

對應下載:https://github.com/520xchly/C-