Как отслеживать изменения фокуса между несколькими трекбарами с помощью WTL?

Я пытаюсь отслеживать изменения фокуса между несколькими трекбарами (они же ползунки, все в одном окне) с помощью WTL.

До сих пор я безуспешно пробовал MESSAGE_HANDLER(WM_SETFOCUS, func), а также одну COMMAND_HANDLER(IDC_SLIDERn, WM_SETFOCUS, func) для каждого ползунка.

На странице элементов управления трекбаром на msdn написано: «WM_SETFOCUS Перекрашивает окно трекбара». ..

редактировать: теперь я получил ползунки из своего собственного класса, где я обрабатываю WM_SETFOCUS с MESSAGE_HANDLER и уведомляю родительское окно, отправляя ему сообщение с m_hWnd как lParam, чтобы я мог проверить родителя, какой слайдер получил фокус.

Это работает, но есть ли более элегантный способ сделать это?


person xnor    schedule 04.02.2012    source источник


Ответы (2)


WM_SETFOCUS отправляется конкретному окну, которое получает фокус, а не родительскому окну, как вы обнаружили.

Однако есть альтернативный метод, который можно использовать, чтобы избежать создания подклассов; большинство элементов управления (в частности, «общие элементы управления», которые включают ползунки) будут отправлять WM_NOTIFY своему родителю, когда происходят определенные события, позволяя родителю обрабатывать эти события для набора дочерних элементов.

В вашем случае попробуйте прослушать сообщение WM_NOTIFY в родительском окне, в частности, проверив случай, когда идентификатор уведомления NM_SETFOCUS — из MSDN:

Notifies a control's parent window that the control has received the input focus. This notification code is sent in the form of a WM_NOTIFY message.

... похоже на то, что вы ищете. Очевидно, ATL поддерживает их в карте сообщений, используя NOTIFY_HANDLER, что-то вроде:

NOTIFY_HANDLER(IDC_SLIDERn, NM_SETFOCUS, func)

Обратите внимание, что это работает, потому что общие элементы управления Win32 поддерживают такую ​​пересылку уведомлений; если вместо этого вы будете использовать какой-либо другой настраиваемый элемент управления, вы можете не получить эти уведомления и вам придется прибегнуть к подклассам. Но для обычных элементов управления это самый простой способ сделать это.

person BrendanMcK    schedule 04.02.2012

Вам не нужно создавать свой класс, создание подклассов с помощью CContainedWindowT вполне нормально.

BEGIN_MSG_MAP_EX(CDialog)
// ...
ALT_MSG_MAP(IDC_TRACKBAR)
    MSG_WM_SETFOCUS(OnControlSetFocus)
    MSG_WM_KILLFOCUS(OnControlKillFocus)
END_MSG_MAP()
// ...
CContainedWindowT<CTrackBarCtrl> m_TrackBar;
// ...
CDialog() :
    m_TitleListView(this, IDC_TRACKBAR)
// ...
LRESULT OnInitDialog(HWND, LPARAM)
{
    // ...
    ATLVERIFY(m_TrackBar.SubclassWindow(GetDlgItem(IDC_TRACKBAR)));
    // ...
// ...  
LRESULT OnControlSetFocus(...) { }
LRESULT OnControlKillFocus(...) { }
person Roman R.    schedule 04.02.2012