MFCの基礎 - キーボード

提供: MochiuWiki : SUSE, EC, PCB

📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

概要

MFCアプリケーションにおけるキーボード処理は、Windowsのメッセージドリブン設計に基づいて実装される。

キーボード入力は、WM_KEYDOWN、WM_KEYUP、WM_CHARなどのWindowsメッセージとして処理される。
MFCは、これらのメッセージを処理するための便利なメッセージハンドラ (OnKeyDown、OnKeyUp、OnChar等) を提供している。

  • キーボードメッセージの種類と処理フロー
  • 仮想キーコードと文字コードの違い
  • GetKeyState関数とGetAsyncKeyState関数によるキー状態の取得
  • MFCのキーボードイベントハンドラ
  • アクセラレータキーとホットキーの登録
  • キーボード入力のシミュレーション


仮想キーコードは、キーボードのキー自体を識別するためのコードであり、VK_RETURNVK_SHIFT 等の定数で表現される。
一方、文字コードは、キー入力によって生成される文字を表すコードであり、WM_CHAR メッセージで取得できる。

MFCのキーボード処理を理解することにより、以下に示す機能を実装できる。

  • ショートカットキーの実装
  • ゲームや対話型アプリケーションのキー入力処理
  • カスタムキーバインディング
  • キーボードマクロとオートメーション



キーボードメッセージ

Windowsは、キーボード入力を複数のメッセージとして処理する。

主要なキーボードメッセージ
メッセージ 説明
WM_KEYDOWN / WM_KEYUP キーが押下された時と離された時に送信される。
WM_CHAR 文字入力時に送信される。
(TranslateMessage関数による変換後)
WM_SYSKEYDOWN / WM_SYSKEYUP Altキーと組み合わせたシステムキー入力時に送信される。


キーボードメッセージの処理フローを理解することは、適切なキーボード処理の実装に不可欠である。

WM_KEYDOWN / WM_KEYUP

  • WM_KEYDOWNメッセージ
    キーが押下された時に送信される。
  • WM_KEYUPメッセージ
    キーが離された時に送信される。


※注意
WM_KEYDOWN と WM_KEYUP は、文字入力ではなく、キーの物理的な押下と解放を検出する場合に使用する。

メッセージパラメータ
パラメータ 説明
wParam 仮想キーコード (VK_RETURN、VK_ESCAPE等)
lParam キーの詳細情報 (リピートカウント、スキャンコード、拡張キーフラグ等)


lParamの構造
ビット 説明
0〜15 リピートカウント
16〜23 スキャンコード
24 拡張キーフラグ (1の場合、拡張キー)
29 コンテキストコード (Altキーが押されている場合は1)
30 前のキー状態 (既に押されていた場合は1)
31 遷移状態 (WM_KEYUPの場合は1)


WM_CHAR

  • WM_CHARメッセージ
    文字入力時に送信される。


WM_CHARメッセージは、TranslateMessage 関数により WM_KEYDOWN メッセージから生成される。
TranslateMessage 関数は、仮想キーコードを文字コードに変換する。

メッセージパラメータ
パラメータ 説明
wParam 文字コード (ASCII文字やUnicode文字)
lParam キーの詳細情報 (WM_KEYDOWNと同様)


WM_CHARメッセージは、テキスト入力を処理する場合に使用する。
例えば、エディットコントロールやカスタムテキストエディタの実装に利用する。

また、WM_CHARメッセージは、Shift、Ctrl、Altキーの状態を考慮した文字コードを提供する。
例えば、[Shift]キー + [A]キーを同時押下する時、wParamは"A"の文字コードとなる。

WM_SYSKEYDOWN / WM_SYSKEYUP

WM_SYSKEYDOWNメッセージ と WM_SYSKEYUPメッセージは、[Alt]キーと組み合わせたキー入力時に送信される。

これらのメッセージは、システムキーの処理に使用される。
システムキーには、[Alt] + [F4] (ウィンドウを閉じる)、[Alt] + [Tab] (タスク切り替え) 等が含まれる。

メッセージパラメータは、WM_KEYDOWN と WM_KEYUPと同様である。

WM_SYSKEYDOWN と WM_SYSKEYUPを処理する場合、通常は DefWindowProc 関数に渡して、デフォルトのシステム動作を維持する。
カスタム処理が必要な場合のみ、これらのメッセージを独自に処理する。

メッセージの処理フロー

