ExcelのVBAで3択クイズを作っていて、ユーザーフォーム上で解答選択支が表示されている
コマンドボタンが3つあって、
そのどれかをクリックすると正解か不正解の表示が出る仕組みのプログラムを作ったのですが、
スムーズに選択できるようキーボードでコマンドボタンを押せるようにしたいのです。
左キーを押すとコマンドボタン1、上キーを押すとコマンドボタン2、右キーを押すとコマンドボタン3
が反応するといった感じにしたいのです。
いろんなサイトを見て回ったのですがAPIのGetAsyncKeyStateという関数を使うというところまでは
分かったのですが素人なものでそこから先を何を記述すべきか分からなくて困っています。
いろいろためしたものの反応がしなくて分からないです。
なにかいい方法はありませんか?
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.5
- 回答日時:
#2です。
xl2000とxl2010で確認しております。他のバージョンは分かりませんが別の理由だと思います。
然るべきモジュールに置かれたのか、他のルーチンと同居させたのか等が分かりませんのでお返事のしようはないですが、GetAsyncKeyStateの使い方の一例を紹介させていただいたのみですので、スルーして下さって結構です。
No.4
- 回答日時:
再掲:
>他のコントロールを置かなきゃならないなら,そちらのコントロールもフォーカスを持たないようにするか,またはフォーカスを持つ(可能性のある)コントロールのkeyDownイベントに同じ仕込みをしておくこと
意味が分からなくてスルーしてたのなら,そこを聞くべきだったのではありませんか?
次の通り追加します
Private Sub CommandButton1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 39 Then CommandButton1_Click
If KeyCode = 38 Then CommandButton2_Click
If KeyCode = 37 Then CommandButton3_Click
End Sub
Private Sub CommandButton2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 39 Then CommandButton1_Click
If KeyCode = 38 Then CommandButton2_Click
If KeyCode = 37 Then CommandButton3_Click
End Sub
Private Sub CommandButton3_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 39 Then CommandButton1_Click
If KeyCode = 38 Then CommandButton2_Click
If KeyCode = 37 Then CommandButton3_Click
End Sub
Private Sub CommandButton4_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 39 Then CommandButton1_Click
If KeyCode = 38 Then CommandButton2_Click
If KeyCode = 37 Then CommandButton3_Click
End Sub
No.3
- 回答日時:
1問目とか2問目と言われても,ナンのことか(アナタのエクセルがどうなっているのか)さっぱり判りません。
具体的なハウツーの回答が必要でしたら,もっとエクセルの(ユーザーフォームの)姿をキチンと情報提供するよう頑張って説明してみてください。
断片的な情報から推測できることとしては恐らく
>黒枠が動くだけ
回答で説明した
・他のコントロールがない
という条件が満たされていない,
若しくは
・プロパティパネルで設定する
という準備を怠っている
と考えられます。
もしご自分で作成した(作成中の)モノの説明ができないようでしたら,次のように作成すれば回答1で出来ますので作り直してください。
1.設問ごとにユーザーフォームを作成する
2.ユーザーフォームごとにコマンドボタン1,2,3を配置する
3.ユーザーフォームごとに各ボタンのプロパティを正しく設定する
4.ユーザーフォームごとにマクロを登録する
この回答への補足
英単語の3択でsheets1はコマンドボタンが1つあって、それを押すと全20問で問題がランダムに
出るユーザーフォームが出てくる仕組みです。
sheets2は問題の属性データと問題元データがあります。
問題元データはsheets1のコマンドボタンを押すたびにランダムに変わるようになっています。
sheet3は名詞の単語が1551個収録、sheets4は形容詞の単語が792個収録、sheets5は動詞の単語が
1059個収録、sheets6は副詞の単語が61個収録といった構成です。
userform1には問題数表示と問題文のラベルと4つのコマンドボタンが設置してあり3つは問題の回答選択支としてのボタンで
残りの1つは次の問題へと進むためのボタンです。
下にuserform1のcommandbutton1~4までのプログラムを載せます。
Private Sub CommandButton1_Click()
Application.ScreenUpdating = False
If Label4.Caption = "正解!!" Or Label4.Caption = "残念!!" Then
CommandButton4.SetFocus
ElseIf Label5.Caption = "1" Or Label5.Caption = "2" Or Label5.Caption = "3" Or Label5.Caption = "4" Or Label5.Caption = "5" Or Label5.Caption = "6" Then
Label4.Caption = "正解!!"
Sheets("処理").Select
Cells(2, 3) = Cells(2, 3) + 1
Sheets("スタート").Select
CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty
If Label2 = "20" Then
MsgBox "全20問終了しました。"
End If
Else
Sheets("処理").Select
Label4.Caption = "残念!!" & vbCrLf & Cells(Label2 + 1, 16).Value
Sheets("スタート").Select
CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty
If Label2 = "20" Then
MsgBox "全20問終了しました。"
End If
End If
Application.ScreenUpdating = True
CommandButton4.SetFocus
End Sub
Private Sub CommandButton2_Click()
Application.ScreenUpdating = False
If Label4.Caption = "正解!!" Or Label4.Caption = "残念!!" Then
CommandButton4.SetFocus
ElseIf Label5.Caption = "7" Or Label5.Caption = "8" Or Label5.Caption = "13" Or Label5.Caption = "14" Or Label5.Caption = "19" Or Label5.Caption = "20" Then
Label4.Caption = "正解!!"
Sheets("処理").Select
Cells(2.3) = Cells(2, 3) + 1
Sheets("スタート").Select
CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty
If Label2 = "20" Then
MsgBox "全20問終了しました"
End If
Else
Sheets("処理").Select
Label4.Caption = "残念!!" & vbCrLf & Cells(Label2 + 1, 16).Value
Sheets("スタート").Select
CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty
If Label2 = "20" Then
MsgBox "全20問終了しました。"
End If
End If
Application.ScreenUpdating = True
CommandButton4.SetFocus
End Sub
Private Sub commandbutton3_click()
Application.ScreenUpdating = False
If Label4.Caption = "正解!!" Or Label4.Caption = "残念!!" Then
CommandButton4.SetFocus
ElseIf Label5.Caption = "9" Or Label5.Caption = "11" Or Label5.Caption = "15" Or Label5.Caption = "17" Or Label5.Caption = "21" Or Label5.Caption = "23" Then
Label4.Caption = "正解!!"
Sheets("処理").Select
Cells(2, 3) = Cells(2, 3) + 1
Sheets("スタート").Select
CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty
If Label2 = "20" Then
MsgBox "全20問終了しました"
End If
Else
Sheets("処理").Select
Label4.Caption = "残念!!" & vbCrLf & Cells(Label2 + 1, 16).Value
Sheets("スタート").Select
CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty
If Label2 = "20" Then
MsgBox "全20問終了しました。"
End If
End If
Application.ScreenUpdating = True
CommandButton4.SetFocus
End Sub
commndbutton4のプログラムも載せます。
全部載せると文字数が足らないので膨大なcaptionの部分は省きます。
Private Sub CommandButton4_Click()
Dim 正解率 As Variant
Application.ScreenUpdating = False
If Left(Label4.Caption, 4) = "正解!!" Or Left(Label4.Caption, 4) = "残念!!" Then
If Label2 = "20" Then
Sheets("処理").Select
正解率 = Cells(2, 3) / 20 * 100
Label4.Caption = "正解率は" & 正解率 & "%でした。"
Sheets("スタート").Select
MsgBox "全20問終了しました。"
Unload Me
Exit Sub
End If
Label2.Caption = Label2 + 1
Sheets("処理").Select
Label4.Caption = Cells(Label2 + 1, 11)
Label5.Caption = Cells(Label2 + 1, 4).Value
省略
End If
Else
MsgBox "解答を選択して下さい!!", vbCritical
End If
Sheets("スタート").Select
Application.ScreenUpdating = True
End Sub
No.2
- 回答日時:
#1で十分だと思いますが、GetAsyncKeyState APIを使ってやってみました。
参考URLの他、VBAのヘルプの「RaiseEvent ステートメントの使用例」をご参照下さい。
とりあえず動いたという以上の検証は出来ておりません。
また、CommandButton1のところしか記載しておりませんので悪しからず。
☆標準モジュール
Sub test()
UserForm1.Show
End Sub
☆UserForm1モジュール
Private WithEvents watchKey As Class1
Private Sub CommandButton1_Click()
MsgBox "CommandButton1が押されたよ"
End Sub
Private Sub UserForm_Initialize()
Set watchKey = New Class1
End Sub
Private Sub UserForm_Activate()
'これをUserForm_Initializeで実行するとフォームが表示されずはまった...
watchKey.watchTask
End Sub
Private Sub UserForm_Terminate()
watchKey.stopLoop = True
Set watchKey = Nothing
End Sub
Private Sub watchKey_keyPushed(ByVal strKey As String)
'MsgBox strKey & "が押されました"
Select Case strKey
Case "←"
Call CommandButton1_Click
Case "↑"
Case "→"
End Select
End Sub
☆Class1モジュール 中身が分かる名前をつけるのが本来ですが、簡便のため挿入/クラスモジュールでつくお仕着せの名前にしてあります。
Public Event keyPushed(ByVal strKey As String)
Private Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Const VK_LEFT = &H25 '[←]
Private Const VK_UP = &H26 '[↑]
Private Const VK_RIGHT = &H27 '[→]
Private myStopFlag As Boolean
Public Sub watchTask()
Do
If GetAsyncKeyState(VK_LEFT) Then
RaiseEvent keyPushed("←")
ElseIf GetAsyncKeyState(VK_UP) Then
RaiseEvent keyPushed("↑")
ElseIf GetAsyncKeyState(VK_RIGHT) Then
RaiseEvent keyPushed("→")
Else
End If
Call Sleep(100)
DoEvents
Loop Until myStopFlag
End Sub
Public Property Let stopLoop(stopFlag As Boolean)
myStopFlag = stopFlag
End Property
参考URL:http://home.att.ne.jp/zeta/gen/excel/c04p07.htm
No.1
- 回答日時:
準備:
UserForm1にCommandButton1,2,3を配置してある(他のコントロールは無い)
プロパティパネルで各コマンドボタンのTabStop並びにTakeFocusOnClickをFalseにしておく
手順:
ユーザーフォームのシートに
Private Sub UserForm_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 39 Then CommandButton1_Click
If KeyCode = 38 Then CommandButton2_Click
If KeyCode = 37 Then CommandButton3_Click
End Sub
としておく。
#他のコントロールを置かなきゃならないなら,そちらのコントロールもフォーカスを持たないようにするか,またはフォーカスを持つ(可能性のある)コントロールのkeyDownイベントに同じ仕込みをしておくこと
回答ありがとうございます!
早速試して1問目に限れば理想どうりに動いたのですが、2問目からはコマンドボタンに点々の黒枠が
出てしまい方向キーをおしてもクリック動作がせず、黒枠が動くだけになってしまいました・・
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/12】 急に朝起こしてきた母親に言われた一言とは?
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・好きな「お肉」は?
- ・あなたは何にトキメキますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・チョコミントアイス
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・あなたの習慣について教えてください!!
- ・ハマっている「お菓子」を教えて!
- ・高校三年生の合唱祭で何を歌いましたか?
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・家の中でのこだわりスペースはどこですか?
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Excel VBAで、実行時にsheet上...
-
エラー内容が分かりません
-
コモンダイアログエラー
-
エクセルVBAでmeに相当するもの...
-
EXCEL VBA テキストボックスの...
-
エクセルでツールバーに「縮小...
-
フォルダ内の全ブックのシート...
-
複数のデータ系列の線の太さを...
-
ExcelVBAで今開いているユーザ...
-
複数のCSVファイルを横に並べて...
-
コピーしたファイルのマクロを...
-
エクセル終了時の保存確認メッ...
-
別のパソコンでエクセルのマク...
-
昨日まで動いていたエクセルの...
-
Excelが勝手にシート移動してし...
-
エクセルの指数を無効にしたい
-
excelファイルに使われているVB...
-
複数のpowerpointのファイルを...
-
VBAを一度起動するとずっと出て...
-
VBA[Private Sub]のコードをシ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Excel VBAで、実行時にsheet上...
-
エラー内容が分かりません
-
エクセルVBAでmeに相当するもの...
-
コモンダイアログエラー
-
オプションボタン
-
キーボードでコマンドボタンを...
-
EXCEL VBA テキストボックスの...
-
アクセス カンレンダーコント...
-
複数のデータ系列の線の太さを...
-
エクセルでツールバーに「縮小...
-
ExcelVBAで今開いているユーザ...
-
VBAを一度起動するとずっと出て...
-
コピーしたファイルのマクロを...
-
フォルダ内の全ブックのシート...
-
エクセル終了時の保存確認メッ...
-
エクセルの指数を無効にしたい
-
Powerpointでランダムな数字の...
-
ファイル名を今日の日付、時刻...
-
excelファイルに使われているVB...
-
昨日まで動いていたエクセルの...
おすすめ情報