アプリ版:「スタンプのみでお礼する」機能のリリースについて

コントロールキーを押しながらコマンドボタンを押した時と、単にコマンドボタンを押した時とで、処理を変えようかと考えています。
Application.OnKey "^{}", "ctrl"で、キーを捕まえようかと考えましたが。エラーになります。
で、質問ですが、1つは、Ctrlキー、Shiftキー、Altキーを単体で押したときに任意のプロシージャーを実行することってできますか?
2つ目は、任意のプロシージャーではなく、押されているかどうかの状態のみ調べる方法ってありますか?
どなたか、詳しい方教えて頂けないでしょうか?宜しくお願い致します。

A 回答 (3件)

こんにちは。

KenKen_SP です。

簡易的には Key_Down イベントでキーコードを判定し、CTRLキーならモジュール
レベルのフラグを立てる方法がありますが、確実ではありません。

そこで、API を使ってキーの状態を調べます。こんな感じ。


Private Sub CommandButton1_Click()

  'Win32API の GetAsyncKeyState に渡す vKey は VB定数があります
  'ので、それを利用します
  'vbKeyShift  0x10 Shift Key
  'vbKeyControl 0x11 Ctrl Key
  'vbKeyMenu  0x12 Alt Key

  'GetAsyncKeyState関数の戻り値が 0 以外ならそのキーは押下状態
  If GetAsyncKeyState(vbKeyControl) <> 0 Then
    MsgBox "CTRLキーを押しながらクリックされましたよ"
  End If
  
End Sub


'【標準モジュール】----------------------------------------------------
'// Win32API キーボードのキーが押されているかどうかを調べる
Declare Function GetAsyncKeyState Lib "user32.dll" _
  (ByVal vKey As Long) As Long
    • good
    • 0

#1 の



> 簡易的には Key_Down イベントでキーコードを判定し、CTRLキーならモジュール
> レベルのフラグを立てる方法がありますが、確実ではありません。

をコーディングするとこんな感じ。API を使いません。ただし、クリックの事前に
CommandButton1 にフォーカスが無いと KeyDown イベントが発生しないので、
それで、「確実ではない」となりますね、、、

Private mblnFLAG As Boolean

Private Sub CommandButton1_Click()
  If mblnFLAG Then
    MsgBox "[CTRL]+[CLICK]"
  Else
    MsgBox "[CLICK]"
  End If
  
End Sub

Private Sub CommandButton1_KeyDown( _
  ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
  If Shift = 2 Then 'fmCtrlMask
    mblnFLAG = True
  End If
End Sub

Private Sub CommandButton1_KeyUp( _
  ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
  mblnFLAG = False
End Sub
    • good
    • 0

こんにちは。

KenKen_SP です。

ついでの余談ですが、、、

GetAsyncKeyState 関数はキーの同時押しをうまく判定できません。
[SHIFT]+[CONTROL]キーの同時押しなどを判定する必要があれば、
GetKeyboardState 関数を使います。

あとは NT 系の OS に限定されますが、SHIFT、CNTROL、ALT の左右
を判定することも可能です。

サンプルを見て下さい。今回のご質問にあわせてボタンクリック時
のキーの状態を表示させてますが、もちろん、任意のタイミングで
キーの状態を取得できますよ。

これらの API は KeyDown イベントなどが使えない(用意されてい
ない)場合、つまり今回のなどで用いることが


'// キーの同時押しを判定
Private Sub CommandButton1_Click()

  Dim KeyState(255) As Byte
  
  GetKeyboardState KeyState(0)
  
  If CBool(KeyState(VK_SHIFT) And &H80) And _
    CBool(KeyState(VK_CONTROL) And &H80) And _
    CBool(KeyState(VK_MENU) And &H80) Then
    MsgBox "[SHIFT]+[CONTROL]+[ALT]+[クリック]"
  ElseIf CBool(KeyState(VK_SHIFT) And &H80) And _
    CBool(KeyState(VK_MENU) And &H80) Then
    MsgBox "[SHIFT]+[ALT]+[クリック]"
  ElseIf CBool(KeyState(VK_SHIFT) And &H80) And _
    CBool(KeyState(VK_CONTROL) And &H80) Then
    MsgBox "[SHIFT]+[CONTROL]+[クリック]"
  ElseIf CBool(KeyState(VK_CONTROL) And &H80) And _
    CBool(KeyState(VK_MENU) And &H80) Then
    MsgBox "[CONTROL]+[ALT]+[クリック]"
  ElseIf CBool(KeyState(VK_SHIFT) And &H80) Then
    MsgBox "[SHIFT]+[クリック]"
  ElseIf CBool(KeyState(VK_CONTROL) And &H80) Then
    MsgBox "[CONTROL]+[クリック]"
  ElseIf CBool(KeyState(VK_MENU) And &H80) Then
    MsgBox "[ALT]+[クリック]"
  Else
    MsgBox "[クリック]"
  End If

End Sub

'// SHIFT、CTRL、ALT キーの左右を判定(NT系OSのみ)
Private Sub CommandButton2_Click()

  Dim KeyState(255) As Byte

  GetKeyboardState KeyState(0)
  If CBool(KeyState(VK_LCONTROL) And &H80) Then
    MsgBox "[左CTRL]+[クリック]"
  ElseIf CBool(KeyState(VK_RCONTROL) And &H80) Then
    MsgBox "[右CTRL]+[クリック]"
  Else
    MsgBox "[クリック]"
  End If
  
End Sub


'【標準モジュール】----------------------------------------------------

'// Win32API キーボードの仮想キーの状態を取得する
Declare Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long

'// キーコード定数
Public Const VK_SHIFT = &H10  'Shift
Public Const VK_CONTROL = &H11 'Ctrl
Public Const VK_MENU = &H12   'Alt
Public Const VK_LSHIFT = &HA0  'NT系OS only 左Shift
Public Const VK_RSHIFT = &HA1  'NT系OS only 右Shift
Public Const VK_LCONTROL = &HA2 'NT系OS only 左Ctrl
Public Const VK_RCONTROL = &HA3 'NT系OS only 右Ctrl
    • good
    • 1
この回答へのお礼

いつもいつもいつも有難う御座います。
お礼が大変遅くなり申し訳ありませんでした。
単純にコピペするだけで実現できました。
いつもながらアッパレと感じました。ただただ、感服しております。Win32APIに関する本って最低でもVBの本になってしまうと思いますので、何度かご指導頂いた使い方と照らし合わせて自分でも使いこなせるように努力したいと思います。(参考に(無謀とは思いつつ)VisualBasicTips1000+ガリバー著ソシム出版を買いました)すると、GetAsyncKeyState 関数も、GetKeyboardState 関数も載っていました。しかし、使い方が解らないので取り合えず中を見てみようと、(VBを持っていないので!)拡張子(frx,vbp,bas,frm)をtxtに変えて中を見てみましたが、 さっぱり解りません。(期待したコードは見れませんでした。)まぁ自分的には、今後の課題とします。まだまだ、minaraiを脱することは出来そうにありません。今後とも宜しくお願い致します。本当に本当に有難う御座いました。

お礼日時:2005/12/15 15:25

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています