Как перенаправить сообщение WM_KEYDOWN на другой элемент управления в MFC? - PullRequest
0 голосов
/ 27 августа 2011

Я сегодня в движении с MFC!: D

У меня есть текстовое поле и элемент управления представлением списка.

Когда пользователь нажимает клавиши VK_UP и VK_DOWN в текстовом поле , яхотелось бы, чтобы это произошло:

  1. Выполните некоторые действия.
  2. У элемента управления представлением списка также обрабатывается сообщение (для выделения предыдущего / следующего элемента).
  3. Я хочу, чтобы представление списка охватывало текущий выбор, , если нажатие клавиши будет первым в его последовательности.
  4. Сделайте еще кое-что.

Я попытался создать подкласс для своего окна редактирования в моем диалоговом окне:

class MyEditBox : public CWnd
{
    bool allowWrap;

    afx_msg void OnKeyUp(UINT, UINT, UINT) { this->allowWrap = true; }

    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
    {
        CListCtrl &listView = static_cast<CListView *>(
            this->GetParent()->GetDlgItem(IDC_LIST_VIEW))->GetListCtrl();

        if (nChar == VK_UP || nChar == VK_DOWN)
        {
            int iSelBefore = listView.GetNextItem(-1, LVNI_SELECTED);

            this->GetParent()->GetDlgItem(IDC_LIST_VIEW)
                ->OnKeyDown(nChar, nRepCnt, nFlags);  //Oops! Protected member :(

            int iSelAfter  = listView.GetNextItem(-1, LVNI_SELECTED);

            if (iSelBefore == iSelAfter &&  // Did the selection reach an end?
                this->allowWrap)            // If so, can we wrap it around?
            {
                int i = a == 0 ? listView.GetItemCount() - 1 : 0;
                listView.SetItemState(i, LVIS_SELECTED | LVIS_FOCUSED,
                                         LVIS_SELECTED | LVIS_FOCUSED);
            }
        }
        this->allowWrap = false;
    }
}

, но OnKeyDown() является защищенным членом, поэтому я не могупросто вызовите его на другом элементе управления.

Есть ли лучший способ решить эту проблему, чем отправка команды вручную с помощью SendMessage?Должен ли я изменить свой дизайн, например, подкласс что-то еще и т. Д.?

Ответы [ 2 ]

0 голосов
/ 05 апреля 2014

Я также вижу другие способы решения этой проблемы:

  1. Получите класс из CListCtrl с именем MyListCtrl и выберите одну из двух вещей:

    1.1Объявите MyEditBox как друга, и теперь вы можете вызывать защищенные методы для MyEditBox

    1.2. Добавьте к нему открытые методы CallOnKeyDown(...) и CallOnKeyup(...), которые делают только то, что нужно.

    И при создании элемента управления, экземпляр MyListCtrl вместо CListCtrl.Также замените переменную listView, которую вы здесь показали, на MyListCtrl и используйте доступные вам методы

  2. Используйте PreTranslateMessage(...).Я думаю, что это «молотковое» решение хуже, чем отправка сообщения.

0 голосов
/ 27 августа 2011

Вы хотите выбрать предыдущий или следующий элемент в списке управления, верно?Затем вам следует вызвать метод, чтобы сделать это прямо вместо запроса CListCtrl «обработать» ваше сообщение.

Вы можете вызвать CListCtrl :: SetSelectionMark и CListCtrl ::SetItemState для выбора следующего или предыдущего нажатия клавиши.Пример:

 cListCtrl.SetSelectionMark(nIndex);
 cListCtrl.SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED, 0xFF);

Вы можете обрабатывать клавиши «Вниз», «Вверх», а также «Вниз», «Вверх», «Конец», «Домой» или любую любую клавишу из поля ввода.Вы должны сделать расчет, хотя.

Или вы можете просто SendMessage.Нет необходимости звонить OnKeyDown напрямую.Пусть фреймворк позвонит вам, когда вы отправите сообщение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...