キーボードメッセージの処理フローを以下に示す。

  1. ユーザがキーを押下する。
  2. Windowsは、WM_KEYDOWNメッセージを生成する。
  3. アプリケーションのメッセージループは、TranslateMessage関数を呼び出す。
  4. TranslateMessage関数は、WM_KEYDOWNからWM_CHARメッセージを生成する。(文字キーの場合)
  5. DispatchMessage関数は、メッセージをウィンドウプロシージャに送信する。
  6. ウィンドウプロシージャは、メッセージハンドラを呼び出す。


この処理フローを理解することにより、適切なメッセージハンドラを選択できる。

文字入力を処理する場合は、WM_CHARメッセージを使用する。
キーの物理的な押下を検出する場合は、WM_KEYDOWNメッセージを使用する。


仮想キーの取得

GetKeyState 関数は、特定の仮想キーの状態を取得する関数である。

関数のプロトタイプを以下に示す。

 SHORT GetKeyState(int nVirtKey);


引数 (パラメータ) と 戻り値
種別 項目 説明
引数 (パラメータ) nVirtKey 仮想キーコード (VK_SHIFT、VK_CONTROL等)
戻り値 最上位ビット (ビット15) キーが押されている場合は1、それ以外は0
最下位ビット (ビット0) キーのトグル状態 (CapsLockやNumLockの場合、ONの時は1)


使用例を以下に示す。

 // Shiftキーが押されているか確認
 if (GetKeyState(VK_SHIFT) & 0x8000) {
    // [Shift]キーが押下されている場合
 }
 
 // CapsLockがONか確認
 if (GetKeyState(VK_CAPITAL) & 0x0001) {
    // [CapsLock]がONの状態
 }


下表に、主要な仮想キー定数を示す。

主要な仮想キー定数
定数 説明
VK_SHIFT Shiftキー
VK_CONTROL Ctrlキー
VK_MENU Altキー
VK_LSHIFT 左Shiftキー
VK_RSHIFT 右Shiftキー
VK_LCONTROL 左Ctrlキー
VK_RCONTROL 右Ctrlキー
VK_LMENU 左Altキー
VK_RMENU 右Altキー


矢印キーと編集キー
定数 説明
VK_LEFT 左矢印キー
VK_UP 上矢印キー
VK_RIGHT 右矢印キー
VK_DOWN 下矢印キー
VK_INSERT Insertキー
VK_DELETE Deleteキー
VK_HOME Homeキー
VK_END Endキー
VK_PRIOR Page Upキー
VK_NEXT Page Downキー


特殊キー
定数 説明
VK_RETURN Enterキー
VK_ESCAPE Escapeキー
VK_SPACE Spaceキー
VK_TAB Tabキー
VK_BACK Backspaceキー
VK_CAPITAL CapsLockキー
VK_NUMLOCK NumLockキー
VK_SCROLL ScrollLockキー


ファンクションキー
定数 説明
VK_F1 F1キー
VK_F2 F2キー
VK_F3 F3キー
VK_F4 F4キー
VK_F5 F5キー
VK_F6 F6キー
VK_F7 F7キー
VK_F8 F8キー
VK_F9 F9キー
VK_F10 F10キー
VK_F11 F11キー
VK_F12 F12キー


GetKeyState 関数は、現在のスレッドのメッセージキュー内の最後のメッセージの時点でのキー状態を返す。
リアルタイムのキー状態を取得する場合は、GetAsyncKeyState 関数を使用する。


GetAsyncKeyState関数

GetAsyncKeyState 関数は、リアルタイムのキー状態を取得する関数である。

関数のプロトタイプを以下に示す。

 SHORT GetAsyncKeyState(int vKey);


パラメータと戻り値は、GetKeyState 関数と同様である。

GetKeyState関数との違い

GetKeyState関数とGetAsyncKeyState関数の違いを以下に示す。

GetKeyState関数 と GetAsyncKeyState関数 の比較
項目 GetKeyState関数 GetAsyncKeyState関数
取得タイミング メッセージキュー内の最後のメッセージ時点 関数呼び出し時点 (リアルタイム)
用途 メッセージハンドラ内での使用 ゲームループや非同期処理での使用
同期性 同期的 (メッセージキューと同期) 非同期的 (現在の物理的なキー状態)
マルチスレッド スレッドごとに独立 システム全体で共有


  • GetKeyState関数
    メッセージドリブンな処理に適している。
    メッセージハンドラ内で使用することにより、メッセージが生成された時点のキー状態を正確に取得できる。

  • GetAsyncKeyState関数
    リアルタイムなキー状態の検出に適している。
    ゲームのメインループや、定期的なタイマー処理でキー状態をポーリングする場合に使用する。


