Исчерпывающее руководство по написанию всплывающих подсказок
Шрифт:
Рис.10. Диаграмма классов для примера использования элементов ToolTip
Класс CTitleTip представляет окно подсказки (см. рис.11). В статической переменной CTitleTip::m_pszWndClass хранится зарегистрированное имя класса окна. Имя хранится в статической переменной, потому что класс окна нужно зарегистрировать только один раз для всех экземпляров CTitleTip. CTitleTip::m_nItemIndex – это индекс строки в списке, для которой в данный момент выводится подсказка. Эта переменная может принимать значение константы CTitleTip::m_nNoIndex, если
Рис.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) {
// Зарегистрировать класс окна, если он еще не зарегистрирован
// другим экземпляром CTitleTip.
if (m_pszWndClass == NULL) {
m_pszWndClass = AfxRegisterWndClass(CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW);
}
m_nItemIndex = m_nNoIndex;
m_pListBox = NULL;
}
CTitleTip::~CTitleTip { }
BOOL CTitleTip::Create(CListBox* pParentWnd) {
ASSERT_VALID(pParentWnd);
m_pListBox = pParentWnd;
//
Не рисовать рамку для обычных элементов "список", так как
// строки с пользовательской отрисовкой добавляют рамку автоматически.
DWORD dwStyle = WS_POPUP;
if (!IsListBoxOwnerDraw) {
dwStyle |= WS_BORDER;
}
return CreateEx(0, m_pszWndClass, NULL, dwStyle, 0, 0, 0, 0, pParentWnd->GetSafeHwnd, NULL, NULL);
}
BOOL CTitleTip::IsListBoxOwnerDraw {
ASSERT_VALID(m_pListBox);
DWORD dwStyle = m_pListBox->GetStyle;
return (dwStyle & LBS_OWNERDRAWFIXED) || (dwStyle & LBS_OWNERDRAWVARIABLE);
}
void CTitleTip::Show(CRect DisplayRect, int nItemIndex) {
ASSERT_VALID(m_pListBox);
ASSERT(nItemIndex < m_pListBox->GetCount);
ASSERT(nItemIndex >= 0);
ASSERT(::IsWindow(m_hWnd));
ASSERT(!DisplayRect.IsRectEmpty);
// Пометить для обновления, если новая строка.
if (m_nItemIndex != nItemIndex) {
m_nItemIndex = nItemIndex;
InvalidateRect(NULL);
}
// Установить позицию и видимость окна.
CRect WindowRect;
GetWindowRect(WindowRect);
int nSWPFlags = SWP_SHOWWINDOW | SWP_NOACTIVATE;
if (WindowRect == DisplayRect) {
nSWPFlags |= SWP_NOMOVE | SWP_NOSIZE;
}
VERIFY(SetWindowPos(&wndTopMost, DisplayRect.left, DisplayRect.top, DisplayRect.Width, DisplayRect.Height, nSWPFlags));
}
void CTitleTip::Hide {
ASSERT(::IsWindow(m_hWnd));
ShowWindow(SW_HIDE);
}
BEGIN_MESSAGE_MAP(CTitleTip, CWnd)
//{{AFX_MSG_MAP(CTitleTip)
ON_WM_PAINT
//}}AFX_MSG_MAP
END_MESSAGE_MAP
/////////////////////////////////////////////////////////////////////////////
// CTitleTip message handlers
void CTitleTip::OnPaint {
ASSERT(m_nItemIndex != m_nNoIndex);
Поделиться с друзьями: