0

The main form opens a child form that has a handful of button CONTROLs on it. I need to trap keyboard events so I subclassed one of the controls. All is good until the control loses focus of course.

Ideally, as long as this child form is open I would like to assign the focus to this control and thus trap all the keystrokes, no matter where the user clicks.

I suspect superclassing might be a better way to go but I am not as familiar with it.

Perhaps what I should do is use accelerators on the main form?

ADDED: I should mention that the main form has a large listview control that is subclassed to recover up/down arrows and mousewheel etc.

4

2 に答える 2

1

The traditional way is to install a keyboard hook (SetWindowsHookEx), but you need to inject it into every application, and it doesn't work across 32/64 bit boundaries.

What you can do however, and quite easily at that, is to poll the keyboard with GetKeyboardState on a timer and check whether your f1-f12 keys are activated. The timer can be as slow ticking as 100ms and it will catch almost everything while using virtually no resources.

于 2010-07-30T09:10:29.090 に答える
0

これがWindowsおよびWin32API内にあると仮定すると、1つのオプションは、メインGetMessageTranslateMessage、、DispatchMessageループでメッセージを探すことです。対象のウィンドウに関係なく、このループ内の任意のメッセージを特殊なケースにすることができます。

おそらくIsChild、メッセージがメインウィンドウのコントロールを対象としていることを確認するために使用する必要があります(個別に表示されるダイアログボックスやメッセージボックスとは対照的です)。ロジックを正しく理解するのも面倒です。コントロールがフォーカスを失ったことがわかっている場合にのみメッセージを傍受し、必要な正確なメッセージのみを傍受するのが最善です。

数年前、私はこれをたくさん組み込んだライブラリメッセージループを作成しました。自分の小さなウィンドウクラスのインスタンスへのポインタを保持する単純なマネージャクラスがありました。ループは、ダイアログと通常のウィンドウの違いを認識し、各ウィンドウクラスにその子メッセージをスパイする機会を与えました。これを直接実行することはできず、規則は少し奇妙ですが、これは便利だと思うかもしれません...

int c_Window_List::Message_Loop (void)
{
  MSG msg;
  bool l_Handled;

  while (GetMessage (&msg, NULL, 0, 0))
  {
    l_Handled = false;

    c_Windows::c_Cursor l_Cursor;
    bool                ok;

    for (ok = l_Cursor.Find_First (g_Windows); ok; ok = l_Cursor.Step_Next ())
    {
      if (IsChild (l_Cursor.Key (), msg.hwnd))
      {
        if (l_Cursor.Data ().f_Accelerators != NULL)
        {
          l_Handled = TranslateAccelerator (l_Cursor.Key (), l_Cursor.Data ().f_Accelerators, &msg);

          if (l_Handled)  break;
        }

        if (l_Cursor.Data ().f_Manager != 0)
        {
          l_Handled = l_Cursor.Data ().f_Manager->Spy_Msg (l_Cursor.Key (), msg);
        }

        if (l_Handled)  break;

        if (l_Cursor.Data ().f_Is_Dialog)
        {
          l_Handled = IsDialogMessage (l_Cursor.Key (), &msg);
          if (l_Handled)  break;
        }
      }
    }

    if (!l_Handled)
    {
      TranslateMessage (&msg);
      DispatchMessage  (&msg);
    }

    if (g_Windows.Size () == 0)
    {
      //  When all windows have closed, exit
      PostQuitMessage (0);
    }
  }

  return msg.wParam;
}

接頭辞はf_フィールドを意味します-後で規則を取り上げましたm_が、このコードは非常に長い間再検討されていません。特に私のクラスf_Managerのインスタンスを指しています。クラスは一種のイテレータであり、変数に格納されているすべてのウィンドウ(実際にはグローバルではなく静的クラスメンバー)をステップスルーするために使用されc_Window_Baseます。c_Cursorg_Windows

于 2010-07-30T09:55:16.980 に答える