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

Шрифт
Интервал

CTitleTipListBox::OnLButtonUp захватывает курсор мыши, если окно подсказки показано на экране и CTitleTipListBox еще не захватил мышь. CTitleTipListBox::PreTranslateMessage следит за другими сообщениями от мыши и делает окно представления активным, если список находится в этом окне. Я реализовал это для имитации поведения MFC-окна представления, когда оно получает сообщение WM_MOUSEACTIVATE. Иначе окно может пропустить сообщение об активации мышью, когда пользователь щелкает на окне подсказки.

CODListBox представляет собой пример реализации подсказок TitleTips для элемента "список" с пользовательской отрисовкой (см. рис.13). Константа CODListBox::m_nEdgeSpace используется для добавления пространства по краям текста. Константа CODListBox::m_nFontHeight представляет желаемую высоту шрифта для отображения строк. В переменной CODListBox::m_Font хранится шрифт для отображения строк. CODListBox::CODListBox создает шрифт (m_Font) и использует его при отрисовке элемента "список".

Рис.13. CODListBox

>// ODListBox.h : header file

>//


>/////////////////////////////////////////////////////////////////////////////

>// CODListBox window

>#include "TitleTipListBox.h"


>class CODListBox : public CTitleTipListBox { // Construction public:

> CODListBox();

>// Overrides

> // ClassWizard generated virtual function overrides

> //{{AFX_VIRTUAL(CODListBox)

>public:

> virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);

> virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);

> //}}AFX_VIRTUAL

> // Implementation

>public:

> virtual ~CODListBox();

>protected:

> const int m_nEdgeSpace; // Дополнительное пространство вокруг текста

> const int m_nFontHeight; // Высота шрифта

> CFont m_Font; // Шрифт для отображения строк

> virtual int GetIdealItemRect(int nIndex, LPRECT lpRect);

> // Generated message map functions protected:

> //{{AFX_MSG(CODListBox)

> // NOTE – the ClassWizard will add and remove member functions here.

> //}}AFX_MSG

> DECLARE_MESSAGE_MAP()

>};


>///////////////////////////////////////////////////////////////////////////// // ODListBox.cpp : implementation file //

>#include "stdafx.h"

>#include "TTDemo.h"

>#include "ODListBox.h"


>#ifdef _DEBUG

>#define new DEBUG_NEW

>#undef THIS_FILE

>static char THIS_FILE[] = __FILE__;

>#endif


>/////////////////////////////////////////////////////////////////////////////

>// CODListBox

>CODListBox::CODListBox() : m_nEdgeSpace(4), m_nFontHeight(20) {

> VERIFY(m_Font.CreateFont(m_nFontHeight, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial"));

>}


>CODListBox::~CODListBox() { }


>int CODListBox::GetIdealItemRect(int nIndex, LPRECT lpRect) {

> ASSERT(nIndex >= 0);

> int nResult = GetItemRect(nIndex, lpRect);

> if (nResult != LB_ERR) {

>  CClientDC DC(this);

>  CFont* pOldFont = DC.SelectObject(&m_Font);

>  // Calculate the text length.

>  CString strItem;

>  GetText(nIndex, strItem);

>  CSize TextSize = DC.GetTextExtent(strItem);

>  // Взять максимум от обычной ширины и идеальной ширины.

>  lpRect->right = max(lpRect->right, lpRect->left + TextSize.cx + (m_nEdgeSpace * 2));

>  DC.SelectObject(pOldFont);

> }

> return nResult;

>}


>BEGIN_MESSAGE_MAP(CODListBox, CTitleTipListBox)

> //{{AFX_MSG_MAP(CODListBox)

> // NOTE – the ClassWizard will add and remove mapping macros here.

> //}}AFX_MSG_MAP

>END_MESSAGE_MAP()


>/////////////////////////////////////////////////////////////////////////////

>// CODListBox message handlers

>void CODListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {

> CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);

> ASSERT_VALID(pDC);

> int nSavedDC = pDC->SaveDC();

> CString strItem;

> if (lpDrawItemStruct->itemID != –1) {

>  GetText(lpDrawItemStruct->itemID, strItem);

> }

> COLORREF TextColor;

> COLORREF BackColor;

> UINT nItemState = lpDrawItemStruct->itemState;

> if (nItemState & ODS_SELECTED) {

>  TextColor = RGB(255, 255, 255); // Белый

>  BackColor = RGB(255, 0, 0); // Красный

> } else {

>  TextColor = RGB(255, 0, 0); // Красный

>  BackColor = RGB(255, 255, 255); // Белый

> }

> CRect ItemRect(lpDrawItemStruct->rcItem);

> // Нарисовать фон

> pDC->FillSolidRect(ItemRect, BackColor);

> // Нарисовать текст

> pDC->SetTextColor(TextColor);

> pDC->SetBkMode(TRANSPARENT);

> pDC->SelectObject(&m_Font);

> ItemRect.left += m_nEdgeSpace;

> pDC->DrawText(strItem, ItemRect, DT_LEFT | DT_SINGLELINE | DT_VCENTER);

> ItemRect.left –= m_nEdgeSpace;

> // Нарисовать по необходимости рамку фокуса

> if (nItemState & ODS_FOCUS) {

>  pDC->DrawFocusRect(ItemRect);

> }

> pDC->RestoreDC(nSavedDC);

>}


>void CODListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) {

> lpMeasureItemStruct->itemHeight = m_nFontHeight + (m_nEdgeSpace * 2);

>}

CODListBox::GetIdealItemRect перекрывает такой же метод в классе CTitleTipListBox. Как вы видите, его реализация похожа на реализацию метода в базовом классе, за исключением того, что новый метод использует для шрифта переменную m_Font. Конечно, я мог бы добиться результата и без переопределения метода базового класса, если бы воспользовался CWnd::SetFont для установки шрифта для списка. Однако я хотел показать, как нужно перекрывать этот метод в других случаях. Например, вам придется переопределить CTitleTipListBox::GetIdealItemRect, если вы захотите показывать в списке картинки.


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

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


Симуляция частичной специализации

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


Обработка событий в С++

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


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.