📄 pptooltip.cpp
字号:
/********************************************************************
created: 2003/04/12
created: 12:04:2003 10:50
file base: PPTooltip
file ext: cpp
author: Eugene Pustovoyt
purpose:
*********************************************************************/
#include "stdafx.h"
#include "PPToolTip.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip
CPPToolTip::CPPToolTip()
{
m_pParentWnd = NULL;
m_rgnShadow.CreateRectRgn(0, 0, 0, 0);
m_rgnToolTip.CreateRectRgn(0, 0, 0, 0);
// m_rgnCombo.CreateRectRgn(0, 0, 0, 0);
m_ptOriginal.x = -1;
m_ptOriginal.y = -1;
m_nIndexCurrentWnd = PPTOOLTIP_TOOL_NOEXIST;
m_nIndexDisplayWnd = PPTOOLTIP_TOOL_NOEXIST;
SetDelayTime(TTDT_INITIAL, 500);
SetDelayTime(TTDT_AUTOPOP, 5000);
SetNotify(FALSE);
SetDirection();
SetBehaviour();
SetDefaultStyles();
SetDefaultColors();
SetDefaultSizes();
SetEffectBk(PPTOOLTIP_EFFECT_SOLID);
RemoveAllTools();
// Register the window class if it has not already been registered.
WNDCLASS wndcls;
HINSTANCE hInst = AfxGetInstanceHandle();
if(!(::GetClassInfo(hInst, PPTOOLTIP_CLASSNAME, &wndcls)))
{
// otherwise we need to register a new class
wndcls.style = CS_SAVEBITS;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = NULL;
wndcls.hCursor = LoadCursor(hInst, IDC_ARROW );
wndcls.hbrBackground = NULL;
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = PPTOOLTIP_CLASSNAME;
if (!AfxRegisterClass(&wndcls))
AfxThrowResourceException();
}
}
CPPToolTip::~CPPToolTip()
{
RemoveAllTools();
RemoveAllNamesOfResource();
m_nLengthLines.RemoveAll();
m_nHeightLines.RemoveAll();
// m_rgnCombo.Detach();
// m_rgnCombo.DeleteObject();
m_rgnToolTip.DeleteObject();
m_rgnShadow.DeleteObject();
if (IsWindow(m_hWnd))
DestroyWindow();
}
BEGIN_MESSAGE_MAP(CPPToolTip, CWnd)
//{{AFX_MSG_MAP(CPPToolTip)
ON_WM_PAINT()
ON_WM_TIMER()
ON_WM_DESTROY()
ON_WM_KILLFOCUS()
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip message handlers
BOOL CPPToolTip::Create(CWnd* pParentWnd, BOOL bBalloonSize /* = TRUE */)
{
TRACE(_T("CPPToolTip::Create\n"));
ASSERT_VALID(pParentWnd);
DWORD dwStyle = WS_POPUP;
DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
m_pParentWnd = pParentWnd;
if (!CreateEx(dwExStyle, PPTOOLTIP_CLASSNAME, NULL, dwStyle, 0, 0, 0, 0, pParentWnd->GetSafeHwnd(), NULL, NULL))
{
return FALSE;
}
SetDefaultFont();
SetDefaultSizes(bBalloonSize);
return TRUE;
}
void CPPToolTip::OnDestroy()
{
KillTimers();
CWnd::OnDestroy();
}
void CPPToolTip::OnKillFocus(CWnd* pNewWnd)
{
CWnd::OnKillFocus(pNewWnd);
Pop();
}
BOOL CPPToolTip::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
void CPPToolTip::Pop()
{
if (m_nIndexDisplayWnd == PPTOOLTIP_TOOL_HELPER)
m_nIndexDisplayWnd = PPTOOLTIP_TOOL_NOEXIST;
KillTimers();
ShowWindow(SW_HIDE);
}
BOOL CPPToolTip::PreTranslateMessage(MSG* pMsg)
{
RelayEvent(pMsg);
return CWnd::PreTranslateMessage(pMsg);
}
LRESULT CPPToolTip::SendNotify(CPoint * pt, PPTOOLTIP_INFO & ti)
{
TRACE(_T("CPPToolTip::SendNotify()\n"));
// Make sure this is a valid window
if (!IsWindow(GetSafeHwnd()))
return 0L;
// See if the user wants to be notified
if (!GetNotify())
return 0L;
NM_PPTOOLTIP_DISPLAY lpnm;
PPTOOLTIP_INFO tiCopy = ti;
FromHandle(ti.hWnd)->ClientToScreen(&tiCopy.rectBounds);
m_pParentWnd->ScreenToClient(&tiCopy.rectBounds);
lpnm.pt = pt;
lpnm.ti = &tiCopy;
lpnm.hdr.hwndFrom = m_hWnd;
lpnm.hdr.idFrom = GetDlgCtrlID();
lpnm.hdr.code = UDM_TOOLTIP_DISPLAY;
::SendMessage(m_hNotifyWnd, WM_NOTIFY, lpnm.hdr.idFrom, (LPARAM)&lpnm);
CRect rcBound = ti.rectBounds;
ti = tiCopy;
ti.rectBounds = rcBound;
return 0L;
}
void CPPToolTip::OnPaint()
{
if (!IsEnabledIndexTool(m_nIndexCurrentWnd))
return;
m_nIndexDisplayWnd = m_nIndexCurrentWnd;
m_nIndexCurrentWnd = PPTOOLTIP_TOOL_NOEXIST;
CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect(&rect);
rect.DeflateRect(0, 0, 1, 1);
// Create a memory device-context. This is done to help reduce
// screen flicker, since we will paint the entire control to the
// off screen device context first.CDC memDC;
CDC memDC;
CBitmap bitmap;
memDC.CreateCompatibleDC(&dc);
bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
memDC.BitBlt(0, 0, rect.Width(), rect.Height(), &dc, 0,0, SRCCOPY);
OnDraw(&memDC, rect);
//Copy the memory device context back into the original DC via BitBlt().
dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0,0, SRCCOPY);
//Cleanup resources.
memDC.SelectObject(pOldBitmap);
memDC.DeleteDC();
bitmap.DeleteObject();
}
void CPPToolTip::OnDraw(CDC * pDC, CRect rect)
{
CBrush brBackground(m_crColor [PPTOOLTIP_COLOR_BK_BEGIN]);
CBrush brBorder(m_crColor [PPTOOLTIP_COLOR_BORDER]);
pDC->SetBkMode(TRANSPARENT);
//Sets clip region of the tooltip and draws the shadow if you need
if (m_pToolInfo.nStyles & PPTOOLTIP_SHADOW)
{
//Draws the shadow for the tooltip
OnDrawShadow(pDC);
rect.DeflateRect(0, 0, m_nSizes[PPTTSZ_SHADOW_CX], m_nSizes[PPTTSZ_SHADOW_CY]);
}
pDC->SelectClipRgn(&m_rgnToolTip);
OnDrawBackground(pDC, &rect);
//Draws the main region's border of the tooltip
pDC->FrameRgn(&m_rgnToolTip, &brBorder, m_nSizes[PPTTSZ_BORDER_CX], m_nSizes[PPTTSZ_BORDER_CY]);
//Gets the rectangle to draw the tooltip text
rect.DeflateRect(m_nSizes[PPTTSZ_MARGIN_CX], m_nSizes[PPTTSZ_MARGIN_CY]);
if ((m_nLastDirection == PPTOOLTIP_RIGHT_BOTTOM) || (m_nLastDirection == PPTOOLTIP_LEFT_BOTTOM))
rect.top += m_nSizes[PPTTSZ_HEIGHT_ANCHOR];
else
rect.bottom -= m_nSizes[PPTTSZ_HEIGHT_ANCHOR];
// Draw the icon
if (m_pToolInfo.hIcon != NULL)
{
CPoint ptIcon;
ptIcon.x = m_nSizes[PPTTSZ_MARGIN_CX];
ptIcon.y = rect.top;
if (m_pToolInfo.nStyles & PPTOOLTIP_ICON_VCENTER_ALIGN)
ptIcon.y = rect.top + (rect.Height() - m_szToolIcon.cy) / 2;
else if (m_pToolInfo.nStyles & PPTOOLTIP_ICON_BOTTOM_ALIGN)
ptIcon.y = rect.bottom - m_szToolIcon.cy;
//First variant
// pDC->DrawIcon(m_nSizes[PPTTSZ_MARGIN_CX], rect.top + (rect.Height() - m_szToolIcon.cy) / 2, m_pToolInfo.hIcon);
//Second variant
pDC->DrawState(ptIcon, m_szToolIcon, m_pToolInfo.hIcon, DSS_NORMAL, (CBrush*)NULL);
//Third variant
// DrawIconEx(pDC->m_hDC, ptIcon.x, ptIcon.y, m_pToolInfo.hIcon, m_szToolIcon.cx,
// m_szToolIcon.cy, 0, NULL, DI_NORMAL);
rect.left += m_szToolIcon.cx + m_nSizes[PPTTSZ_MARGIN_CX];
}
//Aligns tooltip's text
if (m_pToolInfo.nStyles & PPTOOLTIP_BOTTOM_ALIGN)
rect.top = rect.bottom - m_szTextTooltip.cy;
else if (m_pToolInfo.nStyles & PPTOOLTIP_VCENTER_ALIGN)
rect.top += (rect.Height() - m_szTextTooltip.cy) / 2;
//Prints the tooltip's text
PrintTitleString(pDC, rect, m_pToolInfo.sTooltip, FALSE);
brBackground.DeleteObject();
brBorder.DeleteObject();
}
void CPPToolTip::OnDrawShadow(CDC * pDC)
{
CBrush brShadow(m_crColor [PPTOOLTIP_COLOR_SHADOW]);
//Draws the shadow for the tooltip
int nRop2Mode = pDC->SetROP2(R2_MASKPEN);
pDC->FillRgn(&m_rgnShadow, &brShadow);
pDC->SetROP2(nRop2Mode);
brShadow.DeleteObject();
}
void CPPToolTip::OnDrawBackground(CDC * pDC, CRect * pRect)
{
switch (m_pToolInfo.nEffect)
{
default:
pDC->FillSolidRect(pRect, m_crColor[PPTOOLTIP_COLOR_BK_BEGIN]);
break;
case PPTOOLTIP_EFFECT_HGRADIENT:
FillGradient(pDC, pRect, m_crColor[PPTOOLTIP_COLOR_BK_BEGIN], m_crColor [PPTOOLTIP_COLOR_BK_END], TRUE);
break;
case PPTOOLTIP_EFFECT_VGRADIENT:
FillGradient(pDC, pRect, m_crColor[PPTOOLTIP_COLOR_BK_BEGIN], m_crColor [PPTOOLTIP_COLOR_BK_END], FALSE);
break;
case PPTOOLTIP_EFFECT_HCGRADIENT:
FillGradient(pDC, CRect(pRect->left, pRect->top, pRect->left + pRect->Width() / 2, pRect->bottom),
m_crColor[PPTOOLTIP_COLOR_BK_BEGIN], m_crColor [PPTOOLTIP_COLOR_BK_END], TRUE);
FillGradient(pDC, CRect(pRect->left + pRect->Width() / 2, pRect->top, pRect->right, pRect->bottom),
m_crColor[PPTOOLTIP_COLOR_BK_END], m_crColor [PPTOOLTIP_COLOR_BK_BEGIN], TRUE);
break;
case PPTOOLTIP_EFFECT_VCGRADIENT:
FillGradient(pDC, CRect (pRect->left, pRect->top, pRect->right, pRect->top + pRect->Height() / 2),
m_crColor[PPTOOLTIP_COLOR_BK_BEGIN], m_crColor [PPTOOLTIP_COLOR_BK_END], FALSE);
FillGradient(pDC, CRect (pRect->left, pRect->top + pRect->Height() / 2, pRect->right, pRect->bottom),
m_crColor[PPTOOLTIP_COLOR_BK_END], m_crColor [PPTOOLTIP_COLOR_BK_BEGIN], FALSE);
break;
case PPTOOLTIP_EFFECT_3HGRADIENT:
FillGradient(pDC, CRect(pRect->left, pRect->top, pRect->left + pRect->Width()/2, pRect->bottom),
m_crColor[PPTOOLTIP_COLOR_BK_BEGIN], m_crColor [PPTOOLTIP_COLOR_BK_MID], TRUE);
FillGradient(pDC, CRect(pRect->left + pRect->Width() / 2, pRect->top, pRect->right, pRect->bottom),
m_crColor[PPTOOLTIP_COLOR_BK_MID], m_crColor [PPTOOLTIP_COLOR_BK_END], TRUE);
break;
case PPTOOLTIP_EFFECT_3VGRADIENT:
FillGradient(pDC, CRect (pRect->left, pRect->top, pRect->right, pRect->top + pRect->Height() / 2),
m_crColor[PPTOOLTIP_COLOR_BK_BEGIN], m_crColor [PPTOOLTIP_COLOR_BK_MID], FALSE);
FillGradient(pDC, CRect (pRect->left, pRect->top + pRect->Height() / 2, pRect->right, pRect->bottom),
m_crColor[PPTOOLTIP_COLOR_BK_MID], m_crColor [PPTOOLTIP_COLOR_BK_END], FALSE);
break;
#ifdef PPTOOLTIP_USE_SHADE
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:
m_dNormal.Draw(pDC->GetSafeHdc(),0,0);
break;
#endif
}
}
void CPPToolTip::RelayEvent(MSG* pMsg)
{
ASSERT(m_pParentWnd);
CWnd * pWnd = NULL;
CPoint pt;
CRect rect;
CString str;
int nIndexTool = PPTOOLTIP_TOOL_NOEXIST;
// PPTOOLTIP_INFO Info;
switch(pMsg->message)
{
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK:
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONDBLCLK:
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONDBLCLK:
case WM_NCMBUTTONDOWN:
case WM_NCMBUTTONDBLCLK:
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
// The user has interupted the current tool - dismiss it
Pop();
break;
case WM_MOUSEMOVE:
// TRACE (_T("OnMouseMove()\n"));
if ((m_ptOriginal == pMsg->pt) ||
(m_nIndexCurrentWnd == PPTOOLTIP_TOOL_HELPER) ||
(m_nIndexDisplayWnd == PPTOOLTIP_TOOL_HELPER))
return; //Mouse pointer was not move
//Check Active window
if (!(m_nStyles & PPTOOLTIP_SHOW_INACTIVE))
{
pWnd = GetActiveWindow();
if (!pWnd)
return;
}
m_ptOriginal = pMsg->pt; //Stores the mouse's coordinates
//Gets the real window under the mouse
pt = pMsg->pt;
m_pParentWnd->ScreenToClient(&pt);
nIndexTool = FindTool(pt);
if (!IsExistTool(nIndexTool))
{
//If the window under the mouse isn't exist
if (IsCursorInToolTip() && (m_pToolInfo.nBehaviour & PPTOOLTIP_CLOSE_LEAVEWND))
return;
Pop();
m_nIndexCurrentWnd = PPTOOLTIP_TOOL_NOEXIST;
m_nIndexDisplayWnd = PPTOOLTIP_TOOL_NOEXIST;
return;
}
else
{
//The window under the mouse is exist
if (nIndexTool == m_nIndexDisplayWnd)
{
if (IsVisible())
{
//Now the tooltip is visible
if ((m_pToolInfo.nBehaviour & PPTOOLTIP_CLOSE_LEAVEWND))
return;
}
if (m_pToolInfo.nBehaviour & PPTOOLTIP_MULTIPLE_SHOW)
{
SetNewToolTip(nIndexTool);
}
else Pop();
}
else
{
SetNewToolTip(nIndexTool, !IsVisible());
}
}
break;
}
}
void CPPToolTip::SetNewToolTip(int nIndexTool, BOOL bWithDelay /* = TRUE */)
{
TRACE (_T("CPPToolTip::SetNewToolTip(Index = 0x%X)\n"), nIndexTool);
m_nIndexDisplayWnd = PPTOOLTIP_TOOL_NOEXIST; //reset the displayed window
Pop();
//Gets the info about current tool
if (!GetTool(nIndexTool, m_pToolInfo))
return;
//Remembers the pointer to the current window
m_nIndexCurrentWnd = nIndexTool;
//Start the show timer
if (bWithDelay)
SetTimer(PPTOOLTIP_SHOW, m_nTimeInitial, NULL);
else
OnTimer(PPTOOLTIP_SHOW);
}
void CPPToolTip::OnTimer(UINT nIDEvent)
{
CPoint pt = m_ptOriginal, point;
CString str;
int nIndexTool = PPTOOLTIP_TOOL_HELPER;
switch (nIDEvent)
{
case PPTOOLTIP_SHOW:
TRACE(_T("OnTimerShow\n"));
Pop();
if (m_nIndexCurrentWnd != PPTOOLTIP_TOOL_HELPER)
{
GetCursorPos(&pt);
point = pt;
m_pParentWnd->ScreenToClient(&point);
nIndexTool = FindTool(point);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -