Исчерпывающее руководство по написанию всплывающих подсказок | страница 22



CTitleTipListBox::OnMouseMove проверяет, не попадает ли курсор мыши на какую-нибудь строку, чтобы показать подсказку для этой строки. Эта проверка осуществляется только когда приложение с элементом "список" активно и курсор мыши действительно изменил свое положение. Я выяснил, что Windows иногда посылает несколько сообщений WM_MOUSEMOVE для одной и той же позиции курсора, поэтому я использую переменную m_LastMouseMovePosition для фильтрации этих лишних сообщений. Далее CTitleTipListBox::OnMouseMove проверяет, находится ли курсор мыши в клиентской области списка. Курсор вполне может оказаться за пределами клиентской области из-за захвата курсора мыши. Забавный побочный эффект наблюдается, если не делать такой проверки – подсказка может появиться для строк, невидимых в списке в данный момент. Если же курсор мыши находится в клиентской области списка, CTitleTipListBox::OnMouseMove проходит по списку и выясняет, над какой именно строкой находится курсор. Если это так, функция использует этот индекс для передачи CTitleTipListBox::AdjustTitleTip.

CTitleTipListBox::OnSelchange обрабатывает нотификационное сообщение LBN_SELCHANGE. Если была выбрана другая строка в списке, то может понадобиться изменить подсказку. Например, если выбрана та же строка, которая отражается элементом TitleTip, то TitleTip нужно обновить для показа выбранной строки. Заметьте, что CTitleTipListBox::OnSelchange различает списки с одиночным и множественным выделением. Для списков с множественным выделением она вызывает CListBox::GetCaretIndex, а для списков с одиночным выделением – CListBox::GetCurSel. Обработка нотификационного сообщения LBN_SELCHANGE также позволяет корректно отображать подсказку, когда пользователь выбирает строки клавиатурой, а не мышью.

CTitleTipListBox::OnKillFocus и CTitleTipListBox::OnDestroy относительно просты. CTitleTipListBox::OnKillFocus прячет подсказку, если только окно, получающее фокус, не является окном подсказки. Это нужно для того, чтобы автоматически прятать подсказку, когда пользователь переключается со списка клавишей Tab. CTitleTipListBox::OnDestroy скрывает и уничтожает элемент TitleTip.

CTitleTipListBox::OnLButtonDown помечает элемент TitleTip для перерисовки при смене строки. Я временно отключаю захват мыши перед вызовом функции базового класса, потому что, как выяснилось, если этого не сделать, нарушается механизм выбора нескольких строк (когда вы перемещаете курсор мыши по строкам, удерживая левую кнопку). Поскольку я не посвящен в тайны внутреннего устройства стандартного элемента "список", я могу лишь догадываться о причинах проблемы. Возможно, список сам захватывает мышь при нажатии левой кнопки мыши для отслеживания перемещений курсора.