<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      左眼水星

      導航

      C#模擬鍵盤輸入、鍵狀態和監聽鍵盤消息

      模擬鍵盤輸入

      模擬鍵盤輸入的功能需要依賴Windows函數實現,這個函數是SendInput,它是專門用來模擬鍵盤、鼠標等設備輸入的函數。

      另外和鍵盤輸入相關的函數還有SendKeys,它是System.Windows.Forms. SendKeys,只能在WinFrom項目中使用,并且它的所有功能都可以由SendInput來實現。

      另一個是keybd_event函數,這個函數依然是有用的,但是目前官方已經推薦使用SendInput替代它了。

      SendInput的定義
      [DllImport("user32.dll")]
      static extern uint SendInput(int nInputs,INPUT[] pInputs,int cbSize);

      INPUT對象中保存了輸入內容,nInputs和cbSize代表pInputs的長度和INPUT結構的大小,這兩個參數能幫助SendInput正確解析INPUT對象。返回值0表示失敗,非零表示正確執行。

       

      INPUT的定義
      [StructLayout(LayoutKind.Sequential)]
      struct KEYBDINPUT {
          public ushort wVk;
          public ushort wScan;
          public uint dwFlags;
          public uint time;
          public IntPtr dwExtraInfo;
      }
      [StructLayout(LayoutKind.Sequential)]
      struct HARDWAREINPUT {
          public uint uMsg;
          public ushort wParamL;
          public ushort wParamH;
      }
      [StructLayout(LayoutKind.Sequential)]
      struct MOUSEINPUT {
          public int dx;
          public int dy;
          public uint mouseData;
          public uint dwFlags;
          public uint time;
          public IntPtr dwExtraInfo;
      }
      [StructLayout(LayoutKind.Explicit)]
      struct MOUSEKEYBDHARDWAREINPUT {
          [FieldOffset(0)]
          public HARDWAREINPUT hi;
          [FieldOffset(0)]
          public KEYBDINPUT ki;
          [FieldOffset(0)]
          public MOUSEINPUT mi;
      }
      [StructLayout(LayoutKind.Sequential)]
      struct INPUT {
          public uint type;
          public MOUSEKEYBDHARDWAREINPUT mkhi;
      }

      INPUT結構中的type表示消息類型,值為1表示鍵盤消息。mkhi表示具體的消息內容,它可以模擬三類消息,其中鍵盤消息使用KEYBDINPUT表示,其它消息類型的結構不在這里介紹(雖然用不到MOUSEINPUT等結構,但是它們的定義不能省略,否則SendInput無法正確解析INPUT中的具體內容)。

      ?FieldOffset(0)將三個結構的起始都放在0位置,所以只能使用其中一個內容,因為一個INPUT也只能表示一個消息,這樣設計可以節省空間。

      KEYBDINPUT結構中的wVK表示虛擬鍵碼 ,dwFlags的第一位bit默認0表示鍵盤按下事件,1表示鍵盤釋放事件。

      虛擬鍵碼是一種能讓Windows以與設備無關的方式處理鍵盤的技術,可以簡單理解為:鍵盤上的每個鍵用一個數字來表示。

       

      模擬A鍵
      INPUT[] inputs = new INPUT[2];
      inputs[0]=new INPUT {
          type=1,
          mkhi=new MOUSEKEYBDHARDWAREINPUT {
              ki=new KEYBDINPUT {
                  wVk=0x41
              }
          }
      };
      inputs[1]=new INPUT {
          type=1,
          mkhi=new MOUSEKEYBDHARDWAREINPUT {
              ki=new KEYBDINPUT {
                  wVk=0x41,
                  dwFlags=2
              }
          }
      };
      SendInput(inputs.Length,inputs,Marshal.SizeOf(inputs[0]));

      A鍵的虛擬鍵碼是0x41。type=1表示這是鍵盤消息,dwFlags=2表示鍵盤釋放事件。

      這里INPUT數組模擬的就是使用物理鍵盤A鍵的過程。inputs[0]模擬A鍵按下,inputs[1]模擬A鍵釋放。

       

      模擬Ctrl+A
      INPUT[] inputs = new INPUT[4];
      inputs[0]=new INPUT {
          type=1,
          mkhi=new MOUSEKEYBDHARDWAREINPUT {
              ki=new KEYBDINPUT {
                  wVk=0x11
              }
          }
      };
      inputs[1]=new INPUT {
          type=1,
          mkhi=new MOUSEKEYBDHARDWAREINPUT {
              ki=new KEYBDINPUT {
                  wVk=0x41
              }
          }
      };
      inputs[2]=new INPUT {
          type=1,
          mkhi=new MOUSEKEYBDHARDWAREINPUT {
              ki=new KEYBDINPUT {
                  wVk=0x41,
                  dwFlags=2
              }
          }
      };
      inputs[3]=new INPUT {
          type=1,
          mkhi=new MOUSEKEYBDHARDWAREINPUT {
              ki=new KEYBDINPUT {
                  wVk=0x11,
                  dwFlags=2,
              }
          }
      };
      SendInput(inputs.Length,inputs,Marshal.SizeOf(inputs[0]));

      0x11是Ctrl的虛擬鍵碼,這里模擬了按下Ctrl鍵,按下A鍵,釋放A鍵,釋放Ctrl鍵的過程,實現了Ctrl+A的組合鍵效果。

       

      SendInput除了能模擬擊鍵消息外還可以在文本輸入中模擬字符消息。

      KEYBDINPUT結構的wScan表示字符內容,將dwFlags的第二位bit置1表示使用wScan屬性而非wVK。

      文本輸入
      string ntext = "你好";
      INPUT[] inputs = new INPUT[ntext.Length*2];
      for(int i = 0;i<ntext.Length;i++) {
          ushort ch = ntext[i];
          inputs[i*2]=new INPUT {
              type=1,
              mkhi=new MOUSEKEYBDHARDWAREINPUT {
                  ki=new KEYBDINPUT {
                      wScan=ch,
                      dwFlags=4
                  }
              }
          };
          inputs[i*2+1]=new INPUT {
              type=1,
              mkhi=new MOUSEKEYBDHARDWAREINPUT {
                  ki=new KEYBDINPUT {
                      wScan=ch,
                      dwFlags=4|2
                  }
              }
          };
      }
      SendInput(inputs.Length,inputs,Marshal.SizeOf(inputs[0]));

       

      鍵狀態

      有時需要知道鍵盤按鍵的當前狀態,可以使用GetKeyState函數。

      GetKeyState的定義
      [DllImport("user32.dll")]
      static extern short GetKeyState(int VKey);

      參數是鍵的虛擬碼,對于開關鍵(Caps Look、Num Lock和Scroll Lock),返回值1表示開啟狀態。對于其它鍵返回負數表示按下狀態。

      CapsLock鍵狀態
      short iState = GetKeyState(0x14);

       

      監聽鍵盤消息

      對于WinForm和WPF程序,要監聽輸入到本程序的鍵盤消息直接使用窗口的KeyDown和KeyUp事件即可。

      對于其它鍵盤消息(即給本程序以外的鍵盤消息),需要使用鉤子(hook)。

      鉤子是Windows系統消息處理機制中的一個節點,可以安裝鉤子來監聽系統中的Windows消息。

      Windows消息分很多種,對于特定的一類消息需要使用對應的特定類型的鉤子,這里只介紹鍵盤消息的鉤子。

      鉤子的安裝需要調用系統SetWindowsHookEx方法。

       

      SetWindowsHookEx的定義
      [DllImport("user32.dll")]
      static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hmod, int threadID);

      idHook等于13表示全局鍵盤消息鉤子,lpfn代表鍵盤消息處理程序,返回非IntPtr.Zero表示安裝成功。

       

      安裝鉤子
      delegate int HookProc(int code,IntPtr wParam,IntPtr lParam);
      static HookProc KeyboardProc;
      static void InstallKeyboardHook() {
          KeyboardProc=KeyboardHookCallback;
          pKeyboardHook=SetWindowsHookEx(13,keyboardProc,IntPtr.Zero,0);
      }

      KeyboardHookCallback就是自定義的具體處理鍵盤消息的方法。

       

      消息處理
      [DllImport("user32.dll")]
      static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
      static int KeyboardHookCallback(int code,IntPtr wParam,IntPtr lParam) {
          if(code<0)
              return CallNextHookEx(IntPtr.Zero,code,wParam,lParam);
          int vkCode = Marshal.ReadInt32(lParam);
          System.Diagnostics.Debug.Write(vkCode+" ");
          long downup = (long)wParam;
          switch(downup) {
              case 256:
                  System.Diagnostics.Debug.WriteLine("down");
                  break;
              case 257:
                  System.Diagnostics.Debug.WriteLine("up");
                  break;
              case 260:
                  System.Diagnostics.Debug.WriteLine("sys_down");
                  break;
              case 261:
                  System.Diagnostics.Debug.WriteLine("sys_up");
                  break;
           }
           return CallNextHookEx(IntPtr.Zero,code,wParam,lParam);
      }

      從lParam中讀取鍵的虛擬碼(lParam其實是指向類似前文提到的KEYBDINPUT結構的指針),wParam表示擊鍵事件的類型。CallNextHookEx將消息傳遞給下一個消息處理節點。

      ?使用前文提到的SendInput方法模擬鍵盤輸入也能被鉤子監聽到。

      ?應避免在消息處理過程中進行耗時操作。

       

      卸載鉤子需要使用UnhookWindowsHookEx

      UnhookWindowsHookEx的定義
      [DllImport("user32.dll")]
      static extern bool UnhookWindowsHookEx(IntPtr pHookHandle);

      傳入SetWindowsHookEx的返回值即可,返回true則卸載成功。

      posted on 2024-08-18 00:57  左眼水星  閱讀(2089)  評論(2)    收藏  舉報

      主站蜘蛛池模板: 插入中文字幕在线一区二区三区| 亚洲一区二区三区激情在线| 欧美交A欧美精品喷水| 蒙自县| 色一伦一情一区二区三区| 成人一区二区不卡国产| 高清中文字幕一区二区| 香港日本三级亚洲三级| 欧美黑人XXXX性高清版| 无码专区人妻系列日韩精品| 久久天天躁夜夜躁狠狠85| 欧美高清freexxxx性| 运城市| 久久精品国产www456c0m| 日本熟妇浓毛| 国产精品久久久久9999| 天天看片视频免费观看| 国产婷婷综合在线视频| 日韩一区二区三区在线视频| 国产av无码专区亚洲av软件| 午夜免费无码福利视频麻豆| 国产女人叫床高潮大片| 男人av无码天堂| 欧美日本精品一本二本三区| 日韩精品一区二区三区在线观看| 久青草视频在线视频在线| 亚洲国产在一区二区三区| 狠狠色丁香婷婷综合尤物| 无遮挡aaaaa大片免费看| 亚洲av午夜福利精品一区二区| 国产精品国产亚洲看不卡| 国产精品剧情亚洲二区| 国产中文字幕精品喷潮| 亚洲天堂网中文在线资源| 欧美高清一区三区在线专区| 日韩av在线不卡一区二区三区| 国产在线精品无码二区| 天堂av最新版中文在线| 人妻系列无码专区无码中出| 亚洲日韩欧美丝袜另类自拍| 无遮挡午夜男女xx00动态|