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

ЖАНРЫ

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

Джек Роджер

Шрифт:

CDTDemoDoc унаследован от CDocument. В этом классе хранится массив объектов CCircle, а также определены функции CDTDemoDoc::GetCircleCount и CDTDemoDoc::GetCircle для доступа к информации об этом массиве. CDTDemoDoc::GetCircle принимает целочисленный индекс, указывающий на смещение в массиве. Объекты CCircle хранятся в переменной CDTDemoDoc::m_CircleArray размером CIRCLECOUNT. Я мог бы объявить этот массив как открытый (public), но не сделал этого по двум причинам. Во-первых, реализацию легче менять, если ее детали скрыты от внешнего мира. Допустим, я захочу в будущем использовать для реализации массива переменного размера шаблон CArray. Во-вторых, я хочу возвращать константные ссылки пользователям CDTDemoDoc::GetCircle, чтобы они не смогли

случайно изменить объекты кругов в массиве. CDTDemoDoc::CDTDemoDoc вызывает CCircle::Initialize для каждого круга в массиве. CCircle::Initialize облегчает создание массивов фиксированного размера, потому что мне не нужно передавать параметры конструктору CCircle. В противном случае мне пришлось бы создавать массив динамически. Я использовал функцию rand для установки координат кругов. Генератор случайных чисел инициализируется текущим значением времени, поэтому довольно высока вероятность того, что позиция каждого круга будет разной каждый раз, когда вы запускаете приложение.

Класс CDTDemoView ответственен за отображение кругов и реализацию элементов DataTip (см. рис.8). В переменной CDTDemoView::m_ToolTip хранится элемент ToolTip, который выступает в качестве DataTip. Я хотел, чтобы этот пример показал вам, как использовать класс CToolTipCtrl напрямую, вместо использования функций класса CWnd. Однако, в данном случае, даже если я захотел использовать CWnd, я бы не смог, потому что мне нужен прямой доступ к элементу ToolTip, чтобы посылать ему сообщения. CWnd не предоставляет документированных способов доступа к создаваемому им элементу ToolTip, а я не хотел бы полагаться на детали конкретной реализации. CDTDemoView::m_pCircleHit хранит круг под курсором мыши. Если ни один из кругов не попадает под курсор мыши, CDTDemoView::m_pCircleHit может быть NULL.

Рис.8. DTDemoView

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

// DTDemoView.cpp : implementation of the CDTDemoView class

.

.

.

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

// CDTDemoView HitTest

const CCircle* CDTDemoView::HitTest(const CPoint& Point) {

 CDTDemoDoc* pDoc = GetDocument;

 ASSERT_VALID(pDoc);

 // Проверяем в обратном порядке, чтобы корректно обработать

 // перекрывающиеся круги

 const CCircle *pCircleHit = NULL;

 for (int n = pDoc->GetCircleCount – 1; n >= 0 && pCircleHit == NULL; n--) {

if (pDoc->GetCircle(n).HitTest(Point)) {

pCircleHit = &(pDoc->GetCircle(n));

}

 }

 return pCircleHit;

}

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

// CDTDemoView drawing

void CDTDemoView::OnDraw(CDC* pDC) {

 CDTDemoDoc* pDoc = GetDocument;

 ASSERT_VALID(pDoc);

 for (int n = 0; n < pDoc->GetCircleCount; n++) {

pDoc->GetCircle(n).Draw(pDC);

 }

}

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

// CDTDemoView diagnostics

#ifdef _DEBUG

void CDTDemoView::AssertValid const {

 CView::AssertValid; } void CDTDemoView::Dump(CDumpContext& dc) const {

 CView::Dump(dc);

}

CDTDemoDoc* CDTDemoView::GetDocument // non-debug version is inline

{

 ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDTDemoDoc)));

 return (CDTDemoDoc*)m_pDocument;

}

#endif //_DEBUG

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

// CDTDemoView message handlers

void CDTDemoView::OnInitialUpdate {

 CView::OnInitialUpdate;

 CRect ClientRect(0, 0, 1000, 1000);

 if (m_ToolTip.Create(this, TTS_ALWAYSTIP) && m_ToolTip.AddTool(this)) {

m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, SHRT_MAX);

m_ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_AUTOPOP, SHRT_MAX);

m_ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_INITIAL, 200);

m_ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_RESHOW, 200);

 } else {

 TRACE("Error in creating ToolTip");

 }

}

BOOL CDTDemoView::OnToolTipNeedText(UINT id, NMHDR * pNMHDR, LRESULT * pResult) {

 BOOL bHandledNotify = FALSE;

 CPoint CursorPos;

 VERIFY(::GetCursorPos(&CursorPos));

 ScreenToClient(&CursorPos);

 CRect ClientRect;

 GetClientRect(ClientRect);

 //
Удостовериться, что курсор попадает в клиентскую область окна,

 // потому что библиотека тоже хочет получать эти сообщения для

 // показа подсказок на панели инструментов.

 if (ClientRect.PtInRect(CursorPos)) {

TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;

m_pCircleHit = HitTest(CursorPos);

if (m_pCircleHit) {

// Adjust the text by filling in TOOLTIPTEXT

CString strTip;

const CPoint& Center = m_pCircleHit->GetCenter;

COLORREF Color = m_pCircleHit->GetColor;

strTip.Format("Center: (%d, %d)\nRadius: %d\nColor: (%d, %d, %d)", Center.x, Center.y, m_pCircleHit->GetRadius, (int)GetRValue(Color), (int)GetGValue(Color), (int)GetBValue(Color));

ASSERT(strTip.GetLength < sizeof(pTTT->szText));

::strcpy(pTTT->szText, strTip);

// Set the text color to same color as circle

m_ToolTip.SendMessage(TTM_SETTIPTEXTCOLOR, Color, L);

Поделиться с друзьями: