• ベストアンサー
  • 困ってます

VB6で他のアプリへ左右のCTRLキーを送る方法

  • 質問No.4322628
  • 閲覧数5698
  • ありがとう数3
  • 気になる数0
  • 回答数3
  • コメント数0

お礼率 57% (4/7)

先に「Excel VBA で CTRLキーを送る方法」と題して質問したものです。
VB6でSendInputを使うアドバイスを頂きCTRLを送ることが出来たので解決したと思っていましたが、左右のキーの判断が出来ていないようです。
下記のコードを実行形式にしてたとき、引数の如何にかかわらず、受け取る側(YourAppli.ws)では右のCTRLを受け取った動作をします。左のCTRL(Zキーに近い方)を受け取った動作をしてくれません。
アプリケーションに左右のCTRLを認識させる方法をご教示お願いします。
コードの作成は http://mt-soft.sakura.ne.jp/web_dl/vb-parts/key_sendinput/​を参考に致しました。

Option Explicit
Private Type KEYBDINPUT
wVk As Integer
wScan As Integer
dwFlags As Long
time As Long
dwExtraInfo As Long
no_use1 As Long
no_use2 As Long
End Type

Private Type INPUT_TYPE
dwType As Long
xi As KEYBDINPUT
End Type

'仮想キーコード
Private Const KEYEVENTF_KEYUP = &H2'キーアップ
Private Const KEYEVENTF_EXTENDEDKEY = &H1'スキャンコードは拡張コード
Private Const INPUT_KEYBOARD = 1'入力タイプ:キーボード
Private Const VK_CTRL = &H11'Contorol
Private Const VK_LCONTROL = &HA2'Left_Contorol
Private Const VK_RCONTROL = &HA3'Right_Contorol
Private Const VK_RETURN = &HD'Right_Contorol
Private Const KEY_DOWN = 0'キー押し下げ
Private Const KEY_UP = 1'キーアップ

'仮想キーコード・ASCII値・スキャンコード間でコードを変換する
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

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

Sub Main()
Const AppID = "YourAppli.ws"
Dim i As Integer

AppActivate AppID
Select Case Command
Case "L", "l"
Send_LCtrl
Case "R", "r"
Send_RCtrl
Case ""
Send_Ctrl
Case Else
MsgBox ("Error")
End Select
Sleep 50
End Sub

Private Sub Send_LCtrl()
Call KeyEvent(VK_LCONTROL, KEY_DOWN)
Call KeyEvent(VK_LCONTROL, KEY_UP)
End Sub

Private Sub Send_RCtrl()
Call KeyEvent(VK_RCONTROL, KEY_DOWN)
Call KeyEvent(VK_RCONTROL, KEY_UP)
End Sub

Private Sub Send_Ctrl()
Call KeyEvent(VK_CTRL, KEY_DOWN)
Call KeyEvent(VK_CTRL, KEY_UP)
End Sub

Sub KeyEvent(VkKey As Integer, UpDown As Integer)
' VkKey:仮想キーコード
' UpDown:動作(KEY_DOWN/KEY_UP)
'
Dim inputevents As INPUT_TYPE
With inputevents
.dwType = INPUT_KEYBOARD
With .xi
.wVk = VkKey '操作キーコード
.wScan = MapVirtualKey(VkKey, 0) 'スキャンコード
If UpDown = KEY_DOWN Then 'キーDown
.dwFlags = KEYEVENTF_EXTENDEDKEY Or 0
Else'キーUP
.dwFlags = KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP
End If
.time = 0
.dwExtraInfo = 0
End With
End With
Call SendInput(1, inputevents, Len(inputevents))
End Sub

質問者が選んだベストアンサー

  • 回答No.3
  • ベストアンサー

ベストアンサー率 60% (226/373)

以下の改造で動きます。

---

■追加
Private Declare Function GetMessageExtraInfo Lib "user32" () As Long

■変更
Private Sub Send_LCtrl()
Call KeyEvent(VK_LCONTROL, KEY_DOWN, 0)
Call KeyEvent(VK_LCONTROL, KEY_UP, KEYEVENTF_KEYUP)
End Sub

Private Sub Send_RCtrl()
Call KeyEvent(VK_RCONTROL, KEY_DOWN, KEYEVENTF_EXTENDEDKEY Or 0)
Call KeyEvent(VK_RCONTROL, KEY_UP, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP)
End Sub

Sub KeyEvent(VkKey As Integer, UpDown As Integer, flags As Long)
' VkKey:仮想キーコード
' UpDown:動作(KEY_DOWN/KEY_UP)
' flags:フラグ
Dim inputevents As INPUT_TYPE
inputevents.dwType = INPUT_KEYBOARD
With inputevents.xi
.wVk = VkKey
.wScan = MapVirtualKey(VkKey, 0)
.dwFlags = flags
.time = 100
.dwExtraInfo = GetMessageExtraInfo()
End With
Call SendInput(1, inputevents, Len(inputevents))
End Sub


---補足説明---
KEYEVENTF_EXTENDEDKEY の指定を間違えていたようです。
拡張キーは、歴史的に後から追加されたキーを指し、RShift, RAlt, RCtrl, End などが該当します。LCtrl は拡張キーではありません。
テンキー上の「/」は拡張キーなのに、テンキー上の「*」は拡張キーではない、などイレギュラーなものもあるようです。
GetMessageExtraInfo は MSDN の説明を元に一応設定しておきました。


---参考サイト---
http://msdn.microsoft.com/ja-jp/library/ms646271(en-us,VS.85).aspx
http://homepage1.nifty.com/yasunari/VB/VB2005/ScreenKeyBoardMaking.htm
お礼コメント
mana_okwav

お礼率 57% (4/7)

完全なる解決です。
数度に亘りご指導感謝いたします。
蛇足ですが、いろいろ試してみて、仮想キーの値には関係なく、キーダウン時のFlagだけで左右が決まってしまうことがわかりました。
投稿日時:2008/09/15 08:54

その他の回答 (全2件)

  • 回答No.2

ベストアンサー率 60% (226/373)

>を読み解かなければならないのでしょうが、基礎がないため内容が理解できません。

一番下に VB のソースが載っているのでそれをほとんど流用するだけですが。英語サイトだからといって尻込みしているだけに見えます。
ともあれ、後述の通りこのサイトのソースでも同じ現象が出るので、無意味となりました。

---

VB6 のコードを試してみましたが、再現しますね。
http://mt-soft.sakura.ne.jp/web_dl/vb-parts/key_sendinput/
↑ここに、VB2008 対応コードがダウンロードできる形で置かれていましたが、同じ症状でした。

また、上述したように以下のサイトのサンプルでも同じ症状でした(私は右Ctrlの送信しかテストしていませんでしたので、確認してみました)。
http://www.pinvoke.net/default.aspx/user32.SendInput

なんか SendInput API の使い方を間違えているのでしょうかねぇ。

こんなサイトを見つけたので、
http://lukewarm.s101.xrea.com/index.html
興味本位でソースを覗いてみようと思いますが(ホットキーの割り当てだけでなくSendInputの機能もあり、左右のCtrlの送信が可能っぽい)、時間かかるかもです。

とりあえず、左Ctrl の送信は SendKey コマンドを使って回避してはどうでしょうか。
補足コメント
mana_okwav

お礼率 57% (4/7)

英語が問題ということではありませんが
Excel VBAしか経験なく、Classなどの概念が理解できていないことが一番問題です。今回、本を読みコトからはじめ、概念は理解できたつもりですが、コードがVBではない書式(Type→Structureなど)でVB.netはVB6と違うのか等苦戦してます。
dot.net 2003でも勉強しようかと購入し、封も開けず数年置いておいたものを、インストールしたところです。

>とりあえず、左Ctrl の送信は SendKey コマンドを使って回避してはどうでしょうか。
SendKeysではCtrl単体を送ることが出来ません。
投稿日時:2008/09/15 09:27
  • 回答No.1

ベストアンサー率 60% (226/373)

こんにちは。少し確認点を。

1.wScan の値は左右で違う値に変換されていますか?
以前私が紹介した英語のサイト、ほぼそのまま入力してこちらでは動きました。VB6での掲載ソースとの違いを言うと、wScan = 0 固定でした。つまり MapVirtualKey は利用していません。

2.また送信対象のプログラムは信用できますか?
一応 VB6 で、右Ctrlと左Ctrlのキー入力を検知するソースを載せておきますので、これを使って実際にあなたが作成したプログラムから左右のCtrlが正しくキー送信されているか確認してみてください。

---

Private Declare Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
Dim k(255) As Byte

If Shift = 2 Then
GetKeyboardState k(0)
If CBool(k(&HA2) And &H80) Then
Me.Label1.Caption = "Left Ctrl Key"
Else
If CBool(k(&HA3) And &H80) Then
Me.Label1.Caption = "Right Ctrl Key"
End If
End If
Else
Me.Label1.Caption = ""
End If
End Sub

Private Sub Form_Load()
Me.KeyPreview = True
End Sub

#フォームにラベルを一つ貼り、ますば手操作で検知できる事を確認して使ってください。
補足コメント
mana_okwav

お礼率 57% (4/7)

edp3142さん
ご親切に評価用コードを提供頂きありがとうございます。
3連休中に試してみます。

現在分りましたことは以下です。
それにしても、左キーではなく、右キーを入れたときと同じ動作となるのも変です。
> 1.wScan の値は左右で違う値に変換されていますか?
VkKey=VK_LCONTROL、VkKey=VK_RCONTROLのいづれでも &H1Dです。
wScan = 0 に固定しても結果は同じでした。(右キーのシュミレートとなる)
> 2.また送信対象のプログラムは信用できますか?
長年使用しているもので、大手の製品です。
 左コントロールは入力エラーなどが発生たときの回復に使用するようになっています。手でキーを操作すると問題なく動作します。
投稿日時:2008/09/12 15:55
お礼コメント
mana_okwav

お礼率 57% (4/7)

edp3142さん
ご提供頂いたコードで試して見ました。
当方で作成したコードからは、左キーを送ったつもりでも右キーが受信されました。
提供頂いたコードは大変役に立ち、問題点が絞れてきました。
http://www.pinvoke.net/default.aspx/user32.SendInput
を読み解かなければならないのでしょうが、基礎がないため内容が理解できません。
投稿日時:2008/09/12 17:26
結果を報告する
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。
関連するQ&A

その他の関連するQ&Aをキーワードで探す

ピックアップ

ページ先頭へ