使用例

GetAsyncKeyState関数の使用例を以下に示す。

 // ゲームループ内でのキー状態チェック
 
 void CGameView::OnTimer(UINT_PTR nIDEvent)
 {
    // 矢印キーで移動制御
    if (GetAsyncKeyState(VK_LEFT) & 0x8000) {
       m_playerX -= 5;  // 左に移動
    }
 
    if (GetAsyncKeyState(VK_RIGHT) & 0x8000) {
       m_playerX += 5;  // 右に移動
    }
 
    if (GetAsyncKeyState(VK_UP) & 0x8000) {
       m_playerY -= 5;  // 上に移動
    }
 
    if (GetAsyncKeyState(VK_DOWN) & 0x8000) {
       m_playerY += 5;  // 下に移動
    }
 
    // [Space]キーでジャンプ
    if (GetAsyncKeyState(VK_SPACE) & 0x8000) {
       Jump();
    }
 
    Invalidate();  // 再描画
    CView::OnTimer(nIDEvent);
 }


この例では、タイマーイベント内で定期的にキー状態をチェックし、プレイヤーの位置を更新している。

GetAsyncKeyState関数は、複数のキーの同時押しを検出する場合にも便利である。

 // [Ctrl] + [S]キーの同時押下を検出
 
 if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) && (GetAsyncKeyState('S') & 0x8000)) {
    SaveDocument();
 }



MFCでのキーボードイベントハンドラ

MFCは、キーボードメッセージを処理するための便利なメッセージハンドラを提供している。

主要なキーボードイベントハンドラ
メソッド 説明
OnKeyDown / OnKeyUp WM_KEYDOWN / WM_KEYUPメッセージの処理
OnChar WM_CHARメッセージの処理
PreTranslateMessage メッセージの前処理 (メッセージがDispatchされる前に介入)


これらのハンドラを適切に使用することにより、柔軟なキーボード処理を実装できる。

OnKeyDown / OnKeyUp

OnKeyDown イベントハンドラ と OnKeyUp イベントハンドラ は、キーの押下と解放を処理するハンドラである。

関数のプロトタイプを以下に示す。

 afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
 afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);


引数 (パラメータ)
項目 説明
nChar 仮想キーコード
nRepCnt リピートカウント (キーが押下され続けている場合の繰り返し回数)
nFlags キーの詳細情報 (拡張キーフラグ、コンテキストコード等)


OnKeyDownハンドラを使用することにより、特定のキーに対する処理を簡潔に実装できる。

使用例を以下に示す。

 void CMyView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
 {
    switch (nChar)
    {
    case VK_LEFT:
       // [左矢印]キーが押下された場合
       MoveLeft();
       break;
    case VK_RIGHT:
       // [右矢印]キーが押下された場合
       MoveRight();
       break;
    case VK_ESCAPE:
       // [Esc]キーが押下された場合
       CancelOperation();
       break;
    case VK_F1:
       // [F1]キーが押下された場合 (ヘルプ表示)
       ShowHelp();
       break;
    default:
       CView::OnKeyDown(nChar, nRepCnt, nFlags);
       break;
    }
 }


OnChar

OnChar イベントハンドラは、文字入力を処理するハンドラである。

関数のプロトタイプを以下に示す。

 afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);


パラメータ
項目 説明
nChar 文字コード (ASCII文字やUnicode文字)
nRepCnt リピートカウント
nFlags キーの詳細情報


OnCharハンドラは、テキスト入力を処理する場合に使用する。
Shift、Ctrl、Altキーの状態を考慮した文字コードが提供されるため、文字入力処理が簡潔になる。

使用例を以下に示す。

 void CMyView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
 {
    if (nChar == VK_RETURN) {
       // [Enter]キーが押下された場合
       ProcessInput();
    }
    else if (nChar == VK_ESCAPE) {
       // [Esc]キーが押下された場合
       CancelInput();
    }
    else if (nChar >= 32) {
       // 印字可能文字の場合
       // 文字を入力バッファに追加
       m_inputBuffer += (TCHAR)nChar;
       Invalidate();
    }
 
    CView::OnChar(nChar, nRepCnt, nFlags);
 }


PreTranslateMessageメソッド

PreTranslateMessage メソッドは、メッセージがディスパッチされる前に呼び出されるメソッドである。
このメソッドをオーバーライドすることにより、メッセージの前処理やフィルタリングを実装できる。

