[リストへもどる]
一括表示

投稿時間:2003/02/05(Wed) 18:31
投稿者名:たけ
URL :
タイトル:
SendInputの使い方
SendInputを使ってESCを押したようにしたいのですが、うまくいきません。
SPY++でみても、ESCメッセージが出ていませんでした。
どなたか、どこが悪いのか教えてください。

' ユーザーインプットを合成する関数の宣言
Declare Function SendInput Lib "user32.dll" (ByVal nInputs As Long, pInputs As tagINPUT, ByVal cbSize As Long) As Long

' キーストローク情報を含む構造体
Type tagKEYBDINPUT
    wVk                 As Integer
    wScan               As Integer
    dwFlags             As Long
    time                As Long
    dwExtraInfo         As Long
    bytUnusedPadding(7) As Byte
End Type

' ユーザーインプットを合成する情報を保存する構造体
Type tagINPUT
    type As Long
    ki   As tagKEYBDINPUT
End Type

' インプットイベントの種類を示す定数の宣言
'ublic Const INPUT_MOUSE = 0
Public Const INPUT_KEYBOARD = 1
'ublic Const INPUT_HARDWARE = 2
Public Const VK_ESCAPE = &H1B&

Private Sub Command1_Click()
    '***************************************************************************
        Dim udtInputEvent(2)      As tagINPUT
        Dim lngWin32apiResultCode As Long

        With udtInputEvent(0)
            ' インプットイベントの種類を指定
            .type = INPUT_KEYBOARD
            With .ki
                ' 仮想キーコードを指定
                .wVk = VK_ESCAPE
            End With
        End With
        With udtInputEvent(1)
            ' インプットイベントの種類を指定
            .type = INPUT_KEYBOARD
            With .ki
                ' 仮想キーコードを指定
                .wVk = VK_ESCAPE
                ' 動作を指定
                .dwFlags = KEYEVENTF_KEYUP
            End With
        End With
        ' キー ストロークを合成
        lngWin32apiResultCode = SendInput(2, udtInputEvent(0), Len(udtInputEvent(0)))
    '***************************************************************************
End Sub

投稿時間:2003/02/05(Wed) 20:25
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: SendInputの使い方
ここの逆引きヘルプの キーストロークをシミュレート(押下げ・制御)する(SendInput関数使用) と
見比べて下さい。(といってもそんなに立派なサンプルではありませんが)

Command1_Click イベントを下記に変更して試して見て下さい。

Private Sub Command1_Click()
    Dim wVkKey() As Integer
    Dim UpDown() As Integer
    ReDim wVkKey(3) As Integer
    ReDim UpDown(3) As Integer
    
    wVkKey(0) = vbKeyControl:   UpDown(0) = 0   'UpDown(0) = 0 は省略可
    wVkKey(1) = vbKeyEscape:    UpDown(1) = 0   '0 以外は keyUP
    wVkKey(2) = vbKeyEscape:    UpDown(2) = 1
    wVkKey(3) = vbKeyControl:   UpDown(3) = 1
    sKeyEventSet 4, wVkKey, UpDown
'キーコード定数はVBのキーコード定数でもOK
End Sub

投稿時間:2003/02/06(Thu) 13:55
投稿者名:たけ
URL :
タイトル:
Re^2: SendInputの使い方
早速試してみました。が、CTRL+ESCだと、スタートメニューが開いたのでESCだけにしました。
ところが、NTではうまくいきましたが、2000ではだめでした。
もともと、Keybd_eventをいれていて、2000にしたらESCが出ていないことがわかり、SendInputに
変更しようとしています。

投稿時間:2003/02/06(Thu) 14:39
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^3: SendInputの使い方
> 早速試してみました。が、CTRL+ESCだと、スタートメニューが開いたのでESCだけにしました。
ESC キーが機能したかのテスト用のサンプルですので当然です。

> ところが、NTではうまくいきましたが、2000ではだめでした。
Win98・WinXP でもOKですが!
投稿されたサンプルでもWinXPでは機能しております。

Windows2000 をお持ちの他の方に試して頂くしかないですかね

投稿時間:2003/02/06(Thu) 17:08
投稿者名:たけ
URL :
タイトル:
Re^4: SendInputの使い方
> > 早速試してみました。が、CTRL+ESCだと、スタートメニューが開いたのでESCだけにしました。
> ESC キーが機能したかのテスト用のサンプルですので当然です。

