Метод PreTranslateMessage не получает вызванный порядок для реализации Ctrl+A в C++

Я пытаюсь реализовать Ctrl+A в элементе управления редактирования заметки:m_editNoteTypeView", который является экземпляром cEdit внутри класса NoteDialog. Редактирование моей заметки создается, как показано ниже.

NoteDialog::initDialog()
{
    m_editNoteTypeView.CreateEx(::GetWindowLong(m_editSubject.m_hWnd, GWL_EXSTYLE), "edit", "", dwStyle | ES_READONLY, CRect(0, 0, 0, 0), this, 0);
    m_editNoteTypeView.SetSel(0,-1,TRUE);
}

Класс NoteDialog является производным от другого класса с именем Sdialog, который в конечном итоге является производным от CDialog,

Я определил PreTranslateMessage(MSG* pMsg) в SDialog, но управление не идет к PreTranslateMessage, поэтому я не могу проверить, какую клавишу я нажимаю на keboard, когда я печатаю при редактировании заметки.

bool Sdialog::PreTranslateMessage(MSG* pMsg)
{
    if (GetFocus() == this) 
    {
        if (pMsg->message == WM_CHAR)
        {
            if ((LOWORD(pMsg->wParam) & VK_CONTROL) == VK_CONTROL)
            {
                //SetSel(0, -1);
            }
        }
    }

    return CDialog::PreTranslateMessage(pMsg);
}

1 ответ

return тип для PreTranslateMessage должно быть BOOL иначе вы получите ошибку компиляции в MFC.

if (pMsg->message == WM_CHAR)
    if ((LOWORD(pMsg->wParam) & VK_CONTROL) == VK_CONTROL)
        {...}

WM_CHAR сообщение не несет VK_CONTROL в wParam,

Чтобы перехватить Ctrl + A:

  • Ждать WM_KEYDOWN сообщение
  • Проверьте ключ
  • Проверьте, нажата ли клавиша Ctrl

Таким образом:

BOOL Sdialog::PreTranslateMessage(MSG* pMsg)
{
    static int i = 0;
    CString s;

    if(pMsg->message == WM_KEYDOWN)
    {
        if(GetKeyState(VK_CONTROL) & 0x8000)
        {
            if(pMsg->wParam == 'A')
            {
                ...
            }
        }
    }

    return CDialog::PreTranslateMessage(pMsg);
}

Кроме того, вы можете добавить эти вспомогательные макросы:

// Handy functions
#define IsCTRLpressed()  ( GetKeyState(VK_CONTROL) & 0x8000 )
#define IsSHIFTpressed()  ( GetKeyState(VK_SHIFT) & 0x8000 )
//15 = sizeof(SHORT) * 8 - 1
//0000 0000 0000 0001 = 1
//1000 0000 0000 0000 = 15 << 1

Тогда это может быть так просто, как:

if (IsCTRLpressed() &&
    pMsg->message == WM_KEYDOWN && pMsg->wParam == _TINT(_T('A')))
{
    // Do whatever

    // Eat it.
    bNoDispatch = TRUE;
    bDealtWith = TRUE;
}

Имейте в виду, что вам нужно решить, хотите ли вы по-прежнему запускать базовую реализацию. Если вы на самом деле обрабатываете сообщение и разбираетесь с ним, вам следует вернуться TRUE, В противном случае, пусть базовый класс справится с этим.

Пример:

BOOL Sdialog::PreTranslateMessage(MSG* pMsg)
{
    BOOL    bNoDispatch, bDealtWith;

    bDealtWith = FALSE;

    if (IsCTRLpressed() &&
        pMsg->message == WM_KEYDOWN && pMsg->wParam == _TINT(_T('A')))
    {
        // Deal with it

        // Eat it.
        bNoDispatch = TRUE;
        bDealtWith = TRUE;
    }

    if (!bDealtWith)
        bNoDispatch = CDialogEx::PreTranslateMessage(pMsg);

    return bNoDispatch;
}
Другие вопросы по тегам