Чтение онлайн

на главную - закладки

Жанры

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

Джек Роджер

Шрифт:

Функция CDTDemoView::OnToolTipNeedText перехватывает нотификационные сообщения TTN_NEEDTEXT от элемента, на который указывает переменная m_ToolTip. Главное предназначение этой функции – определить, над каким кругом находится курсор и определить текст подсказки. Сначала она получает координаты курсора мыши и конвертирует их в клиентскую систему координат. Затем идет проверка на принадлежность координат клиентской части представления. Если этого не сделать, пропадут подсказки на панели инструментов, так как нотификационное сообщение TTN_NEEDTEXT используется также панелью инструментов. CDTDemoView::OnToolTipNeedText автоматически будет получать все сообщения TTN_NEEDTEXT при активном окне представления. Переменная bHandledNotify показывает, должно ли сообщение передаваться дальше главному окну. Если курсор находится в клиентской части окна, я проверяю его координаты на принадлежность какому-нибудь кругу и сохраняю

результаты проверки в переменной m_pCircleHit. Эта переменная также используется в функции CDTDemoView::OnMouseMove. Если курсор попадает в один из кругов, я создаю строку подсказки, в которую заношу координаты центра, радиус и цвет круга. Эта строка копируется в поле szText переданной структуры TOOLTIPTEXT. И, наконец, я устанавливаю цвет текста подсказки с помощью сообщения TTM_SETTIPTEXTCOLOR. [5] Параметр wParam этого сообщения содержит новое значение цвета текста, и устанавливается равным цвету круга (еще одна новая возможность IE 4.0 Common Controls DLL). Если курсор не попадает ни в один круг, поле szText указывает на пустую строку.

5

что эквивалентно CToolTipCtrl::SetTipTextColor – прим.пер.

Функция CDTDemoView::PreTranslateMessage ретранслирует некоторые сообщения мыши элементу DataTip с помощью функции CToolTipCtrl::RelayEvent. CDTDemoView::PreTranslateMessage вызывается для каждого сообщения, посылаемого окну. Проще всего вызывать CToolTipCtrl::RelayEvent здесь, потому что в этом случае мне не нужно переопределять перехватчики каждого сообщения мыши для передачи этих сообщений элементу DataTip. Подобным же образом работает и поддержка подсказок классом CWnd.

Функция CDTDemoView::OnMouseMove прячет и показывает подсказку в зависимости от принадлежности координат курсора какому-нибудь кругу, что определяется функцией HitTest. Если курсор мыши не находится над кругом либо если он находится не над тем кругом, над которым он находился во время последнего показа подсказки, то CDTDemoView::OnMouseMove прячет подсказку вызовом m_ToolTip.Activate(FALSE). Значение FALSE показывает, что элемент DataTip должен быть спрятан. Далее, если курсор находится над другим кругом, подсказка снова выводится на экран вызовом m_ToolTip.Activate(TRUE), а в переменную CDTDemoView::m_pCircleHit заносится указатель на новый круг. Таким образом, при перемещении курсора с одного круга на другой, я выключаю подсказку и сразу включаю ее. Это делается для того, чтобы элемент DataTip запросил новый текст подсказки через сообщение TTN_NEEDTEXT, что позволяет инициализировать подсказку новой информацией о круге. В IE 4.0 для скрытия подсказки предназначено сообщение TTM_POP, но это сообщение отсутствовало в той версии файла commctrl.h, которая у меня была.

Подсказки домашнего изготовления: TitleTips

Демонстрационный проект TTDemo

Демонстрационный проект TTDemoDelay

TitleTip – это вид подсказок, которые позволяют полностью увидеть не полностью показанные строки в списковых элементах управления. Например, такие подсказки присутствуют в окне Project Workspace среды разработки Visual C++. Если имя класса не помещается в окно Project Workspace, появляется подсказка, которая показывает нужный текст целиком. Это избавляет пользователя от необходимости горизонтальной прокрутки и увеличении ширины окна. Я написал демо-проект, реализующий TitleTips для элемента управления "список". Однако вы можете использовать сходные приемы для добавления этого вида подсказок и к другим элементам управления. Код, который я написал, может работать как с обычными элементами "список", так и со списками с пользовательской отрисовкой (owner-draw listboxes). Я заполнил оба списка названиями моих любимых книг по программированию (см. рис.9).

Рис.9. Демонстрация элементов TitleTip

Вы, наверное, поинтересуетесь, почему я не использовал возможность пользовательской отрисовки подсказок (появившейся в IE 4.0 Common Controls DLL) для реализации TitleTips. Дело в том, что ширина окна подсказки рассчитывается исходя из ширины показанной части строки в списке. Другими словами, у вас нет прямого контроля над шириной элемента ToolTip. Это мешает реализации подсказок для элементов "список" с пользовательской отрисовкой, потому что вам может понадобиться вывести на экран не только текст. Кроме того, я думаю, нужно уметь создавать подсказки с нуля, потому что всегда может оказаться, что стандартная

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