私の返信がまずかったです。
CTRL+ESCで、NT、2000ともスタートメニューが開きました。
ということは、SendInput自体は動作しているようです。

> > ところが、NTではうまくいきましたが、2000ではだめでした。

何がうまくいかないのかも説明不足でした。

VBで作った画面が二つあり(別々のexeファイル)、そのなかにVS-FlexGrid
(MS-FlexGridの正式版)があります。
このセルにデータを編集中に画面を一方に切り換え、戻ってきたときに
編集中のデータをキャンセルしていました。
NTのときは、画面切り替わり時に、コントロールにSetFocusして、Keybd_Event
でESCを出すと、編集中のデータがキャンセルできました。
2000ではこれができません。Keybd_EventからSendInputに変更してもできませんでした。
これが今起こっている不具合です。

SPY++で調べたのですが、2000では、SetFocusした直後にKillFocusがなぜか
走っています。NTにはありません。
2000ではFocusを当てただけでは、アクティブにならないようです。

ここまでわかったのですが、解決策が見つかりません。

混乱させてすいませんでした。

投稿時間:2003/02/06(Thu) 17:33
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^5: SendInputの使い方
Windows 98からの仕様のようです。NT4やWindows95とは動作が異なっています。
詳しくは SetForegroundWindow windows2000 をキーワードに検索して
見て下さい。

下記も参考になるかも
http://www.microsoft.com/japan/msdn/windows/windows2000/win2000appcomp.asp

投稿時間:2003/02/07(Fri) 22:57
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^5: SendInputの使い方
もう解決されたのでしょうか?
http://www.systemyou.co.jp/tips/vb/tips3.htm に解決策として
SetForegroundWindowを行うウィンドウのスレッドにアタッチしてから、
SetForegroundWindowを行います。とかいてあるのですが

SetForegroundWindow APIを直接実行するだけでもいいような気も
するのですが
一応両方のサンプルを作って試して見たのですがおっしゃってる
場面と同じ状態が作れないので確かな確認はできてませんが?

投稿時間:2003/02/12(Wed) 17:02
投稿者名:たけ
URL :
タイトル:
Re^6: SendInputの使い方
返事が遅くなりました。連休モードに入っていたので...

> http://www.systemyou.co.jp/tips/vb/tips3.htm に解決策として
> SetForegroundWindowを行うウィンドウのスレッドにアタッチしてから、
> SetForegroundWindowを行います。とかいてあるのですが
>
> SetForegroundWindow APIを直接実行するだけでもいいような気も
> するのですが
> 一応両方のサンプルを作って試して見たのですがおっしゃってる
> 場面と同じ状態が作れないので確かな確認はできてませんが?

教えていただいたホームページを参考に試したところ、2000でも元の動作
にすることが出来ました。
もちろん、NTでも問題ありません。

私も、SetForegroundWindowだけでうまくいくのではと考え、これだけを
いれてみましたがだめでした。
AttachThreadInputをいれないとうまくいきません。
ところが、アタッチ先と元が同じIDになっており、AttachThreadInputの
結果がエラーになっているのに、SetForegroundWindowの前にこれがない
と動作しないのが腑に落ちませんでした。
レジストリを変更するほうはやっていません。

投稿時間:2003/02/14(Fri) 10:35
投稿者名:たけ
Eメール:
URL :
タイトル:
Re^7: SendInputの使い方
自己レスです。

> ところが、アタッチ先と元が同じIDになっており、AttachThreadInputの
> 結果がエラーになっているのに、SetForegroundWindowの前にこれがない
> と動作しないのが腑に落ちませんでした。

VBのブレークポイントを貼る位置が悪くてこのような結果になっていました。
AttachThreadInputは正常終了を返してきていました。


'**************************************************************************
        Dim nResult1 As Long
        Dim nResult2 As Long
        Dim nTargetID As Long
        
        nTargetID = GetWindowThreadProcessId(GetForegroundWindow, 0)
        If App.ThreadID <> nTargetID Then
            nResult1 = AttachThreadInput(App.ThreadID, nTargetID, True)
        End If
        nResult2 = SetForegroundWindow(frmMainForm.hWnd)
        If App.ThreadID <> nTargetID Then
            nResult1 = AttachThreadInput(App.ThreadID, nTargetID, False)
        End If
'***************************************************************************