📄 pptooltip.cpp
字号:
if ((nIndexTool == m_nIndexCurrentWnd) && (pt == m_ptOriginal) && IsEnabledIndexTool(nIndexTool))
{
PrepareDisplayToolTip(&pt);
if (m_nTimeAutoPop && !(m_pToolInfo.nBehaviour & PPTOOLTIP_DISABLE_AUTOPOP)) //Don't hide window if autopop is 0
SetTimer(PPTOOLTIP_HIDE, m_nTimeAutoPop, NULL);
}
break;
case PPTOOLTIP_HIDE:
TRACE(_T("OnTimerHide\n"));
if (!IsCursorInToolTip() ||
!IsVisible() ||
!(m_pToolInfo.nBehaviour & PPTOOLTIP_NOCLOSE_OVER))
Pop();
break;
}
CWnd::OnTimer(nIDEvent);
}
BOOL CPPToolTip::IsEnabledIndexTool(int nIndex)
{
return (BOOL)(IsExistTool(nIndex) || (nIndex == PPTOOLTIP_TOOL_HELPER));
}
BOOL CPPToolTip::IsCursorInToolTip() const
{
ASSERT(m_pParentWnd);
// Is tooltip visible?
if (!IsVisible() || !IsWindow(m_hWnd))
return FALSE;
CPoint pt;
GetCursorPos(&pt);
CPPToolTip * pWnd = (CPPToolTip*)WindowFromPoint(pt);
return (pWnd == this);
}
void CPPToolTip::KillTimers(UINT nIDTimer /* = NULL */)
{
// TRACE (_T("CPPToolTip::KillTimers\n"));
if (nIDTimer == NULL)
{
KillTimer(PPTOOLTIP_SHOW);
KillTimer(PPTOOLTIP_HIDE);
}
else if (nIDTimer == PPTOOLTIP_SHOW)
KillTimer(PPTOOLTIP_SHOW);
else if (nIDTimer == PPTOOLTIP_HIDE)
KillTimer(PPTOOLTIP_HIDE);
}
void CPPToolTip::PrepareDisplayToolTip(CPoint * pt)
{
TRACE (_T("CPPToolTip::DisplayToolTip()\n"));
//Fills default members
if (!(m_pToolInfo.nMask & PPTOOLTIP_MASK_STYLES))
m_pToolInfo.nStyles = m_nStyles;
if (!(m_pToolInfo.nMask & PPTOOLTIP_MASK_EFFECT))
{
m_pToolInfo.nEffect = m_nEffect;
m_pToolInfo.nGranularity = m_nGranularity;
}
if (!(m_pToolInfo.nMask & PPTOOLTIP_MASK_COLORS))
{
m_pToolInfo.crBegin = m_crColor[PPTOOLTIP_COLOR_BK_BEGIN];
m_pToolInfo.crMid = m_crColor[PPTOOLTIP_COLOR_BK_MID];
m_pToolInfo.crEnd = m_crColor[PPTOOLTIP_COLOR_BK_END];
}
if (!(m_pToolInfo.nMask & PPTOOLTIP_MASK_DIRECTION))
m_pToolInfo.nDirection = m_nDirection;
if (!(m_pToolInfo.nMask & PPTOOLTIP_MASK_BEHAVIOUR))
m_pToolInfo.nBehaviour = m_nBehaviour;
//Send notify
SendNotify(pt, m_pToolInfo);
//If string and icon are not exist then exit
if ((m_pToolInfo.hIcon == NULL) && m_pToolInfo.sTooltip.IsEmpty())
return;
//calculate the width and height of the box dynamically
CSize sz = GetTooltipSize(m_pToolInfo.sTooltip);
m_szTextTooltip = sz; //Stores the real size of the tooltip's text
//Gets size of the current icon
m_szToolIcon = GetSizeIcon(m_pToolInfo.hIcon);
if (m_szToolIcon.cx || m_szToolIcon.cy)
{
sz.cx += m_szToolIcon.cx;
if (m_szTextTooltip.cx != 0)
sz.cx += m_nSizes[PPTTSZ_MARGIN_CX]; //If text is exist then adds separator
sz.cy = max(m_szToolIcon.cy, sz.cy);
}
//Gets size of the tooltip with margins
sz.cx += m_nSizes[PPTTSZ_MARGIN_CX] * 2;
sz.cy += m_nSizes[PPTTSZ_MARGIN_CY] * 2 + m_nSizes[PPTTSZ_HEIGHT_ANCHOR];
if (m_pToolInfo.nStyles & PPTOOLTIP_SHADOW)
{
sz.cx += m_nSizes[PPTTSZ_SHADOW_CX];
sz.cy += m_nSizes[PPTTSZ_SHADOW_CY];
}
CRect rect (0, 0, sz.cx, sz.cy);
#ifdef PPTOOLTIP_USE_SHADE
//If needed to create the bitmap of the background effect
switch (m_pToolInfo.nEffect)
{
case PPTOOLTIP_EFFECT_NOISE:
case PPTOOLTIP_EFFECT_DIAGSHADE:
case PPTOOLTIP_EFFECT_HSHADE:
case PPTOOLTIP_EFFECT_VSHADE:
case PPTOOLTIP_EFFECT_HBUMP:
case PPTOOLTIP_EFFECT_VBUMP:
case PPTOOLTIP_EFFECT_SOFTBUMP:
case PPTOOLTIP_EFFECT_HARDBUMP:
case PPTOOLTIP_EFFECT_METAL:
SetShade(rect, m_pToolInfo.nEffect, m_nGranularity, 5, m_pToolInfo.crBegin);
}
#endif
DisplayToolTip(pt, &rect);
}
void CPPToolTip::DisplayToolTip(CPoint * pt, CRect * rect)
{
//Calculate the placement on the screen
CalculateInfoBoxRect(pt, rect);
SetWindowPos(NULL,
rect->left, rect->top,
rect->Width() + 2, rect->Height() + 2,
SWP_SHOWWINDOW|SWP_NOCOPYBITS|SWP_NOACTIVATE|SWP_NOZORDER);
CRgn rgnCombo;
rgnCombo.CreateRectRgn(0, 0, 0, 0);
if (m_pToolInfo.nStyles & PPTOOLTIP_SHADOW)
{
rect->right -= m_nSizes[PPTTSZ_SHADOW_CX];
rect->bottom -= m_nSizes[PPTTSZ_SHADOW_CY];
}
m_rgnToolTip.DeleteObject();
GetWindowRegion(&m_rgnToolTip, CSize (rect->Width(), rect->Height()), *pt);
rgnCombo.CopyRgn(&m_rgnToolTip);
if (m_pToolInfo.nStyles & PPTOOLTIP_SHADOW)
{
m_rgnShadow.DeleteObject();
m_rgnShadow.CreateRectRgn(0, 0, 0, 0);
m_rgnShadow.CopyRgn(&m_rgnToolTip);
m_rgnShadow.OffsetRgn(m_nSizes[PPTTSZ_SHADOW_CX], m_nSizes[PPTTSZ_SHADOW_CY]);
rgnCombo.CombineRgn(&rgnCombo, &m_rgnShadow, RGN_OR);
}
SetWindowRgn((HRGN)rgnCombo.Detach(), FALSE);
}
CRect CPPToolTip::GetWindowRegion(CRgn * rgn, CSize sz, CPoint pt)
{
CRect rect;
rect.SetRect(0, 0, sz.cx, sz.cy);
CRgn rgnRect;
CRgn rgnAnchor;
CPoint ptAnchor [3];
ptAnchor [0] = pt;
ScreenToClient(&ptAnchor [0]);
switch (m_nLastDirection)
{
case PPTOOLTIP_LEFT_TOP:
case PPTOOLTIP_RIGHT_TOP:
rect.bottom -= m_nSizes[PPTTSZ_HEIGHT_ANCHOR];
ptAnchor [1].y = ptAnchor [2].y = rect.bottom;
break;
case PPTOOLTIP_LEFT_BOTTOM:
case PPTOOLTIP_RIGHT_BOTTOM:
rect.top += m_nSizes[PPTTSZ_HEIGHT_ANCHOR];
ptAnchor [1].y = ptAnchor [2].y = rect.top;
break;
}
//Gets the region for rectangle with the text
if (m_pToolInfo.nStyles & PPTOOLTIP_ROUNDED)
rgnRect.CreateRoundRectRgn(rect.left, rect.top, rect.right + 1, rect.bottom + 1,
m_nSizes[PPTTSZ_ROUNDED_CX], m_nSizes[PPTTSZ_ROUNDED_CY]);
else rgnRect.CreateRectRgn(rect.left, rect.top, rect.right + 1, rect.bottom + 1);
//Gets the region for anchor
if (m_pToolInfo.nStyles & PPTOOLTIP_ANCHOR)
{
switch (m_nLastDirection)
{
case PPTOOLTIP_LEFT_TOP:
case PPTOOLTIP_LEFT_BOTTOM:
ptAnchor [1].x = rect.right - m_nSizes[PPTTSZ_MARGIN_ANCHOR];
ptAnchor [2].x = ptAnchor [1].x - m_nSizes[PPTTSZ_WIDTH_ANCHOR];
break;
case PPTOOLTIP_RIGHT_TOP:
case PPTOOLTIP_RIGHT_BOTTOM:
ptAnchor [1].x = rect.left + m_nSizes[PPTTSZ_MARGIN_ANCHOR];
ptAnchor [2].x = ptAnchor [1].x + m_nSizes[PPTTSZ_WIDTH_ANCHOR];
break;
}
rgnAnchor.CreatePolygonRgn(ptAnchor, 3, ALTERNATE);
}
else
rgnAnchor.CreateRectRgn(0, 0, 0, 0);
rgn->CreateRectRgn(0, 0, 0, 0);
rgn->CombineRgn(&rgnRect, &rgnAnchor, RGN_OR);
rgnAnchor.DeleteObject();
rgnRect.DeleteObject();
return rect;
}
///////////////////////////////////////////////////
// Gets the size of the current tooltip text
//
// Parameters:
// none
//
// Return value:
// Size of current tooltip text
///////////////////////////////////////////////////
CSize CPPToolTip::GetTooltipSize(CString str)
{
//Gets max windows rectangle
CRect rect;
GetWindowRect(&rect);
//Creates compatibility context device in memory
// CDC * pDC = GetDC();
CWindowDC dc(NULL);
CDC memDC;
CBitmap bitmap;
memDC.CreateCompatibleDC(&dc);
// memDC.CreateCompatibleDC(pDC);
bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
// bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
//Prints the string on device context for gets minimal size of the rectangle
//of the tooltip
CSize sz = PrintTitleString(&memDC, rect, str);
memDC.SelectObject(pOldBitmap);
memDC.DeleteDC();
bitmap.DeleteObject();
// ReleaseDC(pDC);
//Returns minimal rectangle of the tooltip
return sz;
}
CSize CPPToolTip::GetSizeIcon(HICON hIcon) const
{
ICONINFO ii;
CSize sz (0, 0);
if (hIcon != NULL)
{
// Gets icon dimension
::ZeroMemory(&ii, sizeof(ICONINFO));
if (::GetIconInfo(hIcon, &ii))
{
sz.cx = (DWORD)(ii.xHotspot * 2);
sz.cy = (DWORD)(ii.yHotspot * 2);
//release icon mask bitmaps
if(ii.hbmMask)
::DeleteObject(ii.hbmMask);
if(ii.hbmColor)
::DeleteObject(ii.hbmColor);
}
}
return sz;
}
///////////////////////////////////////////////////
// Calculates the real rect for the tooltip with margins
//
// Parameters:
// pt [in] - the mouse coordinates (screen coordinates)
// sz [in] - the size of the tooltip text
//
// Return value:
// The rectangle when the tooltip will draw (screen coordinates)
///////////////////////////////////////////////////
void CPPToolTip::CalculateInfoBoxRect(CPoint * pt, CRect * rect)
{
// Use the screen's right edge as the right hand border, not the right edge of the client.
CWindowDC wdc(NULL);
CRect rWindow(0, 0, 0, 0);
rWindow.right = GetDeviceCaps(wdc, HORZRES);// - 8;
rWindow.bottom = GetDeviceCaps(wdc, VERTRES);// - 8;
/*
m_szToolIcon = GetSizeIcon(m_pToolInfo.hIcon);
if (m_szToolIcon.cx || m_szToolIcon.cy)
{
sz.cx += m_szToolIcon.cx + m_nSizes[PPTTSZ_MARGIN_CX];
sz.cy = max(m_szToolIcon.cy, sz.cy);
}
//Gets size of the tooltip with margins
sz.cx += m_nSizes[PPTTSZ_MARGIN_CX] * 2;
sz.cy += m_nSizes[PPTTSZ_MARGIN_CY] * 2 + m_nSizes[PPTTSZ_HEIGHT_ANCHOR];
if (m_pToolInfo.nStyles & PPTOOLTIP_SHADOW)
{
rWindow.right -= m_nSizes[PPTTSZ_SHADOW_CX];
rWindow.bottom -= m_nSizes[PPTTSZ_SHADOW_CY];
sz.cx += m_nSizes[PPTTSZ_SHADOW_CX];
sz.cy += m_nSizes[PPTTSZ_SHADOW_CY];
}
*/
// CRect rect;
// rect.SetRect(0, 0, sz.cx, sz.cy);
// CRect rectCopy = *rect;
//Offset the rect from the mouse pointer
CPoint ptEnd;
m_nLastDirection = m_pToolInfo.nDirection;
if (!TestHorizDirection(pt->x, rect->Width(), rWindow.right, m_nLastDirection, rect))
{
m_nLastDirection = GetNextHorizDirection(m_nLastDirection);
TestHorizDirection(pt->x, rect->Width(), rWindow.right, m_nLastDirection, rect);
}
if (!TestVertDirection(pt->y, rect->Height(), rWindow.bottom, m_nLastDirection, rect))
{
m_nLastDirection = GetNextVertDirection(m_nLastDirection);
TestVertDirection(pt->y, rect->Height(), rWindow.bottom, m_nLastDirection, rect);
}
//Returns the rect of the tooltip
if ((m_pToolInfo.nStyles & PPTOOLTIP_SHADOW) &&
((m_nLastDirection == PPTOOLTIP_LEFT_TOP) || (m_nLastDirection == PPTOOLTIP_LEFT_BOTTOM)))
rect->OffsetRect(m_nSizes[PPTTSZ_SHADOW_CX], m_nSizes[PPTTSZ_SHADOW_CY]);
}
///////////////////////////////////////////////////
// Gets the next horizontal direction
//
// Parameters:
// nDirection [in] - the current direction
//
// Return value:
// The next horizontal direction
///////////////////////////////////////////////////
int CPPToolTip::GetNextHorizDirection(int nDirection) const
{
switch (nDirection)
{
case PPTOOLTIP_LEFT_TOP:
nDirection = PPTOOLTIP_RIGHT_TOP;
break;
case PPTOOLTIP_RIGHT_TOP:
nDirection = PPTOOLTIP_LEFT_TOP;
break;
case PPTOOLTIP_LEFT_BOTTOM:
nDirection = PPTOOLTIP_RIGHT_BOTTOM;
break;
case PPTOOLTIP_RIGHT_BOTTOM:
nDirection = PPTOOLTIP_LEFT_BOTTOM;
break;
}
return nDirection;
}
///////////////////////////////////////////////////
// Gets the next vertical direction
//
// Parameters:
// nDirection [in] - the current direction
//
// Return value:
// The next vertical direction
///////////////////////////////////////////////////
int CPPToolTip::GetNextVertDirection(int nDirection) const
{
switch (nDirection)
{
case PPTOOLTIP_LEFT_TOP:
nDirection = PPTOOLTIP_LEFT_BOTTOM;
break;
case PPTOOLTIP_LEFT_BOTTOM:
nDirection = PPTOOLTIP_LEFT_TOP;
break;
case PPTOOLTIP_RIGHT_TOP:
nDirection = PPTOOLTIP_RIGHT_BOTTOM;
break;
case PPTOOLTIP_RIGHT_BOTTOM:
nDirection = PPTOOLTIP_RIGHT_TOP;
break;
}
return nDirection;
}
BOOL CPPToolTip::TestHorizDirection(int x, int cx, int w_cx, int nDirection, LPRECT rect) const
{
int left,right;
switch (nDirection)
{
case PPTOOLTIP_LEFT_TOP:
case PPTOOLTIP_LEFT_BOTTOM:
right = ((x + (int)m_nSizes[PPTTSZ_MARGIN_ANCHOR]) > w_cx) ? w_cx : (x + m_nSizes[PPTTSZ_MARGIN_ANCHOR]);
left = right - cx;
break;
case PPTOOLTIP_RIGHT_TOP:
case PPTOOLTIP_RIGHT_BOTTOM:
left = (x < (int)m_nSizes[PPTTSZ_MARGIN_ANCHOR]) ? 0 : (x - m_nSizes[PPTTSZ_MARGIN_ANCHOR]);
right = left + cx;
break;
}
BOOL bTestOk = ((left >= 0) && (right <= w_cx)) ? TRUE : FALSE;
if (bTestOk)
{
rect->left = left;
rect->right = right;
}
return bTestOk;
}
BOOL CPPToolTip::TestVertDirection(int y, int cy, int w_cy, int nDirection, LPRECT rect) const
{
int top, bottom;
switch (nDirection)
{
case PPTOOLTIP_LEFT_TOP:
case PPTOOLTIP_RIGHT_TOP:
bottom = y;
top = bottom - cy;
break;
case PPTOOLTIP_LEFT_BOTTOM:
case PPTOOLTIP_RIGHT_BOTTOM:
top = y;
bottom = top + cy;
break;
}
BOOL bTestOk = ((top >= 0) && (bottom <= w_cy)) ? TRUE : FALSE;
if (bTestOk)
{
rect->top = top;
rect->bottom = bottom;
}
return bTestOk;
}
/////////////////////////////////////////////////////////////////
// Gets the system tooltip's logfont
/////////////////////////////////////////////////////////////////
LPLOGFONT CPPToolTip::GetSystemToolTipFont() const
{
static LOGFONT LogFont;
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
return FALSE;
memcpy(&LogFont, &(ncm.lfStatusFont), sizeof(LOGFONT));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -