Рейтинговые книги
Читем онлайн Программирование на Visual C++. Архив рассылки - Алекс Jenter

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 62 63 64 65 66 67 68 69 70 ... 156

BOOL APIENTRY AddTool(HWND hTip, HWND hWnd, RECT* pr, UINT nIDTool, LPCTSTR szText) {

 TOOLINFO ti;

 RECT r = {0,0,0,0};

 FillInToolInfo(&ti, hWnd, nIDTool);

 ti.hinst  = (HINSTANCE)GetModuleHandle(NULL);

 ti.uFlags |= TTF_SUBCLASS | TTF_TRANSPARENT;

 ti.lpszText = LPSTR(szText ? szText : LPSTR_TEXTCALLBACK);

 if (!(ti.uFlags & TTF_IDISHWND)) {

  if (!pr) {

   pr = &r;

   GetClientRect(hWnd, pr);

  }

  memcpy(&ti.rect, pr, sizeof(RECT));

 }

 BOOL res = SendMessage(hTip, TTM_ADDTOOL, 0, (LPARAM)&ti);

 return res;

}

После того, как область зарегистрирована, можно управлять ее текстом посредством UpdateTipText(). Можно заметить, что в ней может быть использован тот же механизм обратного вызова текста подсказки, что и в AddTool(). Т.е. в том случае, если указатель lpszText будет установлен в NULL, то будет задействован механизм обратного вызова текста подсказки. А как же поступить в случае, если нужно просто прекратить вывод какой-либо одной подсказки, если установка lpszText в NULL задействует альтернативный способ? В этом случае нужно, чтобы lpszText указывал на пустую строку "".

//-------------------------------------------------------------

void APIENTRY UpdateTipText(HWND hTip, HWND hWnd, UINT nIDTool, LPCTSTR lpszText) {

 TOOLINFO ti;

 FillInToolInfo(&ti, hWnd, nIDTool);

 ti.lpszText = LPSTR(lpszText ? lpszText : LPSTR_TEXTCALLBACK);

 SendMessage(hTip, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);

}

Получить текст конкретной подсказки можно посредством GetTipText().

//-------------------------------------------------------------

void APIENTRY GetTipText(HWND hTip, HWND hWnd, UINT nIDTool, LPSTR szText) {

 TOOLINFO ti;

 if (!szText) return;

 *szText = 0;

 FillInToolInfo(&ti, hWnd, nIDTool);

 ti.lpszText = szText;

 SendMessage(hTip, TTM_GETTEXT, 0, (LPARAM)&ti);

}

Включить/выключить вывод всех подсказок, зарегистрированных данным tooltip-контролом, можно функцией EnableToolTip().

//-------------------------------------------------------------

void APIENTRY EnableToolTip(HWND hTip, BOOL activate) {

 SendMessage(hTip, TTM_ACTIVATE, activate, 0);

}

ПРИМЕЧАНИЕ

Необходимо отметить, что в данной реализации способа работы с областями подсказки имеется одно ограничение – если программист явным образом задает идентификаторы областей подсказки (флаг TTF_IDISHWND в этом случае не установлен), то механизм обратного вызова текста подсказки не работает, поскольку нотификационные сообщения обратного вызова приходят не диалогу, а окну-носителю области подсказки, которое не умеет их обрабатывать (в данной реализации).

MFC

В MFC для работы с всплывающими подсказками предназначен класс CToolTipCtrl. Рассмотрим, как им пользоваться.

Первым делом необходимо добавить объект класса CToolTipCtrl в класс диалогового окна, которое вы хотите снабдить всплывающими подсказками. Тем самым мы гарантируем, что этот объект будет существовать ровно столько, сколько сам диалог. Например:

class CMFCTipsDlg : public CDialog {

 …

protected:

 CToolTipCtrl m_tt;

 …

};

Хотя большую часть времени всплывающая подсказка не видна на экране, это обыкновенное окно, и прежде чем работать с ним, его необходимо создать и связать с уже имеющимся у нас объектом m_tt. Для этого используется функция CToolTipCtrl::Create, которая получает указатель на объект родительского окна и стиль подсказки, например:

BOOL CMFCTipsDlg::OnInitDialog() {

 …

 m_tt.Create(this);

 …

}

Следующая наша задача – сообщить всплывающей подсказке, над какими контролами она должна появляться и какой текст при этом выдавать. Для этого нужно зарегистрировать каждый контрол в подсказке. Это выполняется с помощью функции CToolTipCtrl::AddTool.

BOOL AddTool(CWnd* pWnd, LPCTSTR lpszText =  LPSTR_TEXTCALLBACK, LPCRECT lpRectTool = NULL, UINT nIDTool = 0);

Параметры pWnd и lpRectTool задают окно и прямоугольную область внутри этого окна, над которой будет появляться подсказка, а в nIDTool записывается уникальный идентификатор этой области. Если задать lpRectTool равным NULL, создаётся область, занимающая окно целиком. Именно это нам и требуется, поскольку мы хотим добавить подсказки для контролов в диалоге. В этом случае nIDTool должен быть равен нулю (значение по умолчанию). Параметр lpszText содержит указатель на текст подсказки. Если передать вместо текста значение LPSTR_TEXTCALLBACK, подсказка будет запрашивать его непосредственно перед отображением, посылая окну, содержащему контрол (или прямоугольную область), сообщение TTN_GETDISPINFO. О том, как обрабатывать это сообщение, мы поговорим немного позже.