ディスパッチ (Dispatch) とは、メッセージを適切なウィンドウプロシージャに転送することを意味する。
Windowsのメッセージループでは、一般的に以下に示す流れで処理される。

  1. GetMessage関数
    メッセージキューからメッセージを取得する。
  2. TranslateMessage関数
    キーボードメッセージを文字メッセージに変換する。
  3. DispatchMessage関数
    メッセージを対象ウィンドウのウィンドウプロシージャ (WndProc) に転送する。


PreTranslateMessageメソッドは、このDispatchMessageが呼ばれる前の段階で介入できるメソッドである。
このメソッドがTRUEを返す場合、メッセージはウィンドウプロシージャに転送されずに、破棄または独自処理される。
これにより、特定のキー入力を横取りしてショートカットキーとして処理する等の実装が可能になる。

関数のプロトタイプを以下に示す。

 virtual BOOL PreTranslateMessage(MSG* pMsg);


引数 (パラメータ) と 戻り値
種別 項目 説明
パラメータ pMsg メッセージ構造体へのポインタ
戻り値 TRUE メッセージを処理済み (DispatchMessageに渡さない)
FALSE メッセージを通常通り処理 (DispatchMessageに渡す)


使用例を以下に示す。

 BOOL CMyDialog::PreTranslateMessage(MSG* pMsg)
 {
    if (pMsg->message == WM_KEYDOWN) {
       // [Enter]キーの処理を無効化 (ダイアログを閉じないようにする)
       if (pMsg->wParam == VK_RETURN) {
          // カスタム処理
          OnEnterKey();
          return TRUE;  // メッセージを消費
       }
 
       // [Esc]キーの処理を無効化
       if (pMsg->wParam == VK_ESCAPE) {
          // カスタム処理
          OnEscapeKey();
          return TRUE;  // メッセージを消費
       }
 
       // [Tab]キーで次のコントロールに移動 (カスタム順序)
       if (pMsg->wParam == VK_TAB) {
          FocusNextControl();
          return TRUE;  // メッセージを消費
       }
    }
 
    return CDialog::PreTranslateMessage(pMsg);
 }


PreTranslateMessageメソッドは、ダイアログのデフォルト動作を変更する場合に特に有用である。

例えば、ダイアログでは、[Enter]キーを押下するとOKボタンが押下され、[Esc]キーを押下するとキャンセルボタンが押下されるデフォルト動作がある。
PreTranslateMessageメソッドをオーバーライドすることにより、この動作をカスタマイズできる。


アクセラレータキー

アクセラレータキー (ショートカットキー) は、メニューコマンドをキーボードから直接実行する機能である。

MFCでは、リソースを使用した実装と、動的な実装の2つの方法がある。

リソースを使用した実装

リソースエディタを使用してアクセラレータテーブルを定義する方法を以下に示す。

ステップ 1 : リソースファイルの編集

リソースファイル (.rc) にアクセラレータテーブルを追加する。

 IDR_MAINFRAME ACCELERATORS
 BEGIN
    "N",      ID_FILE_NEW,       VIRTKEY, CONTROL  // Ctrl+N
    "O",      ID_FILE_OPEN,      VIRTKEY, CONTROL  // Ctrl+O
    "S",      ID_FILE_SAVE,      VIRTKEY, CONTROL  // Ctrl+S
    VK_F1,    ID_HELP,           VIRTKEY           // F1
    VK_F5,    ID_VIEW_REFRESH,   VIRTKEY           // F5
    "Q",      ID_APP_EXIT,       VIRTKEY, CONTROL  // Ctrl+Q
 END


ステップ 2 : アクセラレータテーブルのロード

アプリケーションクラスでアクセラレータテーブルをロードする。

 BOOL CMyApp::InitInstance()
 {
    // アクセラレータテーブルのロード
    m_hAccelTable = LoadAccelerators(AfxGetInstanceHandle(),
                                     MAKEINTRESOURCE(IDR_MAINFRAME));
 
    // メインウィンドウの作成など
    // ...
 
    return TRUE;
 }


ステップ 3 : メッセージループでの処理

メッセージループでTranslateAccelerator関数を呼び出す。

MFCでは、CWinAppクラスが自動的にアクセラレータテーブルを処理するため、通常は追加のコードは不要である。

ステップ 4 : コマンドハンドラの実装

