SendInput でアクティブウィンドウに送信

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
KICO
記事: 57
登録日時: 2005年12月13日(火) 17:42

SendInput でアクティブウィンドウに送信

#1 投稿記事 by KICO »

何時も、お世話に成っています。

 目的ウィンドウに送信後、フォーカスを変更したいのですが、
SendInputの後にSetFocus等で変更したウィンドウに送信されるのですが、
度の様にすれば良いのでしょうか?

 下記の場合、EditBox2に送信される。
SetFocus(EditBox1)
SendInput()
SetFocus(EditBox2)


p.s.
keybd_event 関数
 「Windows NT/2000/XP: この関数は SendInput 関数に取って代わられました。」
となっていますが、不具合が生じるのでしょうか?


宜しくお願いします。
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

Re: SendInput でアクティブウィンドウに送信

#2 投稿記事 by NoWest »

> 何時も、お世話に成っています。
>
>  目的ウィンドウに送信後、フォーカスを変更したいのですが、
> SendInputの後にSetFocus等で変更したウィンドウに送信されるのですが、
> 度の様にすれば良いのでしょうか?
>
>  下記の場合、EditBox2に送信される。
> SetFocus(EditBox1)
> SendInput()
> SetFocus(EditBox2)
SendInput()の後にSleep()を50~100ミリ秒くらい入れてみてはどうでしょうか?
EditBoxに文字を打ち込むだけならSetWindowTextでもよさそうですが。。。

> p.s.
> keybd_event 関数
>  「Windows NT/2000/XP: この関数は SendInput 関数に取って代わられました。」
> となっていますが、不具合が生じるのでしょうか?
keybd_event()とSendInput()との大きな違いはkeybd_event()がキーイベントを1つ1つ個別に送信するのに対し、
SendInput()はキーやマウスのイベントをブロック単位で送信するというものです。

keybd_event()はキーイベントの送信中に、人間がキーを操作してしまうとそのキーイベントが紛れ込んでしまいます。
(もちろんkeybd_event()を使用する別のアプリケーションからも影響を受けます。)

一方のSendInputを使用すると、キーイベントをブロック単位で発生させますので、割り込みの影響を受けにくいです。


どちらを使うかは自由ですが、keybd_event()はMicrosoftは推奨していません。
今後サポートを打ち切られる可能性もあります。
(サポートしないといいながら16bit時代のガラクタがWindowsXPには大量に搭載されてます。Vistaで大分整理されたみたいだが...)

一応、ActiveBasicでは環境依存(9X系のWindowsは98以降にSendInputは実装されている)の強いAPIは搭載しない方針できていたので
SendInput関数は標準には入りにくかったとは思うんですが、
おそらく、SendInput関数のINPUT構造体は共用体を含むので入ってないのではないかと思います。


P.S.
さすがに今、10年前のOSである95は考えなくてもいいと思うので、
今後はSendInput関数を使う方向でいいんじゃないですかね。
KICO
記事: 57
登録日時: 2005年12月13日(火) 17:42

SendInput でアクティブウィンドウに送信

#3 投稿記事 by KICO »

NoWest様、何時も ありがとう御座います。

 SendInput()の後にSleep()を50~100ミリ秒くらい入れてみてはどうでしょうか?
 カーソルが指定時間表示するだけでSendInput後に変更したウィンドウに送信されます。
 EditBoxに文字を打ち込むだけならSetWindowTextでもよさそうですが。。。
 その通りで、拡張キーなど併用しています。
 どちらを使うかは自由ですが、keybd_event()はMicrosoftは推奨していません。
今後サポートを打ち切られる可能性もあります。
P.S.
さすがに今、10年前のOSである95は考えなくてもいいと思うので、
今後はSendInput関数を使う方向でいいんじゃないですかね。
 ありがとう、そうします。
でも、この問題が解決しないと使い辛いですね。


宜しくお願いします。
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

Re: SendInput でアクティブウィンドウに送信

#4 投稿記事 by NoWest »

>  カーソルが指定時間表示するだけでSendInput後に変更したウィンドウに送信されます。

コード: 全て選択

Function DoEvents() As Long
    Dim msg As MSG
    While PeekMessage(msg,NULL,0,0,PM_REMOVE)=TRUE
        Select Case msg.message
            Case WM_QUIT
                ExitProcess(0)
            Case Else
                TranslateMessage(msg)
                DispatchMessage(msg)
        End Select
        Sleep(0)
    Wend
End Function
以前、どっかのスレッドで紹介したコードなんですが、
このDoEvents()をSleep()の代わりにSetFocus()の後で呼んでみてください。
また、SendInput()の後にもDoEvents()を呼んでみてください。
こちらではこれでうまく動きました。


SetFocus()という関数はどうやら内部で
SendMessage(hwnd,WM_KILLFOCUS,0,0)と
SendMessage(hwnd,WM_SETFOCUS,0,0)を呼んでいるようなので、
同じ関数内で、SetFocus()を2回以上呼び出すと最後の呼び出しだけが有効となるようです。

これを避けるためには関数内でメッセージループを強制的に回してやって
フォーカスがエディットボックスに移るのを待って、キーイベントを発生させ、
次のフォーカスへ移動してやればよいです。


P.S.

DoEvents()って意外と使う場面が多いですね。
急場しのぎとはいえVBに感謝ですね。
KICO
記事: 57
登録日時: 2005年12月13日(火) 17:42

SendInput でアクティブウィンドウに送信 [解決]

#5 投稿記事 by KICO »

NoWest様、ありがとう御座いました。
 このDoEvents()をSleep()の代わりにSetFocus()の後で呼んでみてください。
また、SendInput()の後にもDoEvents()を呼んでみてください。
こちらではこれでうまく動きました。
 DoEvents で解決しました。(凄いですね。^ ^)

 以前にも色々教えて頂きまして、ありがとう御座います。

これからも、宜しくお願いします。
返信する