На рис.10 показана диаграмма классов, которая показывает отношения между классами нашего примера. Класс CListBox – это стандартный класс MFC, который инкапсулирует функциональность стандартного элемента управления "список". Класс CTitleTipListBox унаследован от класса CListBox и ответственен за создание и управление подсказками для списка. CTitleTipListBox может использоваться напрямую, если вы реализуете обычный элемент "список". Класс CTitleTip унаследован от CWnd и представляет элемент ToolTip. Класс CODListBox – это элемент "список" с пользовательской отрисовкой, он унаследован от CTitleTipListBox. Для создания элемента "список" с пользовательской отрисовкой нужно унаследовать класс от CTitleTipListBox и переопределить функцию CTitleTipListBox::GetIdealItemRect. Мы обсудим детали реализации CTitleTipListBox::GetIdealItemRect позже.

Рис.10. Диаграмма классов для примера использования элементов ToolTip

Класс CTitleTip представляет окно подсказки (см. рис.11). В статической переменной CTitleTip::m_pszWndClass хранится зарегистрированное имя класса окна. Имя хранится в статической переменной, потому что класс окна нужно зарегистрировать только один раз для всех экземпляров CTitleTip. CTitleTip::m_nItemIndex – это индекс строки в списке, для которой в данный момент выводится подсказка. Эта переменная может принимать значение константы CTitleTip::m_nNoIndex, если подсказка не выводится ни для одной из строк. CTitleTip::m_pListBox хранит указатель на родительское окно элемента TitleTip. Родительское окно должно быть элементом "список", чтобы я смог взять оттуда информацию для подсказки.

Рис.11. CTitleTip

/////////////////////////////////////////////////////////////////////////////

// CTitleTip window

class CTitleTip : public CWnd {

public:

 CTitleTip;

 virtual BOOL Create(CListBox* pParentWnd);

 virtual void Show(CRect DisplayRect, int nItemIndex);

 virtual void Hide;

// Overrides

 // ClassWizard generated virtual function overrides

 //{{AFX_VIRTUAL(CTitleTip)

 //}}AFX_VIRTUAL

 // Implementation

public:

 virtual ~CTitleTip;

protected:

 const int m_nNoIndex; // Пустой индекс

 static LPCSTR m_pszWndClass; // Имя зарегистрированного класса

 int m_nItemIndex; // Индекс строки, для которой показывается подсказка

 CListBox* m_pListBox; // Родительское окно

 BOOL IsListBoxOwnerDraw;

 // Generated message map functions

protected:

 //{{AFX_MSG(CTitleTip)

 afx_msg void OnPaint;

 //}}AFX_MSG

 DECLARE_MESSAGE_MAP

};

/////////////////////////////////////////////////////////////////////////////

// TitleTip.cpp : implementation file //

#include "stdafx.h"

#include "TitleTip.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CTitleTip

LPCSTR CTitleTip::m_pszWndClass = NULL;

CTitleTip::CTitleTip : m_nNoIndex(-1) {

Поделиться:
Популярные книги

Адвокат Империи 3

Карелин Сергей Витальевич
3. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 3

Кротовский, может, хватит?

Парсиев Дмитрий
3. РОС: Изнанка Империи
Фантастика:
попаданцы
альтернативная история
аниме
7.50
рейтинг книги
Кротовский, может, хватит?

Дурная жена неверного дракона

Ганова Алиса
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Дурная жена неверного дракона

Вонгозеро

Вагнер Яна
1. Вонгозеро
Детективы:
триллеры
9.19
рейтинг книги
Вонгозеро

Ведьма Вильхельма

Шёпот Светлана
Любовные романы:
любовно-фантастические романы
8.67
рейтинг книги
Ведьма Вильхельма

Папина дочка

Рам Янка
4. Самбисты
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Папина дочка

Законы Рода. Том 6

Flow Ascold
6. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 6

Как я строил магическую империю 7

Зубов Константин
7. Как я строил магическую империю
Фантастика:
попаданцы
постапокалипсис
аниме
фантастика: прочее
5.00
рейтинг книги
Как я строил магическую империю 7

Лучший из худший 3

Дашко Дмитрий
3. Лучший из худших
Фантастика:
городское фэнтези
попаданцы
аниме
6.00
рейтинг книги
Лучший из худший 3

Штурмовик из будущего 3

Политов Дмитрий Валерьевич
3. Небо в огне
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Штурмовик из будущего 3

Последний попаданец 2

Зубов Константин
2. Последний попаданец
Фантастика:
юмористическая фантастика
попаданцы
рпг
7.50
рейтинг книги
Последний попаданец 2

Идеальный мир для Лекаря 14

Сапфир Олег
14. Лекарь
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 14

Безумный Макс. Поручик Империи

Ланцов Михаил Алексеевич
1. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
7.64
рейтинг книги
Безумный Макс. Поручик Империи

Вдова на выданье

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Вдова на выданье