各コマンドIDに対するハンドラを実装する。

 void CMainFrame::OnFileNew()
 {
    // [Ctrl] + [N]キーが押下された時の処理
    AfxMessageBox(_T("新規ファイル作成"));
 }
 
 void CMainFrame::OnFileOpen()
 {
    // [Ctrl] + [O]キーが押下された時の処理
    CFileDialog dlg(TRUE);
    if (dlg.DoModal() == IDOK) {
       OpenFile(dlg.GetPathName());
    }
 }


動的なアクセラレータ作成

実行時に動的にアクセラレータテーブルを作成する方法を以下に示す。

 void CMainFrame::CreateDynamicAccelerators()
 {
    // アクセラレータテーブルの定義
    ACCEL accel[3];
 
    // [Ctrl] + [N]キー
    accel[0].fVirt = FCONTROL | FVIRTKEY;
    accel[0].key = 'N';
    accel[0].cmd = ID_FILE_NEW;
 
    // [Ctrl] + [O]キー
    accel[1].fVirt = FCONTROL | FVIRTKEY;
    accel[1].key = 'O';
    accel[1].cmd = ID_FILE_OPEN;
 
    // [F5]キー
    accel[2].fVirt = FVIRTKEY;
    accel[2].key = VK_F5;
    accel[2].cmd = ID_VIEW_REFRESH;
 
    // アクセラレータテーブルの作成
    m_hAccelTable = CreateAcceleratorTable(accel, 3);
 
    // 既存のアクセラレータテーブルを破棄
    if (m_hOldAccelTable != NULL) {
       DestroyAcceleratorTable(m_hOldAccelTable);
    }
 }


動的なアクセラレータ作成は、ユーザがキーバインディングをカスタマイズできる機能を実装する場合に有用である。


ホットキーの登録

ホットキーは、アプリケーションがフォーカスを持っていない場合でも検出できるグローバルなキーボードショートカットである。

RegisterHotKey 関数を使用して、システム全体で有効なホットキーを登録できる。

RegisterHotKey関数

RegisterHotKey関数は、ホットキーを登録する関数である。

関数のプロトタイプを以下に示す。

 BOOL RegisterHotKey(
    HWND hWnd,
    int id,
    UINT fsModifiers,
    UINT vk
 );


引数 (パラメータ)
項目 説明
hWnd ホットキーが押下された時にWM_HOTKEYメッセージを受け取るウィンドウのハンドル
id ホットキーの識別子 (0x0000〜0xBFFFの範囲)
fsModifiers 修飾キー (MOD_ALT、MOD_CONTROL、MOD_SHIFT、MOD_WIN)
vk 仮想キーコード


使用例を以下に示す。

 // [Ctrl] + [Alt] + [F12]キーをホットキーとして登録
 BOOL CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
 {
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1) {
       return -1;
    }
 
    // ホットキーの登録 (ID: 1)
    if (!RegisterHotKey(m_hWnd, 1, MOD_CONTROL | MOD_ALT, VK_F12)) {
       AfxMessageBox(_T("ホットキーの登録に失敗しました"));
    }
 
    return 0;
 }
 
 // ホットキーの解除
 void CMainFrame::OnDestroy()
 {
    UnregisterHotKey(m_hWnd, 1);
    CFrameWnd::OnDestroy();
 }


WM_HOTKEYメッセージの処理

ホットキーが押下されると、WM_HOTKEYメッセージが送信される。

メッセージハンドラの実装を以下に示す。

 // ヘッダファイルでメッセージマップを宣言
 class CMainFrame : public CFrameWnd
 {
 protected:
    afx_msg LRESULT OnHotKey(WPARAM wParam, LPARAM lParam);
    DECLARE_MESSAGE_MAP()
 };
 
 // メッセージマップの定義
 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    ON_WM_HOTKEY()
 END_MESSAGE_MAP()
 
 // ハンドラの実装
 LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
 {
    int nHotKeyId = (int)wParam;
    UINT fsModifiers = (UINT)LOWORD(lParam);
    UINT vk = (UINT)HIWORD(lParam);
 
    if (nHotKeyId == 1) {
       // [Ctrl] + [Alt] + [F12]キーが押下された場合
       AfxMessageBox(_T("ホットキーが押されました"));
    }
 
    return 0;
 }


※注意
ホットキーは、システム全体で有効なため、他のアプリケーションと競合しないように注意する必要がある。
また、アプリケーション終了時には、必ずUnregisterHotKey関数でホットキーを解除する。


