2

PreTranslateMessage で特定のメッセージを処理する MFC ダイアログ アプリケーションがあります。私が興味を持っているものの1つはCtrl+Rです。ただし、別のウィンドウ (Visual Studio 2010 のコード エディター、notepad++ など) をクリックしてCtrl+ C(または Ctrl+X) でテキストをコピーすると、このメッセージが表示されます。Ctrl+では発生しないようで、 と の両方をV使用して再現可能であることに注意してください。動作が非常に紛らわしいです!再現するには、Visual Studio 10 で基本的な MFC ダイアログを作成し、pretranslate を次のように追加します。GetKeyStateGetASyncKeyState

BOOL CPreTranslateTestDlg::PreTranslateMessage(MSG *pMsg)
{
    if (GetKeyState(VK_CONTROL) & 0x8000 && pMsg->wParam == 'R')
    {
        return true;
    }

    return CDialogEx::PreTranslateMessage(pMsg);
}

にブレークポイントを置きreturn true;、ダイアログを起動します。次に、Visual Studio Code ウィンドウに移動し、Ctrl+Cテキストを入力します。ブレークポイントにヒットします。

なぜこれが起こっているのかについてのアイデアはありますか?

4

2 に答える 2

5

GetKeyStateダイアログにフォーカスがあるかどうかに関係なく、キーのステータスを表示するように設計されているため、この場合は Ctrl が押されていることを正しく示しています。

第二に、発生したばかりのメッセージのタイプをチェックしていないため、キーダウンなどではない可能性があります.wParam値がたまたま「R」に等しい、キーに関連しないメッセージがトリガーされていると思われます。

ダイアログにフォーカスがあることを確認し、ダウンしGetAsyncKeyStateているかどうかを判断するために使用するように、コードを変更します。R

BOOL CPreTranslateTestDlg::PreTranslateMessage(MSG *pMsg)
{
    if (GetKeyState(VK_CONTROL) & 0x8000 && 
     GetKeyState(VK_R) & 0x8000 && 
     GetFocus == this)
    {
        return true;
    }

    return CDialogEx::PreTranslateMessage(pMsg);
}

お役に立てれば。

于 2013-03-15T21:14:14.303 に答える
0

ダイアログでキーボードショートカットをキャッチするためにこれを行います。

まず、ダイアログで使用するアクセラレータを含むアクセラレータ テーブルをリソース ファイルに用意する必要があります。

例えば:

IDR_MYDIALOG_ACCEL

IDC_CTRL_R    Ctrl+R    Virtkey

ダイアログのメッセージ マップには、次のようなものがあるはずです。

BEGIN_MESSAGE_MAP(CMyDialogDlg, CDialog)
  //{{AFX_MSG_MAP(CMyDialogDlg)
  ...
    ON_COMMAND(IDC_CTRL_R, OnMyCtrlRHandler)
    ON_WM_DESTROY()
  ...
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

OnMyCtrlRHandlerは、ショートカットによって呼び出されるメソッドです。

アクセラレータ テーブルのロードは、次のようにOnInitDialogで行われます。

BOOL CMyDialogDlg::OnInitDialog()
{
  ...
    m_hAccel = LoadAccelerators ( AfxGetResourceHandle(), 
                                  MAKEINTRESOURCE(IDR_MYDIALOG_ACCEL) );
  ...
}

m_hAccelCMyDialogDlgtypeのメンバーであることHACCEL

次のように PretranslateMessage をオーバーライドします。

BOOL CMyDialogDlg::PreTranslateMessage(MSG* pMsg)
{
    if (::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
      return(TRUE);
    else
      return CDialog::PreTranslateMessage(pMsg);
}

最後に、OnDestroy ハンドラでアクセラレータ テーブルを破棄する必要があります。

void CMyDialogDlg::OnDestroy()
{
  ...
  DestroyAcceleratorTable(m_hAccel) ;
  ...
}
于 2013-03-18T07:58:17.633 に答える