• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:ExcelVBA: ダイアログで F1 ヘルプ?)

ExcelVBAでF1ヘルプを表示する方法とファンクションキーでマクロを起動する方法

このQ&Aのポイント
  • ExcelVBAでユーザーフォームでF1ボタンを押下するとヘルプ画面が表示される方法について教えてください。
  • UserForm_KeyPressイベントでF1を拾う方法について知りたいです。
  • ExcelVBAでファンクションキーを押すとマクロが起動する方法について教えてください。

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

  • ベストアンサー
  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.4

■その3 対象となるフォームのコードウインドウを表示して、順に作業してください。 使い方はシンプルです。 ' // 宣言セクション(冒頭)で clsKeyDown クラスをイベント付で使用する ' // と宣言する Private WithEvents m_clsKeyDown As clsKeyDown ' // Initialize イベント Private Sub UserForm_Initialize()   ' // clsKeyDown クラスのインスタンスを生成する   Set m_clsKeyDown = New clsKeyDown   ' // clsKeyDown クラスの KeyDownEventHook メソッドにフォーム   ' // 自身(Me)を渡す   m_clsKeyDown.KeyDownEventHook Me End Sub ' // QueryClose イベント Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)   ' // 明示してインスタンスを破棄してるだけ。必須ではない   Set m_clsKeyDown = Nothing End Sub とここまで、やってしまえば、コードウインドウ左上のコンボボックスで m_clsKeyDown を選べば、勝ってにイベントプロシージャが書き込まれます。 だいたい、眺めてもらえばわかると思いますが、第一引数 ctrl には、 KeyDown イベントの発生したコントロール自身が、KeyCode には押された キーが、Shift には、Shift キー、Ctrl キー、Alt キーなどの装飾キーの 状態が渡されてきます。 ' // 例 Private Sub m_clsKeyDown_KeyDown(ByVal ctrl As MSForms.Control, ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   MsgBox "Ctrl Name:= " & ctrl.Name & vbLf & _       "KeyCode:= " & CStr(KeyCode) & vbLf & _       "Shift:= " & CStr(Shift) End Sub 今回は、コントロールがどうこうというのではなく、フォーカスがどこに あっても F1 キーの入力を検知するのが目的なので、こんな感じ。 Private Sub m_clsKeyDown_KeyDown(ByVal ctrl As MSForms.Control, ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   If KeyCode = vbKeyF1 Then     MsgBox "[F1] KeyDown [ " & ctrl.Name & " ]"   End If End Sub まあ、初回導入は多少大変なのですが、一回クラスを作成してしまえば、 あとは他案件でもクラスのインポート・エクスポートで流用できてしまいます。 取り付けるフォームに書き込むコードの量は少なくなりますしね。 そもそも KeyPreview プロパティーがあれば、こんなことしなくても良い はずなんですが、、、

TYWalker
質問者

お礼

ありがとうございます!!! 無事に動作しました。 これだと、F1 が押下されたときのフォーカスのあるコントロールによって、たとえば URL にアンカーを渡して Web ページの表示位置を変えることもできるので願ったりかなったりです。 大変たすかりました!

その他の回答 (3)

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.3

■その2 1. クラスモジュールを挿入し、名前を clsKeyDownEvent に変更 2. 以下ソース Option Explicit ' // KeyDown イベント子クラス Private WithEvents chk As MSForms.CheckBox Private WithEvents cbo As MSForms.ComboBox Private WithEvents cmb As MSForms.CommandButton Private WithEvents frm As MSForms.Frame Private WithEvents lst As MSForms.ListBox Private WithEvents mlt As MSForms.MultiPage Private WithEvents opt As MSForms.OptionButton Private WithEvents scr As MSForms.ScrollBar Private WithEvents spn As MSForms.SpinButton Private WithEvents txt As MSForms.TextBox Private WithEvents tbs As MSForms.TabStrip Private WithEvents tgl As MSForms.ToggleButton Private m_ParentClass As clsKeyDown ' // 親クラス ' // Constracta, Destracta ++++++++++++++++++++++++++++++++++++++++++ Private Sub Class_Terminate()   Set m_ParentClass = Nothing   Set chk = Nothing: Set cbo = Nothing: Set cmb = Nothing   Set frm = Nothing: Set lst = Nothing: Set mlt = Nothing   Set opt = Nothing: Set scr = Nothing: Set spn = Nothing   Set tbs = Nothing: Set tgl = Nothing: Set txt = Nothing End Sub ' // Methods +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Public Sub ParentClass(ByRef ParentClass As clsKeyDown)   Set m_ParentClass = ParentClass End Sub Public Sub Bind(ByVal ctrl As MSForms.Control)   Select Case UCase$(TypeName(ctrl))     Case "CHECKBOX":    Set chk = ctrl     Case "COMBOBOX":    Set cbo = ctrl     Case "COMMANDBUTTON":  Set cmb = ctrl     Case "FRAME":      Set frm = ctrl     Case "LISTBOX":     Set lst = ctrl     Case "MULTIPAGE":    Set mlt = ctrl     Case "OPTIONBUTTON":  Set opt = ctrl     Case "SCROLLBAR":    Set scr = ctrl     Case "SPINBUTTON":   Set spn = ctrl     Case "TABSTRIP":    Set tbs = ctrl     Case "TOGGLEBUTTON":  Set tgl = ctrl     Case "TEXTBOX":     Set txt = ctrl   End Select End Sub ' // Events +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Private Sub chk_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(chk, KeyCode, Shift) End Sub Private Sub cbo_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(cbo, KeyCode, Shift) End Sub Private Sub cmb_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(cmb, KeyCode, Shift) End Sub Private Sub frm_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(frm, KeyCode, Shift) End Sub Private Sub lst_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(lst, KeyCode, Shift) End Sub Private Sub mlt_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(mlt, KeyCode, Shift) End Sub Private Sub opt_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(opt, KeyCode, Shift) End Sub Private Sub scr_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(scr, KeyCode, Shift) End Sub Private Sub spn_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(spn, KeyCode, Shift) End Sub Private Sub tbs_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(tbs, KeyCode, Shift) End Sub Private Sub tgl_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(tgl, KeyCode, Shift) End Sub Private Sub txt_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   RaiseEvent m_ParentClass.FireEvent(txt, KeyCode, Shift) End Sub

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.2

