399 lines
10 KiB
C++
399 lines
10 KiB
C++
// ==========================================================================
|
|
// Class Implementation : COXScrollTip
|
|
// ==========================================================================
|
|
|
|
// Source file : OXScrollTip.cpp
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "OXScrollTip.h"
|
|
|
|
#include "UTBStrOp.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
IMPLEMENT_DYNAMIC(COXScrollTip, CWnd)
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Definition of static members
|
|
BOOL COXScrollTip::m_bWindowClassCreated = FALSE;
|
|
CString COXScrollTip::m_sWindowClass;
|
|
|
|
// Data members -------------------------------------------------------------
|
|
// protected:
|
|
// CPen m_framePen;
|
|
// --- Therd Januari pen that should be used to draw the window border (solid COLOR_WINDOWFRAME)
|
|
|
|
// CBrush m_backgroundBrush;
|
|
// --- The brush that should be used to fill the background (solid COLOR_INFOBK)
|
|
|
|
// COLORREF m_textColor;
|
|
// --- The color used to draw text (COLOR_INFOTEXT)
|
|
// CFont m_font;
|
|
// --- The fint used to draw text (same as of CToolTipCtrl)
|
|
|
|
// int m_cxHScroll;
|
|
// int m_cyVScroll;
|
|
|
|
// BOOL m_bVisible;
|
|
// --- Whether the window is currently visible
|
|
|
|
// CString m_sText;
|
|
// --- The current or new contents of the window
|
|
// BOOL m_bTextChanged;
|
|
// --- Whether the text has been changed in a call to Adjust, but not yet applied
|
|
|
|
// CRect m_rect;
|
|
// --- The current or new position and size
|
|
// BOOL m_bRectChanged;
|
|
// --- Whether the rect has been changed in a call to Adjust, but not yet applied
|
|
|
|
// BOOL m_bFastBackgroundRepaint;
|
|
// --- Whether WP_PAINTs should be send to the windows that reappear when the
|
|
// scroll tip is moved
|
|
// If TRUE WM_PAINT will be send, otherwise it will be (automatically) posted (by WIndows)
|
|
|
|
// static BOOL m_bWindowClassCreated;
|
|
// --- Whether an attempt has already been made to create a window class
|
|
|
|
// static CString m_sWindowClass;
|
|
// --- The The name of the window class
|
|
|
|
// private:
|
|
|
|
// Member functions ---------------------------------------------------------
|
|
// public:
|
|
|
|
BEGIN_MESSAGE_MAP(COXScrollTip, CWnd)
|
|
//{{AFX_MSG_MAP(COXScrollTip)
|
|
ON_WM_WININICHANGE()
|
|
ON_WM_PAINT()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
COXScrollTip::COXScrollTip()
|
|
:
|
|
m_textColor(0),
|
|
m_cxHScroll(0),
|
|
m_cyVScroll(0),
|
|
m_bVisible(FALSE),
|
|
m_sText(),
|
|
m_bTextChanged(FALSE),
|
|
m_rect(0, 0, 0, 0),
|
|
m_bRectChanged(FALSE),
|
|
m_bFastBackgroundRepaint(TRUE)
|
|
{
|
|
// Get the width of the scroll arrow of horizontal scrollbar and
|
|
// the height of the scroll arrow of vertical scrollbar and
|
|
m_cxHScroll = ::GetSystemMetrics(SM_CXHSCROLL);
|
|
m_cyVScroll = ::GetSystemMetrics(SM_CYVSCROLL);
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
int COXScrollTip::GetHorizontalArrowWidth() const
|
|
{
|
|
return m_cxHScroll;
|
|
}
|
|
|
|
int COXScrollTip::GetVerticalArrowHeight() const
|
|
{
|
|
return m_cyVScroll;
|
|
}
|
|
|
|
BOOL COXScrollTip::Create(CWnd* pParentWnd)
|
|
{
|
|
// Create a new window class if necessary
|
|
if (!m_bWindowClassCreated)
|
|
{
|
|
m_sWindowClass = AfxRegisterWndClass(CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW);
|
|
m_bWindowClassCreated = TRUE;
|
|
}
|
|
|
|
ASSERT(m_bWindowClassCreated);
|
|
if (m_sWindowClass.IsEmpty())
|
|
{
|
|
// Have tried to create a window class, but it failed
|
|
TRACE0("COXScrollTip::Create : Could not create window class\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// Create the window itself (no caption, empty rect and invisible)
|
|
// ... Must use CreateEx() because we want a pop-up window
|
|
// ... We will paint the border frame ourselves
|
|
if (!CWnd::CreateEx(0, m_sWindowClass, _T(""), WS_POPUP, 0, 0, 0, 0,
|
|
pParentWnd->GetSafeHwnd(), 0))
|
|
{
|
|
TRACE0("COXScrollTip::Create : Failed to create window\n");
|
|
return FALSE;
|
|
}
|
|
|
|
ASSERT(!m_bVisible);
|
|
|
|
// Get the needed colors now
|
|
AdjustColorsFontsMetrics();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void COXScrollTip::Show(BOOL bShow)
|
|
{
|
|
if (bShow)
|
|
ShowWindow(SW_SHOWNA);
|
|
else
|
|
{
|
|
m_rect.SetRectEmpty();
|
|
ShowWindow(SW_HIDE);
|
|
m_sText.Empty();
|
|
}
|
|
m_bVisible = bShow;
|
|
}
|
|
|
|
void COXScrollTip::Adjust(CRect rect, LPCTSTR pszText)
|
|
{
|
|
if (m_rect != rect)
|
|
{
|
|
m_rect = rect;
|
|
m_bRectChanged = TRUE;
|
|
}
|
|
|
|
if (m_sText != pszText)
|
|
{
|
|
m_sText = pszText;
|
|
m_bTextChanged = TRUE;
|
|
}
|
|
|
|
if (m_bRectChanged || m_bTextChanged)
|
|
Redraw();
|
|
|
|
ASSERT(!m_bRectChanged);
|
|
ASSERT(!m_bTextChanged);
|
|
}
|
|
|
|
void COXScrollTip::EnableFastBackgroundRepaint(BOOL bEnable /* = TRUE */)
|
|
{
|
|
m_bFastBackgroundRepaint = bEnable;
|
|
}
|
|
|
|
CSize COXScrollTip::ComputeSize(LPCTSTR pszText)
|
|
{
|
|
CSize size(0,0);
|
|
CDC* pDC = GetDC();
|
|
if (pDC != NULL)
|
|
size = pDC->GetTextExtent(pszText, (int)_tcslen(pszText));
|
|
else
|
|
TRACE0("COXScrollTip::ComputeSize : Failed to get DC\n");
|
|
ReleaseDC(pDC);
|
|
return size;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
void COXScrollTip::AssertValid() const
|
|
{
|
|
CWnd::AssertValid();
|
|
}
|
|
|
|
void COXScrollTip::Dump(CDumpContext& dc) const
|
|
{
|
|
CWnd::Dump(dc);
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
COXScrollTip::~COXScrollTip()
|
|
{
|
|
}
|
|
|
|
// protected:
|
|
// private:
|
|
|
|
// ==========================================================================
|
|
|
|
|
|
void COXScrollTip::OnWinIniChange(LPCTSTR lpszSection)
|
|
{
|
|
CWnd::OnWinIniChange(lpszSection);
|
|
|
|
// Colors and fonts may have changed, adjust them
|
|
AdjustColorsFontsMetrics();
|
|
}
|
|
|
|
void COXScrollTip::AdjustColorsFontsMetrics()
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Adjust the colors, fonts etc. to the new WIndows settings
|
|
{
|
|
// Get the tooltip frame, background and text color
|
|
if (m_framePen.m_hObject != NULL)
|
|
// ... Destroy previous pen
|
|
m_framePen.DeleteObject();
|
|
if (m_backgroundBrush.m_hObject != NULL)
|
|
// ... Destroy previous brush
|
|
m_backgroundBrush.DeleteObject();
|
|
VERIFY(m_framePen.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOWFRAME)));
|
|
VERIFY(m_backgroundBrush.CreateSolidBrush(::GetSysColor(COLOR_INFOBK)));
|
|
m_textColor = ::GetSysColor(COLOR_INFOTEXT);
|
|
|
|
// Get the tooltip font
|
|
if ((HFONT)m_font != NULL)
|
|
// ... Destroy previous font
|
|
m_font.DeleteObject();
|
|
|
|
// ... Although the tooltip font can be specified through control panel
|
|
// there seems to be no way to retrieve this information.
|
|
// So we will crete a temporary tooltip to get its font
|
|
CToolTipCtrl toolTip;
|
|
|
|
// ... Tooltip control can be created with NULL parent
|
|
// We only need it for the font, so this will arm nobody
|
|
if (toolTip.Create(NULL))
|
|
{
|
|
CFont* pFont = toolTip.GetFont();
|
|
if (pFont != NULL)
|
|
{
|
|
LOGFONT logFont;
|
|
::ZeroMemory(&logFont, sizeof(logFont));
|
|
pFont->GetLogFont(&logFont);
|
|
m_font.CreateFontIndirect(&logFont);
|
|
}
|
|
toolTip.DestroyWindow();
|
|
}
|
|
|
|
if ((HFONT)m_font == NULL)
|
|
{
|
|
TRACE0("COXScrollTip::AdjustColorsFontsMetrics : Could not establish correct font, using default");
|
|
LOGFONT logFont;
|
|
::ZeroMemory(&logFont, sizeof(logFont));
|
|
logFont.lfHeight = -11;
|
|
logFont.lfWeight = 400;
|
|
UTBStr::tcscpy(logFont.lfFaceName, 14, _T("MS Sans Serif"));
|
|
VERIFY(m_font.CreateFontIndirect(&logFont));
|
|
}
|
|
|
|
// Use the font in this control
|
|
SetFont(&m_font);
|
|
|
|
// The font may have changed, re-align the text within the control
|
|
CString sText;
|
|
GetWindowText(sText);
|
|
SetWindowText(sText);
|
|
|
|
// Get the width of the scroll arrow of horizontal scrollbar and
|
|
// the height of the scroll arrow of vertical scrollbar and
|
|
m_cxHScroll = ::GetSystemMetrics(SM_CXHSCROLL);
|
|
m_cyVScroll = ::GetSystemMetrics(SM_CYVSCROLL);
|
|
}
|
|
|
|
|
|
void COXScrollTip::OnPaint()
|
|
{
|
|
CPaintDC dc(this);
|
|
|
|
CRect rect = m_rect;
|
|
ScreenToClient(rect);
|
|
|
|
// Use the correct color and font
|
|
CPen* pOldPen = dc.SelectObject(&m_framePen);
|
|
CBrush* pOldBrush = dc.SelectObject(&m_backgroundBrush);
|
|
CFont* pOldFont = dc.SelectObject(&m_font);
|
|
|
|
dc.SetBkMode(TRANSPARENT);
|
|
dc.SetTextColor(m_textColor);
|
|
|
|
// Draw the rectangle (border and fill) and text
|
|
CString sText;
|
|
GetWindowText(sText);
|
|
dc.Rectangle(&rect);
|
|
VERIFY(0 < dc.DrawText(sText, &rect, DT_CENTER));
|
|
|
|
// Restore the dc context
|
|
dc.SelectObject(pOldPen);
|
|
dc.SelectObject(pOldBrush);
|
|
dc.SelectObject(pOldFont);
|
|
}
|
|
|
|
void COXScrollTip::Redraw()
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Redraws the window with the new rect and text contents
|
|
{
|
|
// First adjust the position
|
|
if (m_bRectChanged)
|
|
{
|
|
// First repaint the area we will not use anymore
|
|
CRect oldRect;
|
|
GetWindowRect(oldRect);
|
|
CRect divRect;
|
|
divRect.SubtractRect(oldRect, m_rect);
|
|
|
|
// Move scroll tip window
|
|
SetWindowPos(&CWnd::wndTop, m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
|
|
SWP_NOACTIVATE);
|
|
|
|
if (m_bFastBackgroundRepaint)
|
|
RedrawBackground(divRect);
|
|
}
|
|
|
|
// Then adjust the text
|
|
if (m_bTextChanged)
|
|
SetWindowText(m_sText);
|
|
|
|
// ... If the window is still invisible, show it now
|
|
if (!m_bVisible)
|
|
Show(TRUE);
|
|
ASSERT(m_bVisible);
|
|
|
|
// Redraw the window if position or text have changed
|
|
if (m_bRectChanged || m_bTextChanged)
|
|
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW);
|
|
|
|
m_bRectChanged = FALSE;
|
|
m_bTextChanged = FALSE;
|
|
}
|
|
|
|
|
|
void COXScrollTip::RedrawBackground(CRect rect)
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Updates the windows that are covered by the specified rect (screen coordinates)
|
|
{
|
|
// We give the windows that are under the top left and bottom right corner of
|
|
// the specified rect the opportunity the redraw themselves now.
|
|
// Other areas will be repainted through a (posted) WM_PAINT, which will
|
|
// be handled later.
|
|
if (!rect.IsRectEmpty())
|
|
{
|
|
CWnd* pBackTopLeftWnd = CWnd::WindowFromPoint(rect.TopLeft());
|
|
if (pBackTopLeftWnd != NULL)
|
|
{
|
|
pBackTopLeftWnd = pBackTopLeftWnd->GetTopLevelParent();
|
|
ASSERT(pBackTopLeftWnd != NULL);
|
|
pBackTopLeftWnd->RedrawWindow(&rect);
|
|
}
|
|
CWnd* pBackBottomRightWnd = CWnd::WindowFromPoint(rect.BottomRight());
|
|
if ((pBackBottomRightWnd != NULL) && (pBackTopLeftWnd != pBackBottomRightWnd))
|
|
{
|
|
pBackBottomRightWnd = pBackBottomRightWnd->GetTopLevelParent();
|
|
ASSERT(pBackBottomRightWnd != NULL);
|
|
pBackBottomRightWnd->RedrawWindow(&rect);
|
|
}
|
|
}
|
|
}
|