キーボード入力のシミュレーション

プログラムから仮想的にキーボード入力を生成する技術を、キーボード入力のシミュレーションという。

Windowsでは、SendInput 関数 と keybd_event 関数の2つの方法がある。

  • SendInput関数
    Windows 2000以降で推奨される方法である。
  • keybd_event関数
    レガシーな方法であり、互換性のために残されている。


SendInput関数

SendInput関数は、キーボードやマウスの入力イベントを合成する関数である。

関数のプロトタイプを以下に示す。

 UINT SendInput(
    UINT nInputs,
    LPINPUT pInputs,
    int cbSize
 );


引数 (パラメータ)
項目 説明
nInputs 入力イベントの数
pInputs INPUT構造体の配列
cbSize INPUT構造体のサイズ


使用例を以下に示す。

 void SendKeyPress(WORD vkCode)
 {
    INPUT inputs[2] = {};
 
    // キー押下イベント
    inputs[0].type = INPUT_KEYBOARD;
    inputs[0].ki.wVk = vkCode;
    inputs[0].ki.dwFlags = 0;  // キーダウン
 
    // キー解放イベント
    inputs[1].type = INPUT_KEYBOARD;
    inputs[1].ki.wVk = vkCode;
    inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
 
    // 入力イベントの送信
    UINT uSent = SendInput(2, inputs, sizeof(INPUT));
    if (uSent != 2) {
       AfxMessageBox(_T("SendInputに失敗しました"));
    }
 }
 
 // 使用例 : [Enter]キーを送信
 void CMyView::SimulateEnterKey()
 {
    SendKeyPress(VK_RETURN);
 }


修飾キー付きのキー入力をシミュレートする例を以下に示す。

 void SendCtrlC()
 {
    INPUT inputs[4] = {};
 
    // [Ctrl]キー押下
    inputs[0].type = INPUT_KEYBOARD;
    inputs[0].ki.wVk = VK_CONTROL;
    inputs[0].ki.dwFlags = 0;
 
    // [C]キー押下
    inputs[1].type = INPUT_KEYBOARD;
    inputs[1].ki.wVk = 'C';
    inputs[1].ki.dwFlags = 0;
 
    // [C]キー解放
    inputs[2].type = INPUT_KEYBOARD;
    inputs[2].ki.wVk = 'C';
    inputs[2].ki.dwFlags = KEYEVENTF_KEYUP;
 
    // [Ctrl]キー解放
    inputs[3].type = INPUT_KEYBOARD;
    inputs[3].ki.wVk = VK_CONTROL;
    inputs[3].ki.dwFlags = KEYEVENTF_KEYUP;
 
    SendInput(4, inputs, sizeof(INPUT));
 }


SendInput関数は、UIPI (User Interface Privilege Isolation) の制約を受ける。
低い整合性レベルのアプリケーションから、高い整合性レベルのアプリケーションに入力を送信することはできない。

keybd_event関数

keybd_event関数は、レガシーなキーボード入力シミュレーション関数である。

関数のプロトタイプを以下に示す。

 VOID keybd_event(
    BYTE bVk,
    BYTE bScan,
    DWORD dwFlags,
    ULONG_PTR dwExtraInfo
 );


引数 (パラメータ)
項目 説明
bVk 仮想キーコード
bScan スキャンコード
(通常は0)
dwFlags フラグ
(KEYEVENTF_KEYUP等)
dwExtraInfo 追加情報
(通常は0)


使用例を以下に示す。

 void SendKeyPressLegacy(BYTE vkCode)
 {
    // キー押下
    keybd_event(vkCode, 0, 0, 0);
 
    // キー解放
    keybd_event(vkCode, 0, KEYEVENTF_KEYUP, 0);
 }
 
 // [Ctrl] + [V]キーの送信
 void SendCtrlV()
 {
    // [Ctrl]キー押下
    keybd_event(VK_CONTROL, 0, 0, 0);
 
    // [V]キー押下
    keybd_event('V', 0, 0, 0);
 
    // [V]キー解放
    keybd_event('V', 0, KEYEVENTF_KEYUP, 0);
 
    // [Ctrl]キー解放
    keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
 }


※注意
keybd_event関数は、Windows 2000以降では非推奨とされている。
新規開発では、SendInput関数の使用を推奨する。

キーボード入力のシミュレーションは、自動化ツール、テストツール、マクロツールなどの実装に利用される。
ただし、セキュリティ上の理由から、使用には注意が必要である。


関連リンク