ウィンドウメッセージその2

前回のコード部分になります。
ついでに現在使っている「プロシージャ内でのCtrl,Shift押しの検出」を追加してみました。

// フックプロシージャ
LRESULT HookProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    // このウィンドウに関連あるウィンドウオブジェクト
    CEdit* edit = (CEdit*)::GetWindowLong(hWnd, GWL_USERDATA);

    // プロシージャ内におけるCtrl,Shift押しを検出
    bool bShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;
    bool bControl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;

    switch(msg) {
    case WM_KEYDOWN:
        // 全て選択
        if (bConrtol && wParam=='A') {
            edit->SetCaret(0, -1);
            edit->ScrollOnCaret();
        }
        break;

    case WM_LBUTTONDOWN:
        // マウスクリックを無効にする部分
        // 元々のプロシージャを呼ばずにreturn
        return 0;
    }

    // 元々のプロシージャを呼び出す
    return ::CallWindowProc(m_pProc, hWnd, msg, wParam, lParam);
}

::CallWindowProc()の活用方法

標準のエディットコントロールにオートインデントを実装する場合、ひとつの方法としてWM_KEYDOWN::VK_RETURNをフックします。
単に改行といっても、「改行挿入」「選択されていれば改行で上書き」「画面スクロール」等の処理がされています。
それらがあるのにわざわざ自分で作成するのは勿体無いので、デフォルトのものを利用してみます。

  • ::CallWindowProc を呼ぶ
  • インデント幅を計算
  • タブを挿入

このように先に元々のプロシージャに仕事をさせてその後に自分の処理を追加していく、ということができます。
(でも真面目にオートインデントを実装するなら、コントロールごと自分で作る方がかなり楽です(´▽`;))