ホーム > VBパーツ

他アプリへの文字入力1 Visual Basic 6.0 Visual Basic 2005 Visual Basic 2008


他のアプリケーションの入力フィールドに、文字を入力する。
ここでは、
SendMessageAPI関数を使ってメモ帳に対して「寿限無」を1文字0.05秒間隔で送信。
(何かと問題のあるSendkeysは使用しない)


他の方法 SendInputによるキー入力シミュレーション

プログラムの手順

1.メモ帳を起動(Shell
   メモ帳はウィンドウズのディレクトリの中のNotepad.exe
   ウィンドウズのパスはEnvironを用いて環境変数から取得
2.メモ帳のウィンドウハンドルを取得(FindWindowEx
   トップレベルのウィンドウから
    クラス名:Notepad  タイトル:無題 - メモ帳
   を探す。
3.メモ帳の子ウィンドウ(Edit)のウィンドウハンドルを取得(FindWindowEx)
   メモ帳を親ウィンドウとして、その子ウィンドウ(Edit)を探す
4.Editにキーコード送信(SendMessage)
   Editに対して1文字ずつ(0.05秒単位)でメッセージ(キーコード)を送信する
   この時、文字列を取り出す関数Midでは、改行(Crlf)を2文字となるので、
   CrLfを1文字として扱うために少し工夫(置換と復元)する。
API関数仕様
FindWindowEx関数
関数の仕様
 クラス名、キャプションから子ウィンドウのハンドルを取得

関数定義

 Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" _
    (ByVal hwndParent As Long, ByVal hwndChildAfter As Long, _
    ByVal lpClassName As String, ByVal lpWindowName As String) As Long


入力パラメータ
 hwndParent:子ウィンドウを見つけるときの親ウィンドウのハンドル
   (デスクトップを親ウィンドウとするとき0)
 hwndChildAfter:検索を開始する子ウィンドウのハンドル
   0 を設定したとき、hwndParentの最初の子ウィンドウから検索する
 lpszClass:クラス名
 lpszWindow:ウィンドウのキャプション(タイトル)
戻り値
 正常終了のとき ウィンドウのハンドル、エラーのとき 0

SendMessage関数

関数の仕様
 
ウィンドウにメッセージを送る

関数定義

 Declare Function SendMessage Lib "user32.dll" _
     Alias "SendMessageA" _
     (ByVal hWnd As Long, _
     ByVal Msg As Long, _
     ByVal wParam As Long, _
     ByVal lParam As Long) As Long


入力パラメータ
 hWnd:メッセージを受け取るウィンドウのハンドル
 Msg:メッセージを指定する定数
     WM_IME_CHAR ( &H286) 文字コード送信
     WM_SETTEXT ( &HC)   文字列送信
 wParam:メッセージとともに送るパラメータ
       WM_IME_CHARの時:キーコード
       WM_SETTEXTの時:未使用=0
 lParam:メッセージとともに送るパラメータ
       WM_IME_CHARの時は未使用=0
       WM_SETTEXTの時:文字列へのポインタ
戻り値
 正常終了のとき ウィンドウのハンドル、エラーのとき 0


以下はサンプルコード
 フォーム上に下記に示すコントロールを配置します。

コントロール配置 実行イメージ

フォームを追加し、下記のコントロールを配置
  コマンドボタン  1個
  テキストボックス 1個
  (MultiLine=Trueにしておく)

標準モジュールを追加


フォーム


以下VB6ソース (VB2005のソースはダウンロード、,VB2008へは2005からアップグレードウィザードで変換)

Option Explicit

Private Sub Command1_Click()
    Dim lnghWnd As Long       'トップレベル(親)のウィンドウハンドル
    Dim lnghWndTarget As Long 'ターゲット(子)のウィンドウハンドル
    Dim lngRc As Long         'APIの返却値
    
    '-------------------------------------
    ' メモ帳を起動
    '-------------------------------------
    lngRc = Shell(Environ("WINDIR") & "\NOTEPAD.EXE", vbNormalFocus) '起動
    Sleep 100               '0.1秒待つ(起動完了)
    
    '-------------------------------------
    ' ターゲットウィンドウのハンドルを取得
    '-------------------------------------
    lnghWnd = FindWindowEx(0, 0, "Notepad", "無題 - メモ帳") '「メモ帳」のウィンドウハンドル
    lnghWndTarget = FindWindowEx(lnghWnd, 0, "Edit", "") '子ウィンドウのEdit
    
    '-------------------------------------
    ' 送信
    '-------------------------------------
    Dim strDtSrc As String
    Dim strDt As String

    '-------------------------------------
    ' 1文字ずつ送信 50ミリ(0.05)秒間隔
    '-------------------------------------
    Dim lngDt As Long
    Dim i As Long
    
    strDtSrc = Replace(Text1.Text, vbCrLf, Chr(&H1)) '改行変換
    For i = 1 To Len(strDtSrc) '文字数分繰り返す
        strDt = Replace(Mid(strDtSrc, i, 1), Chr(&H1), vbCrLf) '改行文字を復元
        lngDt = Asc(strDt)  'ASCIIコードに変換
        lngRc = SendMessage(lnghWndTarget, WM_IME_CHAR, lngDt, 0)   '1文字送信
        Sleep 50    '指定ミリ秒待つ
    Next i
    
'    '-------------------------------
'    ' 全ての文字を一度に送信する場合は
'    ' 下記のようにする。
'    '-------------------------------
'    strDtSrc = Text1.Text
'    lngRc = SendMessageAny(lnghWndTarget, WM_SETTEXT, 0, ByVal strDtSrc)

    
End Sub


Private Sub Form_Load()
    Text1.Text = "SendMessage を使った「メモ帳」への入力" & vbCrLf & _
                "1文字0.1秒" & vbCrLf & _
                vbCrLf & _
                "寿限無、寿限無" & vbCrLf & _
                "五劫の擦り切れ" & vbCrLf & _
                "海砂利水魚の" & vbCrLf & _
                "水行末 雲来末 風来末" & vbCrLf & _
                "食う寝る処に住む処" & vbCrLf & _
                "やぶら小路の藪柑子" & vbCrLf & _
                "パイポパイポ パイポのシューリンガン" & vbCrLf & _
                "シューリンガンのグーリンダイ" & vbCrLf & _
                "グーリンダイのポンポコピーのポンポコナーの" & vbCrLf & _
                "長久命の長助"
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    End
End Sub

標準モジュール

Option Explicit

' 指定時間Wait(ミリ秒)
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)


'クラス名、キャプションから子ウィンドウのハンドルを取得
Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" _
    (ByVal hwndParent As Long, ByVal hwndChildAfter As Long, _
     ByVal lpClassName As String, ByVal lpWindowName As String) As Long
'引数
' hwndParent:子ウィンドウを見つけるときの親ウィンドウのハンドル
'   (デスクトップを親ウィンドウとするとき0)
' hwndChildAfter:検索を開始する子ウィンドウのハンドル
'   0 を設定したとき、hwndParentの最初の子ウィンドウから検索する
' lpszClass:クラス名
' lpszWindow:ウィンドウのキャプション(タイトル)
'
'戻り値
' 正常終了のとき ウィンドウのハンドル、エラーのとき 0
'
'FindWindow()関数との違いは子ウィンドウか検索できること。
'hwndParentとhwndChildAfterが共に0のときトップレベルウィンドウが検索対象。



' ウィンドウにメッセージを送る関数の宣言
Public Declare Function SendMessage Lib "user32.dll" _
    Alias "SendMessageA" _
   (ByVal hWnd As Long, _
    ByVal Msg As Long, _
    ByVal wParam As Long, _
    lParam As Any) As Long

' ウィンドウにメッセージを送る関数の宣言
Public Declare Function SendMessageAny Lib "user32.dll" _
    Alias "SendMessageA" _
   (ByVal hWnd As Long, _
    ByVal Msg As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Any) As Long

Public Const WM_IME_CHAR = &H286    '文字コード送信
Public Const WM_SETTEXT = &HC       '文字列送信

VB6サンプルコードのダウンロード
VB2005(アップグレード済み)サンプルコードのダウンロード
VB2008へは2005からアップグレードして下さい。