Обычно подсказки для контролов также назначают в обработчике WM_INITDIALOG. Поступим так и мы. Например:

BOOL CMFCTipsDlg::OnInitDialog() {

 …

 static int ID[] = {

  IDC_PICTURE,

  IDC_TEXT,

  IDC_EDIT,

  IDC_COMBO,

  IDC_RADIO1,

  IDC_RADIO2,

  IDC_RADIO3,

  IDC_CHECK,

  IDC_LIST,

  IDC_TREE,

  IDOK,

  IDCANCEL

 };

 static constchar *szTipText[] = {

  "Picture",

  "Text",

  "Edit",

  "Combo box",

  "Radio button 1",

  "Radio button 2",

  LPSTR_TEXTCALLBACK,

  "Check box",

  "List view",

  "Tree view",

  "OK",

  "Cancel"

 };

 for (int i = 0; i < sizeof(ID) / sizeof(int); i++)

  m_tt.AddTool(GetDlgItem(ID[i]), szTipText[i]);

 …

}

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

BOOL CMFCTipsDlg::PreTranslateMessage(MSG* pMsg) {

 if (pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)

  m_tt.RelayEvent(pMsg);

 return CDialog::PreTranslateMessage(pMsg);

}

Вот и всё. Проделанных действий достаточно, чтобы подсказки начали появляться. Осталось рассмотреть, как обрабатывать сообщение TTN_GETSIDPINFO. Как уже говорилось, оно посылается, перед отображением подсказки, в случае если текст подсказки не был задан заранее. Сообщение TTN_GETDISPINFO обрабатывается по обычной схеме (при помощи макроса ON_NOTIFY или ON_NOTIFY_RANGE). Если вы решите использовать макрос ON_NOTIFY, вам понадобится значение идентификатора подсказки. В текущей версии MFC этот идентификатор равен NULL, но учтите, что это значение нигде не документировано. Используя ON_NOTIFY_RANGE, вы не попадёте в зависимость от недокументированных параметров. Например:

class CMFCTipsDlg : public CDialog {

 ...

 afx_msg void OnGetDispInfo(UINT id, NMTTDISPINFO *pNMHDR, LRESULT *pResult);

 ...

};

BEGIN_MESSAGE_MAP(CMFCTipsDlg, CDialog)

 ...

 ON_NOTIFY_RANGE(TTN_GETDISPINFO, 0, 0xFFFFFFFF, OnGetDispInfo)

 ...

END_MESSAGE_MAP()

void CMFCTipsDlg::OnGetDispInfo(UINT id, NMTTDISPINFO *pNMHDR, LRESULT *pResult) {

 pNMHDR->lpszText = "Radio button 3";

 *pResult = 0;

}

В этом фрагменте мы просто возвращаем предопределённую строку "Radio button 3", так как ранее мы не задали текст подсказки всего для одного контрола. Если же таких контролов несколько, вам придётся сначала проанализировать значения hwnd, uId и rect структуры NMTTDISPINFO, а затем вернуть соответствующую им строку.

Это все на сегодня. До следующей недели! 

Алекс Jenter   [email protected] Красноярск, 2001. Рассылка является частью проекта RSDN.

Программирование на Visual C++

Выпуск №43 от 6 мая 2001 г.

Здравствуйте, уважаемые подписчики!

Технические работы на сайте закончились и теперь форум и поиск снова работают нормально, причем форум очень сильно изменился соответственно вашим пожеланиям! Можете зайти и посмотреть сами на RSDN.RU.

СТАТЬЯ  Свойства в C++ Автор: Денис Майдыковский Версия текста: 1.1

Эта статья написана по материалам дискуссии в конференции RU.VISUAL.CPP сети FIDO. Основой примера шаблона свойства послужило письмо от "Vyacheslav V. Lanovets" от 6 декабря 2000г.

Развитие современных систем программирования в направлении объектно-ориентированного и компонентно-ориентированного, а также визуального программирования привело к тому, что многие распространённые и хорошо известные алгоритмические языки перестали соответствовать потребностям современного рынка средств разработки. Одним из таких "нововведений" стали свойства объекта. В общем случае, свойство это пара функций, одна из которых отвечает за установку некоторого значения, а другая за его считывание. Такое решение позволяет, во-первых, обеспечить инкапсуляцию данных и защиту их от неправомерного доступа, а во-вторых, обеспечить целостность данных. Необходимость использования свойств возникает тогда, когда при изменении некоторого параметра требуется произвести ещё некоторые действия.

1 ... 62 63 64 65 66 67 68 69 70 ... 156
На этой странице вы можете бесплатно читать книгу Программирование на Visual C++. Архив рассылки - Алекс Jenter бесплатно.
Похожие на Программирование на Visual C++. Архив рассылки - Алекс Jenter книги

Оставить комментарий