キーストロークをシミュレートする
                                                         玄関へお回り下さい。
SendInput関数を使ってキーストロークをシミュレートする   (131)
    Option Explicit   'SampleNo=131 WindowsXP VB6.0(SP5) 2002.05.22
Private Type KEYBDINPUT
   wVk As Integer
   wScan As Integer
   dwFlags As Long
   time As Long
   dwExtraInfo As Long
End Type

Private Type INPUT_TYPE
   dwType As Long
   xi(0 To 23) As Byte
End Type

Private Const KEYEVENTF_KEYUP = &H2
Private Const KEYEVENTF_EXTENDEDKEY = &H1  'スキャンコードは拡張コード
Private Const VK_SHIFT = &H10
Private Const VK_HOME = &H24
Private Const VK_END = &H23
Private Const INPUT_KEYBOARD = 1

'仮想キーコード・ASCII値・スキャンコード間でコードを変換する(P1067)
Private Declare Function MapVirtualKey Lib "user32" _
  Alias "MapVirtualKeyA" (ByVal wCode As Long, _
  ByVal wMapType As Long) As Long

'キーストローク、マウスの動作、ボタンのクリックをシミュレートする
Private Declare Function SendInput Lib "user32.dll" _
  (ByVal nInputs As Long, pInputs As INPUT_TYPE, _
   ByVal cbsize As Long) As Long

'メモリブロックをコピーする(P1008)
Private Declare Sub CopyMemory Lib "kernel32.dll" _
  Alias "RtlMoveMemory" (Destination As Any, Source As Any, _
  ByVal Length As Long)

'システムを立ち上げてからの経過時間を高精度に取得する(P1002)
Private Declare Function timeGetTime Lib "winmm.dll" () As Long


'少しは使いやすいように関数化してみました。
Private Sub sKeyEventSet(nInput As Long, _
             wVkKey() As Integer, UpDown() As Integer)
  Dim inputevents() As INPUT_TYPE
  Dim keyevent As KEYBDINPUT
  Dim Count As Integer
  ReDim inputevents(nInput - 1) As INPUT_TYPE
  For Count = 0 To nInput - 1
    With keyevent
      .wVk = wVkKey(Count)    '操作キーコード
      .wScan = MapVirtualKey(wVkKey(Count), 0) 'スキャンコードを指定
      If UpDown(Count) = 0 Then  'キーDown
        .dwFlags = KEYEVENTF_EXTENDEDKEY Or 0
      Else            'キーUP
        .dwFlags = KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP
      End If
      .time = 0
      .dwExtraInfo = 0
    End With
    inputevents(Count).dwType = INPUT_KEYBOARD
    CopyMemory inputevents(Count).xi(0), keyevent, Len(keyevent)
  Next Count
  Call SendInput(nInput, inputevents(0), Len(inputevents(0)))
End Sub


Private Sub Command1_Click()
'メモ帳をアクティブにして、1行選択状態にする 
  Dim wVkKey() As Integer
  Dim UpDown() As Integer
  AppActivate "無題 - メモ帳"
  StopTime 100
  ReDim wVkKey(5) As Integer
  ReDim UpDown(5) As Integer
  wVkKey(0) = VK_HOME:  UpDown(0) = 0  'UpDown(0) = 0 は省略可
  wVkKey(1) = VK_HOME:  UpDown(1) = 1  '0 以外は keyUP
  wVkKey(2) = VK_SHIFT:  UpDown(2) = 0
  wVkKey(3) = VK_END:   UpDown(3) = 0
  wVkKey(4) = VK_END:   UpDown(4) = 1
  wVkKey(5) = VK_SHIFT:  UpDown(5) = 1
  sKeyEventSet 6, wVkKey, UpDown
'キーコード定数はVBのキーコード定数でもOK
End Sub


Private Sub StopTime(st As Long)
'タイマー関数を使って Sleep 関数と同様の関数を作成
  Dim lngSt As Long
  lngSt = timeGetTime
  Do While timeGetTime - lngSt < st
    DoEvents
  Loop
End Sub

SendInput関数は、Win98 or WinNT4 SP3 以降でサポートされます。
Win2000 以降はkeybd_event関数の代わりに SendInput を使ってくださいとの事です。(MSより)
又、SendInput 関数は、INPUT 構造体内のイベントを順にキーボード又は、マウス入力ストリームに挿入します。
これらのイベントに、ユーザーがキーボードまたはマウスで挿入したり、keybd_event、mouse_event に対する呼び出し又は、SendInput 関数を別に呼び出すことによって発生するイベントが割り込むことはありません。
Windows2000 で VK_SHIFT がうまく送れない現象にもスキャンコードを指定することで対応してい
ます。
keybd_event と違って一度に処理するので使用方法が複雑ですがその分安全かと思います。
旧の掲示板の過去のログの4290番から4360番にかけて関連事項が投稿されていますので
そちらにも、一度目を通しておいて下さい。

 



2002/08/21