ちょっと長いので、分割して投稿します。 ■その1 1. クラスモジュールを挿入し、名前を clsKeyDown に変更 2. 以下ソース Option Explicit ' // KeyDown イベントクラス ' // カスタムイベント Public Event KeyDown(ByVal ctrl As MSForms.Control, _            ByVal KeyCode As MSForms.ReturnInteger, _            ByVal Shift As Integer) ' // 子クラスを割り当てるコントロールの種類リスト Private Const LIST_BIND_CONTROLS As String = _     "CHECKBOX,COMBOBOX,COMMANDBUTTON,FRAME,MULTIPAGE,LISTBOX," & _     "OPTIONBUTTON,"SCROLLBAR,SPINBUTTON,TABSTRIP,TEXTBOX," & _     "TOGGLEBUTTON" Private m_clsKeyDownEvent() As clsKeyDownEvent ' // イベント用子クラス ' // Constracta, Destracta ++++++++++++++++++++++++++++++++++++++++++ Private Sub Class_Initialize()   ' // 特になし End Sub Private Sub Class_Terminate()   Dim i As Long   On Error Resume Next   For i = 0 To UBound(m_clsKeyDownEvent)     Set m_clsKeyDownEvent(i) = Nothing   Next End Sub ' // Methods +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ' // 引数 frm 内のコントロールを走査して、それぞれにイベントトラップ用 ' // の子クラスを割り当てます Public Sub KeyDownEventHook(ByRef frm As MSForms.UserForm)   Dim ctrl As MSForms.Control   Dim i  As Long      For Each ctrl In frm.Controls     If InStr(LIST_BIND_CONTROLS, UCase$(TypeName(ctrl))) > 0 Then       i = i + 1       ReDim Preserve m_clsKeyDownEvent(i)       Set m_clsKeyDownEvent(i) = New clsKeyDownEvent       With m_clsKeyDownEvent(i)         .ParentClass Me         .Bind ctrl       End With     End If   Next    End Sub ' // 子クラスから呼び出され、カスタムイベントを発生させます Public Sub FireEvent(ByVal ctrl As MSForms.Control, _            ByVal KeyCode As MSForms.ReturnInteger, _            ByVal Shift As Integer)   RaiseEvent KeyDown(ctrl, KeyCode, Shift) End Sub

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.1

こんにちは。 KeyPress ではなく、KeyDown イベントを使ってみてください。 Private Sub UserForm_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   If KeyCode = vbKeyF1 Then     MsgBox "[F1]が押された"   End If End Sub ただし、フォームにひとつでも「フォーカスを受け取る」コントロール、 例えば Textbox 等があると Userform 側の KeyDown、KeyUp、KeyPress のイベントが発生しません。 Excel には Access のように Userform に KeyPreview プロパティーが ありません。 したがって、解決策としては、   1. フォーカスを受け取る全てのコントロールに KeyDown     イベントを書く   2. API を使ってキーボードフックするかホットキーを     割り当てる などとなってくるでしょう。 1. の場合、10個のコントロールがあるなら 10個の KeyDown を書くという 意味です。これが最もわかりやすい。 コンロトール数が多くなってくると 1. にクラスモジュールを使うか、2. の選択になってきます。この場合は、いずれにしても難易度は高いです。 私が過去に書いたクラスでよければ、補足していただければアップしますが。

TYWalker
質問者

お礼

ありがとうございます。 くだんのフォームにはコントロールが100個以上あります (^^; 以前も、あるコンボボックスが Any という値だったら、その隣のテキストボックスの Enabled を False にする、というお題でここのお世話になり、クラスモジュールを使用してうまくいきました。 http://okwave.jp/qa4714089.html ということで、よろしければクラスモジュールの使い方を教えてくださるようお願いいたします。 ダイアログに F1 ヘルプを書くというありがちな挙動がプラットフォームでサポートされているとは思わず、安易に質問してしまいました。 よろしくお願いいたします!

関連するQ&A