www.pudn.com > XRayImg.rar > PPTooltip.cpp
//
//--- History ------------------------------
// 2004/03/01 *** Releases version 2.0 ***
//------------------------------------------
// 2004/04/04 [ADD] Added method SetCssStyles(DWORD dwIdCssStyle, LPCTSTR lpszPathDll /* = NULL */)
// 2004/04/14 [FIX] Fixed correct drawing for some tooltip's directions
// 2004/04/15 [FIX] Fixed changing a z-order of the some windows by show a tooltip on Win9x
// 2004/04/27 [FIX] Corrected a work with a tooltip's directions with a large tooltip
// 2004/04/28 [ADD] Disables a message translation if object was't created (thanks to Stoil Todorov)
// 2004/07/02 [UPD] Changes a GetWndFromPoint mechanism of the window's searching
// 2004/09/01 [ADD] New SetMaxTipWidth method was added
// 2004/10/12 [FIX] Now a tooltip has a different methods to show a menu's tooltip and other
// control's tooltip
////////////////////////////////////////////////////////////////////
//
// "SmoothMaskImage" and "GetPartialSums" functions by Denis Sarazhinsky (c)2003
// Modified by Eugene Pustovoyt to use with image's mask instead of full color image.
//
/////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "PPTooltip.h"
// allow multi-monitor-aware code on Win95 systems
// comment out the first line if you already define it in another file
// comment out both lines if you don't care about Win95
#define COMPILE_MULTIMON_STUBS
#include "multimon.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define TIMER_HIDE 0x101 //the identifier of the timer for hide the tooltip
#define TIMER_SHOWING 0x102 //the identifier of the timer for tooltip's fade in
#define TIMER_SHOW 0x100 //the identifier of the timer for show the tooltip
#define TIMER_HIDING 0x103 //the identifier of the timer for tooltip's fade out
#define TIMER_ANIMATION 0x104 //the identifier of the timer for animation
#define PERCENT_STEP_FADEIN 20 //How mush percent will adding during fade in
#define PERCENT_STEP_FADEOUT 20 //How mush percent will adding during fade out
#define PERCENT_MAX_TRANSPARENCY 100 //How mush percent by maximum transparency
#define PERCENT_MIN_TRANSPARENCY 0 //How mush percent by minimum transparency
#define MAX_LENGTH_DEBUG_STRING 25 //
/*
struct PPTOOLTIP_ENUM_CHILD
{
HWND hwndExclude;
HWND hWnd;
POINT ptScreen;
DWORD dwFlags;
};
BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
{
PPTOOLTIP_ENUM_CHILD * structEnum = (PPTOOLTIP_ENUM_CHILD*)lParam;
if (hwndChild != structEnum->hwndExclude)
{
DWORD dwStyle = ::GetWindowLong(hwndChild, GWL_STYLE);
if (!(dwStyle & WS_VISIBLE))
return TRUE;
if (structEnum->dwFlags & CWP_SKIPDISABLED)
{
if (dwStyle & WS_DISABLED)
return TRUE;
}
if ((dwStyle & 0xF) != BS_GROUPBOX)
{
RECT rcWindow;// = wi.rcWindow;
::GetWindowRect(hwndChild, &rcWindow);
if ((rcWindow.left <= structEnum->ptScreen.x) &&
(rcWindow.right > structEnum->ptScreen.x) &&
(rcWindow.top <= structEnum->ptScreen.y) &&
(rcWindow.bottom > structEnum->ptScreen.y))
{
structEnum->hWnd = hwndChild;
return FALSE;
} //if
} //if
} //if
return TRUE;
} //End EnumChildProc
*/
//////////////////
// Note that windows are enumerated in top-down Z-order, so the menu
// window should always be the first one found.
//
static BOOL CALLBACK MyEnumProc(HWND hwnd, LPARAM lParam)
{
TCHAR buf[16];
GetClassName(hwnd, buf, sizeof(buf) / sizeof(TCHAR));
if (_tcscmp(buf, _T("#32768")) == 0) // special classname for menus
{
*((HWND*)lParam) = hwnd; // found it
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip
CPPToolTip::CPPToolTip()
{
// Default values
m_dwTimeAutoPop = 5000;
m_dwTimeInitial = 500;
m_dwTimeFadeIn = 500;
m_dwTimeFadeOut = 500;
m_dwBehaviour = 0; //PPTOOLTIP_CLOSE_LEAVEWND | PPTOOLTIP_NOCLOSE_OVER; //The tooltip's behaviour
m_dwEffectBk = 0;
m_dwDirection = 0;
m_dwStyles = 0;
m_nGranularity = 0;
m_nTransparency = 0;
m_bDelayNextTool = FALSE;
m_dwShowEffect = SHOWEFFECT_FADEINOUT;
m_dwHideEffect = SHOWEFFECT_FADEINOUT;
m_nTooltipState = PPTOOLTIP_STATE_HIDEN;
m_nTooltipType = PPTOOLTIP_NORMAL;
m_nNextTooltipType = PPTOOLTIP_NORMAL;
m_ptOriginal.x = m_ptOriginal.y = 0;
m_rcCurTool.SetRectEmpty();
m_hwndDisplayedTool = NULL;
m_hBitmapBk = NULL;
m_hUnderTooltipBk = NULL;
m_hbrBorder = NULL;
m_hrgnTooltip = NULL;
SetColorBk(::GetSysColor(COLOR_INFOBK));
SetBorder(::GetSysColor(COLOR_INFOTEXT));
EnableHyperlink();
SetNotify(FALSE);
SetDefaultSizes();
SetDirection();
SetBehaviour();
SetDebugMode(FALSE);
SetMaxTipWidth(0);
// EnableTextWrap(FALSE);
SetDelayTime(PPTOOLTIP_TIME_INITIAL, 500);
SetDelayTime(PPTOOLTIP_TIME_AUTOPOP, 5000);
SetDelayTime(PPTOOLTIP_TIME_FADEIN, 0);
SetDelayTime(PPTOOLTIP_TIME_FADEOUT, 0);
SetTooltipShadow(6, 6);
#ifdef PPTOOLTIP_USE_MENU
MenuToolPosition();
#endif //PPTOOLTIP_USE_MENU
// 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();
} //if
}
CPPToolTip::~CPPToolTip()
{
FreeResources();
RemoveAllTools();
HideBorder();
}
BEGIN_MESSAGE_MAP(CPPToolTip, CWnd)
//{{AFX_MSG_MAP(CPPToolTip)
ON_WM_PAINT()
ON_WM_TIMER()
ON_WM_SETCURSOR()
ON_WM_ACTIVATEAPP()
//}}AFX_MSG_MAP
ON_MESSAGE(UDM_TOOLTIP_REPAINT, OnRepaintWindow)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip message handlers
BOOL CPPToolTip::Create(CWnd* pParentWnd, BOOL bBalloon /* = TRUE */)
{
TRACE(_T("CPPToolTip::Create\n"));
ASSERT_VALID(pParentWnd);
DWORD dwStyle = WS_POPUP;
DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
m_hParentWnd = pParentWnd->GetSafeHwnd();
if (!CreateEx(dwExStyle, PPTOOLTIP_CLASSNAME, NULL, dwStyle, 0, 0, 0, 0, pParentWnd->GetSafeHwnd(), NULL, NULL))
return FALSE;
//
SetDefaultSizes(bBalloon);
m_drawer.SetCallbackRepaint(this->GetSafeHwnd(), UDM_TOOLTIP_REPAINT);
SetDelayTime(PPTOOLTIP_TIME_ANIMATION, 100);
return TRUE;
} //End of Create
BOOL CPPToolTip::DestroyWindow()
{
Pop();
SetDelayTime(PPTOOLTIP_TIME_ANIMATION, 0);
return CWnd::DestroyWindow();
} //End of DestroyWindow
/////////////////////////////////////////////////////////////////////
// A tooltip with PPTOOLTIP_DISABLE_AUTOPOP behaviour don't hide on
// change active application
//-------------------------------------------------------------------
// Fixed by vanhoopy (July 10, 2003)
/////////////////////////////////////////////////////////////////////
#if _MSC_VER < 1300
void CPPToolTip::OnActivateApp(BOOL bActive, HTASK hTask)
#else
void CPPToolTip::OnActivateApp(BOOL bActive, DWORD hTask)
#endif //_MSC_VER
{
CWnd::OnActivateApp(bActive, hTask);
if (!bActive)
Pop();
} //End of the WM_ACTIVATEAPP handler
LRESULT CPPToolTip::SendNotify(LPPOINT 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 (!IsNotify())
return 0L;
NM_PPTOOLTIP_DISPLAY lpnm;
lpnm.hwndTool = m_hwndNextTool;
lpnm.pt = pt;
lpnm.ti = &ti;
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);
return 0L;
} //End of SendNotify
/////////////////////////////////////////////////////////////////////
// CPPToolTip::IsNotify()
// This function determines will be send the notification messages from
// the control or not before display.
//-------------------------------------------------------------------
// Return value:
// TRUE if the control will be notified the specified window
///////////////////////////////////////////////////////////////////////
BOOL CPPToolTip::IsNotify()
{
TRACE(_T("CPPToolTip::IsNotify\n"));
return (BOOL)(m_hNotifyWnd != NULL);
} //End of IsNotify
BOOL CPPToolTip::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
CPoint ptClient;
::GetCursorPos(&ptClient);
ScreenToClient(&ptClient);
TRACE (_T("CPPToolTip::OnSetCursor(x=%d, y=%d)\n"), ptClient.x, ptClient.y);
if (m_drawer.OnSetCursor(&ptClient))
return TRUE; //The cursor over the hyperlink
::SetCursor(::LoadCursor(NULL, IDC_ARROW));
// return CWnd::OnSetCursor(pWnd, nHitTest, message);
return TRUE;
} //End of the WM_SETCURSOR handler
LRESULT CPPToolTip::OnRepaintWindow(WPARAM wParam, LPARAM lParam)
{
TRACE (_T("CPPToolTip::OnRepaintWindow()\n"));
if (m_bHyperlinkEnabled)
{
//Window's repaint enabled
CDC * pDC = GetDC();
OnRedrawTooltip(pDC->GetSafeHdc());
ReleaseDC(pDC);
}
return TRUE;
} //End of the UDM_TOOLTIP_REPAINT handler
void CPPToolTip::OnDrawBorder(HDC hDC, HRGN hRgn)
{
ASSERT (hDC);
ASSERT (hRgn);
::FrameRgn(hDC, hRgn, m_hbrBorder, m_szBorder.cx, m_szBorder.cy);
} //End OnDrawBorder
////////////////////////////////////////////////////////////////////////
//
// +-----------------+ +-------------------+ +-----------------+
// +->| Screen +--->| m_hUnderTooltipBk | | m_hBitmapBk |
// | +--------+--------+ +-------------------+ +--------+--------+
// | | |
// | +--------V--------+ +--------V--------+
// | | | +--------------+ | |
// | | | | DrawHTML |---->| |
// | | | +--------------+ | |
// | | | | MemDC |
// | | | +--------------+ | |
// | | | | OnDrawBorder |---->| |
// | | TempDC | +--------------+ +--------+--------+
// | | | |
// | | | +--------------+ |
// | | |<----+ DrawShadow | |
// | | | +--------------+ |
// | | | |
// | | |<--------ALPHA---------------------+
// | | |
// | +--------+--------+
// | |
// +-----------+
//
////////////////////////////////////////////////////////////////////////
void CPPToolTip::OnRedrawTooltip(HDC hDC, BYTE nTransparency /* = 0 */)
{
TRACE (_T("CPPToolTip::OnRedrawTooltip(Transparency = %d)\n"), nTransparency);
//ENG: If a transparency more then max value
//RUS: Если значение прозрачности больше максимально допустимого
if (nTransparency > PERCENT_MAX_TRANSPARENCY)
nTransparency = PERCENT_MAX_TRANSPARENCY;
//ENG: If device context not passed
//RUS: Если контекст устройства не передавался, то получаем его и устанавливаем признак автоматического удаления
BOOL bAutoReleaseDC = FALSE;
if (NULL == hDC)
{
hDC = ::GetDC(this->GetSafeHwnd());
bAutoReleaseDC = TRUE;
} //if
//ENG: Creates memory context
//RUS: Создаем контекст устройства в памяти
HDC hMemDC = ::CreateCompatibleDC(hDC);
HDC hBkDC = ::CreateCompatibleDC(hDC);
HDC hTempDC = ::CreateCompatibleDC(hDC);
HBITMAP hOldBkBitmap = (HBITMAP)::SelectObject(hBkDC, m_hBitmapBk);
HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, m_rcBoundsTooltip.Width(), m_rcBoundsTooltip.Height());
HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hBitmap);
HBITMAP hTempBitmap = ::CreateCompatibleBitmap(hDC, m_rcBoundsTooltip.Width(), m_rcBoundsTooltip.Height());
HBITMAP hOldTempBitmap = (HBITMAP)::SelectObject(hTempDC, hTempBitmap);
//ENG: Gets the rectangle of the tooltip without a shadow
//RUS: Получаем размер тултипа без тени
CRect rect = m_rcBoundsTooltip;
rect.DeflateRect(0, 0, m_szOffsetShadow.cx, m_szOffsetShadow.cy);
//ENG: Copy background to the temporary bitmap
//RUS: Копируем фон под тултипом в память
::BitBlt(hMemDC, 0, 0, rect.Width(), rect.Height(),
hBkDC, 0, 0, SRCCOPY);
//ENG: Draw HTML string
//RUS: Отображаем HTML строку
m_drawer.DrawPreparedOutput(hMemDC, &m_rcTipArea);
//ENG: Gets a region of a window
//RUS: Получаем регион окна
// HRGN hrgn = ::CreateRectRgn(0, 0, 0, 0);
// GetWindowRgn(hrgn);
//ENG: Draw border of the tooltip
//RUS: Отображаем контур тултипа
if ((NULL != m_hbrBorder) && (m_szBorder.cx) && (m_szBorder.cy))
OnDrawBorder(hMemDC, m_hrgnTooltip);
if (NULL == m_hUnderTooltipBk)
{
//ENG: Stores a background under the tooltip to a bitmap
//RUS: Сохраняем фон под тултипом в битмап
m_hUnderTooltipBk = ::CreateCompatibleBitmap(hDC, m_rcBoundsTooltip.Width(), m_rcBoundsTooltip.Height());
::SelectObject(hBkDC, m_hUnderTooltipBk);
::BitBlt(hBkDC, 0, 0, m_rcBoundsTooltip.Width(), m_rcBoundsTooltip.Height(),
hDC, m_rcBoundsTooltip.left, m_rcBoundsTooltip.top, SRCCOPY);
}
else
{
//ENG: Restores a background from a bitmap
//RUS: Восстанавливаем фон из битмапа
::SelectObject(hBkDC, m_hUnderTooltipBk);
} //if
//ENG: Copy a original background bitmap to the temporary DC
//RUS: Копируем оригинальный битмап во временный контекст памяти
::BitBlt(hTempDC, m_rcBoundsTooltip.left, m_rcBoundsTooltip.top, m_rcBoundsTooltip.Width(), m_rcBoundsTooltip.Height(),
hBkDC, 0, 0, SRCCOPY);
//ENG: Draws a shadow
//RUS: Выводим тень
if (m_szOffsetShadow.cx || m_szOffsetShadow.cy)
{
//ENG: Creates a mask of the tooltip for shadow
//RUS: Создаем маску тултипа для вывода тени
HBITMAP hMask = ::CreateCompatibleBitmap(hDC, rect.Width(), rect.Height());
HDC hMaskDC = ::CreateCompatibleDC(hDC);
//ENG: Creates a mask of the tooltip
//RUS: Создание маски тултипа
BYTE nColor = LOBYTE(::MulDiv(255, 100 - m_nDarkenShadow, 100));
nColor += ((255 - nColor) * nTransparency) / 100;
HBRUSH hBrush = ::CreateSolidBrush(RGB(nColor, nColor, nColor));
HBITMAP hOldMask = (HBITMAP)::SelectObject(hMaskDC, hMask);
::BitBlt(hMaskDC, 0, 0, rect.Width(), rect.Height(), NULL, 0, 0, WHITENESS);
::FillRgn(hMaskDC, m_hrgnTooltip, hBrush);
::DeleteObject(hBrush);
::SelectObject(hMaskDC, hOldMask);
::DeleteDC(hMaskDC);
//HBITMAP hTempBmp = m_drawer.GetDrawManager()->CreateImageEffect(m_hTooltipMask, rect.Width(), rect.Height(), IMAGE_EFFECT_LIGHTEN, )
m_drawer.GetDrawManager()->DrawShadow(hTempDC,
m_szOffsetShadow.cx,
m_szOffsetShadow.cy,
rect.Width(), rect.Height(), hMask,
m_bGradientShadow,
m_szDepthShadow.cx, m_szDepthShadow.cy);
::DeleteObject(hMask);
} //if
//ENG: Merges a tooltip on with the client area
//RUS: Накладываем тултип на клиентскую часть с альфа-наложением
::SelectClipRgn(hTempDC, m_hrgnTooltip);
m_drawer.GetDrawManager()->AlphaBitBlt(hTempDC, m_rcBoundsTooltip.left, m_rcBoundsTooltip.top,
rect.Width(), rect.Height(),
hMemDC, 0, 0, 100 - nTransparency);
::SelectClipRgn(hTempDC, NULL);
//ENG: Output a tooltip to the screen
//RUS: Выводим тултип на экран
::BitBlt(hDC, m_rcBoundsTooltip.left, m_rcBoundsTooltip.top,
m_rcBoundsTooltip.Width(), m_rcBoundsTooltip.Height(),
hTempDC, 0, 0, SRCCOPY);
//ENG: Free resources
//RUS: Освобождаем задействованные ресурсы
::SelectObject(hBkDC, hOldBkBitmap);
::SelectObject(hMemDC, hOldBitmap);
::SelectObject(hTempDC, hOldTempBitmap);
::DeleteObject(hBitmap);
::DeleteObject(hTempBitmap);
::DeleteDC(hBkDC);
::DeleteDC(hMemDC);
::DeleteDC(hTempDC);
//ENG: Releases device context if needed
//RUS: Освобождаем контекст устройства если это необходимо
if (bAutoReleaseDC)
::ReleaseDC(this->GetSafeHwnd(), hDC);
} //End of OnRedrawWindow
void CPPToolTip::OnPaint()
{
TRACE(_T("CPPToolTip::OnPaint()\n"));
CPaintDC dc(this); // device context for painting
//Copying info about current tool to displayed
m_hwndDisplayedTool = m_hwndNextTool;
m_tiDisplayed = m_tiNextTool;
m_nTooltipType = m_nNextTooltipType;
OnRedrawTooltip(dc.GetSafeHdc(), m_dwCurTransparency);
} //End of the WM_PAINT handler
BOOL CPPToolTip::PreTranslateMessage(MSG* pMsg)
{
RelayEvent(pMsg);
return CWnd::PreTranslateMessage(pMsg);
}
BOOL CPPToolTip::RelayEvent(MSG* pMsg)
{
//ENG: Disables a message translation if object was't created (thanks to Stoil Todorov)
//RUS: Запрет обработки сообщений если объект не создан
if (NULL == GetSafeHwnd())
return FALSE;
ASSERT(m_hParentWnd);
HWND hWnd = NULL;
POINT pt;
CRect rect;
PPTOOLTIP_INFO ti;
CString strTemp;
switch(pMsg->message)
{
case WM_SETFOCUS:
rect.left = 0;
break;
case WM_LBUTTONDOWN:
TRACE(_T("CPPToolTip::WM_LBUTTONDOWN\n"));
if (IsCursorOverTooltip())
{
//Left Button was pressed over the tooltip
pt = pMsg->pt;
ScreenToClient(&pt);
m_drawer.OnLButtonDown(&pt); //
} //if
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:
case WM_MOUSEWHEEL:
// // The user has interrupted the current tool - dismiss it
// if (!(m_tiDisplayed.nBehaviour & PPTOOLTIP_NOCLOSE_MOUSEDOWN))
Pop();
break;
case WM_MOUSEMOVE:
if ((PPTOOLTIP_HELP == m_nTooltipType) || (PPTOOLTIP_HELP == m_nNextTooltipType))
return FALSE;
if ((m_ptOriginal.x != pMsg->pt.x) || (m_ptOriginal.y != pMsg->pt.y))
{
// The mouse pointer's position was changed
//Initialize values
rect.SetRectEmpty();
m_ptOriginal = pt = pMsg->pt;
::ScreenToClient(m_hParentWnd, &pt);
if (m_bDebugMode)
{
//Debug mode
ti.sTooltip = GetDebugInfoTool(&pt);
ti.nMask = 0;
m_hwndDisplayedTool = NULL;
SetNewTooltip(this->GetSafeHwnd(), ti);
}
else if (IsCursorOverTooltip() && !(m_tiDisplayed.nBehaviour & PPTOOLTIP_TRACKING_MOUSE))
{
//ENG: Mouse over a tooltip and tracking mode was disabled
//RUS: Курсор над тултипом при выключенном режиме "тракинга"
if (!(m_tiDisplayed.nBehaviour & PPTOOLTIP_NOCLOSE_OVER))
{
//ENG: A tooltip don't hides when mouse over him
//RUS: Если не установлен стиль не закрывания тултипа если курсор над ним
HideTooltip();
}
else
{
//ENG: Resetup autopop timer
//RUS: Переустанавливаем таймер автозакрытия тултипа
SetAutoPopTimer();
} //if
}
else
{
//ENG: Searching a toolbar's item
//RUS: Ищем элемент на панели инструментов
hWnd = FindToolBarItem(pMsg->pt, ti);
if (NULL == hWnd)
{
//ENG: Searching a hot area of the tooltip
//RUS: Ищем предопределенную горячую зону тултипа
hWnd = FindTool(&pt, ti);
} //if
TRACE ("Временное окно = 0x%08X\n", hWnd);
if (NULL == hWnd)
{
//ENG: An item with a tooltip wasn't found
//RUS: Ни один элемент, отображающий тултип, не найден
m_hwndDisplayedTool = NULL;
m_tiDisplayed.rectBounds.SetRectEmpty();
KillTimer(TIMER_SHOW);
HideTooltip();
}
else
{
if ((hWnd != m_hwndDisplayedTool) || (ti.rectBounds != m_tiDisplayed.rectBounds/* m_rcDisplayedTool*/))
{
//ENG: Sets new tooltip for the new window or for the new window's item
//RUS: Если новое окно или новый элемент окна, то установить новый тултип
SetNewTooltip(hWnd, ti);
}
else
{
//ENG: Nothing was changed
//RUS: Если ни окно, ни элемент окна не изменялись
if (m_tiDisplayed.nBehaviour & PPTOOLTIP_TRACKING_MOUSE)
{
//ENG: If sets tracking mode
//RUS: Если установлен режим "тракинга"
SetAutoPopTimer();
OutputTooltipOnScreen(&pMsg->pt);
}
else if (!(m_tiDisplayed.nBehaviour & PPTOOLTIP_CLOSE_LEAVEWND))
{
//ENG: A tooltip must hide at anything mouse move
//RUS: Если должен прятаться прилюбом движении мыши
if ((hWnd == m_hwndDisplayedTool) &&
!(m_tiDisplayed.nBehaviour & PPTOOLTIP_MULTIPLE_SHOW))
{
//ENG: "Multiple show" mode was disabled
//RUS: Если не установлен режим множественного показа тултипа
HideTooltip();
}
else
{
//ENG: "Multiple show" mode was enabled
//RUS: Если установлен режим множественного показа тултипа
SetNewTooltip(hWnd, ti);
} //if
}
else
{
//ENG: A tooltip don't must when a mouse is over window
//RUS: Тултип не должен прятаться пока находится над окном
SetAutoPopTimer();
} //if
} //if
} //if
} //if
} //if
break;
} //switch
return FALSE;
} //End RelayEvent
void CPPToolTip::SetNewTooltip(HWND hWnd, const PPTOOLTIP_INFO & ti, BOOL bDisplayWithDelay /* = TRUE */, TooltipType type /* = PPTOOLTIP_NORMAL */)
{
TRACE (_T("CPPToolTip::SetNewTooltip(hWnd=0x%08X, CRect(left=%d, top=%d, right=%d, bottom=%d), nID=%d)\n"),
hWnd, ti.rectBounds.left, ti.rectBounds.top, ti.rectBounds.right, ti.rectBounds.bottom, ti.nIDTool);
m_bNextToolExist = FALSE;
//ENG: Hides a tooltip
//RUS: Прячем тултип если он показан или показывается
if ((PPTOOLTIP_STATE_SHOWING == m_nTooltipState) ||
(PPTOOLTIP_STATE_SHOWN == m_nTooltipState))
HideTooltip();
//ENG: If a tooltip wasn't hidden
//RUS: Если тултип еще не спрятан, ждем ...
m_nNextTooltipType = type;
m_hwndNextTool = hWnd;
m_tiNextTool = ti;
if (PPTOOLTIP_STATE_HIDEN != m_nTooltipState)
{
TRACE(_T("SetNewTooltip2(%d)\n"), m_nNextTooltipType);
m_bNextToolExist = TRUE;
if (bDisplayWithDelay && m_dwTimeInitial)
m_bDelayNextTool = TRUE;
else
m_bDelayNextTool = FALSE;
return;
} //if
//ENG: Start the show timer
//RUS: Начинаем показ нового тултипа
if (bDisplayWithDelay && m_dwTimeInitial)
SetTimer(TIMER_SHOW, m_dwTimeInitial, NULL);
else
OnTimer(TIMER_SHOW);
} //End of SetNewTooltip
void CPPToolTip::OnTimer(UINT nIDEvent)
{
POINT pt;
switch (nIDEvent)
{
case TIMER_SHOW:
TRACE(_T("OnTimerShow(%d)\n"), m_nNextTooltipType);
//ENG: Kill SHOW timer
//RUS: Убить таймер ожидания показа тултипа
KillTimer(TIMER_SHOW);
//ENG: Get current mouse coordinates
//RUS: Получить текущее положение тултипа
if ((PPTOOLTIP_HELP == m_nNextTooltipType) ||
(PPTOOLTIP_MENU == m_nNextTooltipType))
pt = m_ptOriginal;
else GetCursorPos(&pt);
if ((pt.x != m_ptOriginal.x) || (pt.y != m_ptOriginal.y))
{
//ENG: If mouse coordinates was changed
//RUS: Если курсор сдвинулся, то уничтожить тултип
TRACE(_T("OnTimerShow(HideTooltip)\n"));
HideTooltip();
}
else if (PPTOOLTIP_STATE_HIDEN == m_nTooltipState)
{
TRACE(_T("OnTimerShow(Showing)\n"));
m_nTooltipState = PPTOOLTIP_STATE_SHOWING;
//Display first step
PrepareDisplayTooltip(&m_ptOriginal);
//Fade In effect
if ((SHOWEFFECT_FADEINOUT == m_dwShowEffect) && m_dwTimeFadeIn)
{
TRACE(_T("OnTimerShow(FadeIn)\n"));
SetTimer(TIMER_SHOWING, m_dwTimeFadeIn, NULL); //Fade in showing was enabled
}
else
{
TRACE(_T("OnTimerShow(Shown)\n"));
m_nTooltipState = PPTOOLTIP_STATE_SHOWN; //Tooltip is already show
if (m_dwTimeAutoPop && !(m_tiNextTool.nBehaviour & PPTOOLTIP_DISABLE_AUTOPOP))
SetTimer(TIMER_HIDE, m_dwTimeAutoPop, NULL); //Hiding by timer was enabled
} //if
} //if
break;
case TIMER_SHOWING:
TRACE(_T("OnTimerFadeIn(Current Transparency=%d )\n"), m_dwCurTransparency);
//ENG: If fade-in effect was finished then sets minimum transparency
//RUS: Если шаги эффекта плавного показа исчерпаны, то установить минимальную прозрачность
if (m_dwCurTransparency > (PERCENT_MIN_TRANSPARENCY + PERCENT_STEP_FADEIN))
m_dwCurTransparency -= PERCENT_STEP_FADEIN;
else m_dwCurTransparency = PERCENT_MIN_TRANSPARENCY;
if (m_dwCurTransparency <= m_tiDisplayed.nTransparency)
{
//ENG: Kills showing timer and sets a tooltip's state as SHOWN
//RUS: Убиваем таймер плавного показа и устанавливаем состояние тултипа как SHOWN
m_dwCurTransparency = m_tiDisplayed.nTransparency;
KillTimer(TIMER_SHOWING);
m_nTooltipState = PPTOOLTIP_STATE_SHOWN;
//ENG: Starts timer to auto pop of the tooltip
//RUS: Запуск таймера на автоматическое сокрытие тултипа
SetAutoPopTimer();
} //if
//ENG: Redraw tooltip with new transparency factor
//RUS: Перерисовать текущий тултип с новым коэффициентом прозрачности
OnRedrawTooltip(NULL, m_dwCurTransparency);
break;
case TIMER_HIDE:
TRACE(_T("OnTimerHide()\n"));
//ENG: Kill all timers except HIDING timer
//RUS: Убиваем все таймеры за исключением таймера HIDING
KillTimer(TIMER_SHOW);
KillTimer(TIMER_SHOWING);
KillTimer(TIMER_HIDE);
//ENG: If hiding timer don't start
//RUS: Проверяем запущен ли таймер сокрытия тултипа
if (PPTOOLTIP_STATE_HIDING != m_nTooltipState)
{
m_nTooltipState = PPTOOLTIP_STATE_HIDING;
if ((SHOWEFFECT_FADEINOUT == m_dwHideEffect) && m_dwTimeFadeOut)
{
//ENG: If fade-out effect enabled and setted fade-out timestep
//RUS: Если эффект плавного сокрытия разрешен и указано время шага сокрытия
SetTimer(TIMER_HIDING, m_dwTimeFadeOut, NULL);
}
else
{
//ENG: Sets a maximum transparency and to stops a hiding of a tooltip
//RUS: Устанавливаем максимальную прозрачность и останавливаем сокрытие
m_dwCurTransparency = PERCENT_MAX_TRANSPARENCY;
OnTimer(TIMER_HIDING);
} //if
} //if
break;
case TIMER_HIDING:
TRACE(_T("OnTimerFadeOut(Current Transparency=%d)\n"), m_dwCurTransparency);
//ENG: If fade-out effect was finished then sets maximum transparency
//RUS: Если шаги эффекта плавного сокрытия исчерпаны, то установить максимальную прозрачность
if (m_dwCurTransparency < (PERCENT_MAX_TRANSPARENCY - PERCENT_STEP_FADEOUT))
m_dwCurTransparency += PERCENT_STEP_FADEOUT;
else m_dwCurTransparency = PERCENT_MAX_TRANSPARENCY;
if (PERCENT_MAX_TRANSPARENCY == m_dwCurTransparency)
{
//ENG: Kills hiding timer and hides a tooltip
//RUS: Убиваем таймер плавного сокрытия и прячем окно тултипа
KillTimer(TIMER_HIDING);
if (m_tiDisplayed.nBehaviour & PPTOOLTIP_MULTIPLE_SHOW)
{
//If for tool to set a multiple show then reset last window
m_hwndDisplayedTool = NULL;
m_tiDisplayed.rectBounds.SetRectEmpty();
} //if
ShowWindow(SW_HIDE);
m_nTooltipState = PPTOOLTIP_STATE_HIDEN;
if (m_bNextToolExist)
{
//ENG: If next tooltip is exist then starts show
//RUS: Если существует подготовленный тултип, то начать его отображение
m_bNextToolExist = FALSE;
// m_nTooltipType = m_nNextTooltipType;
// m_nNextTooltipType = PPTOOLTIP_NORMAL;
if (m_bDelayNextTool) SetTimer(TIMER_SHOW, m_dwTimeInitial, NULL);
else OnTimer(TIMER_SHOW);
}
else
{
//ENG: If next tooltip wasn't exist
//RUS: Если подготовленный тултип не существует
m_nTooltipType = PPTOOLTIP_NORMAL;
m_nNextTooltipType = PPTOOLTIP_NORMAL;
} //if
}
else
{
//ENG: Redraw tooltip with new transparency factor
//RUS: Перерисовать текущий тултип с новым коэффициентом прозрачности
OnRedrawTooltip(NULL, m_dwCurTransparency);
} //if
break;
case TIMER_ANIMATION:
if (IsVisible() && (PPTOOLTIP_STATE_SHOWN == m_nTooltipState))
{
if(m_drawer.OnTimer())
OnRedrawTooltip(NULL, m_dwCurTransparency);
} //if
break;
default:
CWnd::OnTimer(nIDEvent);
break;
} //switch
} //End of the WM_TIMER handler
void CPPToolTip::HideTooltip()
{
TRACE (_T("CPPToolTip::HideTooltip(CurState=%d)\n"), m_nTooltipState);
switch(m_nTooltipState)
{
case PPTOOLTIP_STATE_SHOWING:
//ENG: Kill showing tooltip
//RUS: Если тултип только отбражается, то прекращаем его отображать
KillTimer(TIMER_SHOWING);
case PPTOOLTIP_STATE_SHOWN:
//ENG: Hiding a tooltip
//RUS: Прячем тултип
OnTimer(TIMER_HIDE);
break;
} //switch
} //End of HideTooltip
void CPPToolTip::SetAutoPopTimer()
{
TRACE (_T("CPPToolTip::SetAutoPopTimer()\n"));
if (m_dwTimeAutoPop && !(m_tiDisplayed.nBehaviour & PPTOOLTIP_DISABLE_AUTOPOP))
SetTimer(TIMER_HIDE, m_dwTimeAutoPop, NULL);
} //End of SetAutoPopTimer
void CPPToolTip::KillTimers(DWORD dwIdTimer /* = NULL */)
{
TRACE (_T("CPPToolTip::KillTimers()\n"));
if (dwIdTimer == NULL)
{
KillTimer(TIMER_SHOW);
KillTimer(TIMER_HIDE);
KillTimer(TIMER_SHOWING);
KillTimer(TIMER_HIDING);
}
else
{
KillTimer(dwIdTimer);
} //if
} //End KillTimers
void CPPToolTip::Pop()
{
TRACE (_T("CPPToolTip::Pop()\n"));
m_nTooltipState = PPTOOLTIP_STATE_HIDEN;
m_nTooltipType = PPTOOLTIP_NORMAL;
m_nNextTooltipType = PPTOOLTIP_NORMAL;
KillTimers();
if (IsVisible())
{
if (m_tiDisplayed.nBehaviour & PPTOOLTIP_MULTIPLE_SHOW)
{
//If for tool to set a multiple show then reset last window
m_hwndDisplayedTool = NULL;
m_tiDisplayed.rectBounds.SetRectEmpty();
} //if
ShowWindow(SW_HIDE);
} //if
} //End of Pop
void CPPToolTip::PrepareDisplayTooltip(LPPOINT lpPoint)
{
TRACE (_T("CPPToolTip::PrepareDisplayTooltip()\n"));
//Fills default members
if (!(m_tiNextTool.nMask & PPTOOLTIP_MASK_STYLES))
m_tiNextTool.nStyles = m_dwStyles;
if (!(m_tiNextTool.nMask & PPTOOLTIP_MASK_EFFECT))
{
m_tiNextTool.nEffect = m_dwEffectBk;
m_tiNextTool.nGranularity = m_nGranularity;
} //if
if (!(m_tiNextTool.nMask & PPTOOLTIP_MASK_COLORS))
{
m_tiNextTool.crBegin = m_clrBeginBk;
m_tiNextTool.crMid = m_clrMidBk;
m_tiNextTool.crEnd = m_clrEndBk;
} //if
if (!(m_tiNextTool.nMask & PPTOOLTIP_MASK_DIRECTION))
m_tiNextTool.nDirection = m_dwDirection;
if (!(m_tiNextTool.nMask & PPTOOLTIP_MASK_BEHAVIOUR))
m_tiNextTool.nBehaviour = m_dwBehaviour;
if (!(m_tiNextTool.nMask & PPTOOLTIP_MASK_TRANSPARENCY))
m_tiNextTool.nTransparency = m_nTransparency;
//Send notify
POINT pt = *lpPoint; //Pointer in screen coordinates
SendNotify(&pt, m_tiNextTool);
//If string and icon are not exist then exit
if (m_tiNextTool.sTooltip.IsEmpty())
return;
//calculate the width and height of the box dynamically
CDC * pDC = GetDC();
ASSERT(pDC->GetSafeHdc());
CSize sz (0, 0);
m_drawer.PrepareOutput(pDC->GetSafeHdc(), m_tiNextTool.sTooltip, &sz);
m_rcTipArea.SetRect(0, 0, sz.cx, sz.cy);
m_rcTooltip = m_rcTipArea;
//Inflates on MARGIN_CX and MARGIN_CY sizes
m_rcTipArea.OffsetRect(m_nSizes[PPTTSZ_MARGIN_CX], m_nSizes[PPTTSZ_MARGIN_CY]);
m_rcTooltip.InflateRect(0, 0, 2 * m_nSizes[PPTTSZ_MARGIN_CX], 2 * m_nSizes[PPTTSZ_MARGIN_CY]);
//Inflates on
//Gets tooltip's rect with anchor
CPoint ptAnchor;
m_dwCurDirection = GetTooltipDirection(m_tiNextTool.nDirection, pt, ptAnchor, m_rcTooltip, m_rcBoundsTooltip, m_rcTipArea);
//ENG: Clears resources
//RUS: Очищаем ресурсы
FreeResources();
//ENG: Creates a new region of the window
//RUS: Создаем новый регион окна
m_hrgnTooltip = GetTooltipRgn(m_dwCurDirection, ptAnchor.x, ptAnchor.y, m_rcBoundsTooltip.Width(), m_rcBoundsTooltip.Height());
CRect rect = m_rcBoundsTooltip;
//ENG: Creates a background bitmap
//RUS: Создаем битмап фона тултипа
m_hBitmapBk = ::CreateCompatibleBitmap(pDC->GetSafeHdc(), rect.Width(), rect.Height());
HDC hMemDC = ::CreateCompatibleDC(pDC->GetSafeHdc());
//ENG: Creates a background of the tooltip's body
//RUS: Создание фона тела тултипа
HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, m_hBitmapBk);
m_drawer.GetDrawManager()->FillEffect(hMemDC,
m_tiNextTool.nEffect,
m_rcTooltip,
m_tiNextTool.crBegin,
m_tiNextTool.crMid,
m_tiNextTool.crEnd,
m_tiNextTool.nGranularity,
5);
//ENG: Fills an anchor
//RUS: Заполняем якорь тултипа
switch (m_dwCurDirection)
{
case PPTOOLTIP_LEFTEDGE_TOP:
case PPTOOLTIP_LEFTEDGE_VCENTER:
case PPTOOLTIP_LEFTEDGE_BOTTOM:
m_drawer.GetDrawManager()->MultipleCopy(hMemDC, m_rcBoundsTooltip.left, m_rcBoundsTooltip.top, m_rcTooltip.left - m_rcBoundsTooltip.left, m_rcBoundsTooltip.Height(),
hMemDC, m_rcTooltip.left + 1, m_rcBoundsTooltip.top, 1, m_rcBoundsTooltip.Height());
break;
case PPTOOLTIP_RIGHTEDGE_TOP:
case PPTOOLTIP_RIGHTEDGE_VCENTER:
case PPTOOLTIP_RIGHTEDGE_BOTTOM:
m_drawer.GetDrawManager()->MultipleCopy(hMemDC, m_rcTooltip.right, m_rcBoundsTooltip.top, m_rcBoundsTooltip.right - m_rcTooltip.right, m_rcBoundsTooltip.Height(),
hMemDC, m_rcTooltip.right - 1, m_rcBoundsTooltip.top, 1, m_rcBoundsTooltip.Height());
break;
case PPTOOLTIP_BOTTOMEDGE_LEFT:
case PPTOOLTIP_BOTTOMEDGE_CENTER:
case PPTOOLTIP_BOTTOMEDGE_RIGHT:
m_drawer.GetDrawManager()->MultipleCopy(hMemDC, m_rcBoundsTooltip.left, m_rcTooltip.bottom, m_rcBoundsTooltip.Width(), m_rcBoundsTooltip.bottom - m_rcTooltip.bottom,
hMemDC, m_rcBoundsTooltip.left, m_rcTooltip.bottom - 1, m_rcBoundsTooltip.Width(), 1);
break;
case PPTOOLTIP_TOPEDGE_LEFT:
case PPTOOLTIP_TOPEDGE_CENTER:
case PPTOOLTIP_TOPEDGE_RIGHT:
m_drawer.GetDrawManager()->MultipleCopy(hMemDC, m_rcBoundsTooltip.left, m_rcBoundsTooltip.top, m_rcBoundsTooltip.Width(), m_rcTooltip.top - m_rcBoundsTooltip.top,
hMemDC, m_rcBoundsTooltip.left, m_rcTooltip.top + 1, m_rcBoundsTooltip.Width(), 1);
break;
} //switch
::SelectObject(hMemDC, hOldBitmap);
::DeleteDC(hMemDC);
ReleaseDC(pDC);
//ENG: Calculate the tooltip's placement on the screen
//RUS: Вычисление положения тултипа на экране
rect.left = pt.x - ptAnchor.x;
rect.top = pt.y - ptAnchor.y;
rect.right = rect.left + m_rcBoundsTooltip.Width();
rect.bottom = rect.top + m_rcBoundsTooltip.Height();
//ENG: If fade-in effect ia available
//RUS: Если плавное отображение доступно
if ((SHOWEFFECT_FADEINOUT == m_dwShowEffect) && m_dwTimeFadeIn)
m_dwCurTransparency = 100;
else
m_dwCurTransparency = m_tiNextTool.nTransparency;
HRGN hrgnWindow = ::CreateRectRgn(0, 0, 0, 0);
if (m_szOffsetShadow.cx || m_szOffsetShadow.cy)
{
//ENG: If shadow will drawn
//RUS: Если тень будет отображаться
HRGN hrgnShadow = ::CreateRectRgn(0, 0, 0, 0);
::CombineRgn(hrgnShadow, m_hrgnTooltip, hrgnShadow, RGN_COPY);
::OffsetRgn(hrgnShadow, m_szOffsetShadow.cx, m_szOffsetShadow.cy);
::CombineRgn(hrgnWindow, m_hrgnTooltip, hrgnShadow, RGN_OR);
::DeleteObject(hrgnShadow);
//ENG: Increments the sizes of tooltip to drawing a shadow
//RUS: Увеличиваем размеры тултипа для рисования тени
m_rcBoundsTooltip.right += m_szOffsetShadow.cx;
m_rcBoundsTooltip.bottom += m_szOffsetShadow.cy;
}
else
{
//ENG: The current window has not a shadow
//RUS: Текущее окно не имеет тени
::CombineRgn(hrgnWindow, m_hrgnTooltip, NULL, RGN_COPY);
}//if
//ENG: Applies a region
//RUS: Применяем регион
SetWindowRgn(hrgnWindow, FALSE);
//ENG: Sets a tooltip on the screen
//RUS: Устанавливаем тултип на экране
if (PPTOOLTIP_MENU == m_nTooltipType)
{
SetWindowPos(NULL,
rect.left, rect.top,
m_rcBoundsTooltip.Width(),
m_rcBoundsTooltip.Height(),
SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER/*|SWP_NOCOPYBITS*/);
}
else
{
SetWindowPos(NULL,
rect.left, rect.top,
m_rcBoundsTooltip.Width(),
m_rcBoundsTooltip.Height(),
SWP_SHOWWINDOW|SWP_NOACTIVATE/*|SWP_NOCOPYBITS*/);
}
} //End of PrepareDisplayTooltip
void CPPToolTip::FreeResources()
{
if (NULL != m_hrgnTooltip)
{
::DeleteObject(m_hrgnTooltip);
m_hrgnTooltip = NULL;
} //if
if (NULL != m_hBitmapBk)
{
::DeleteObject(m_hBitmapBk);
m_hBitmapBk = NULL;
} //if
if (NULL != m_hUnderTooltipBk)
{
::DeleteObject(m_hUnderTooltipBk);
m_hUnderTooltipBk = NULL;
} //if
} //End of FreeResources
void CPPToolTip::OutputTooltipOnScreen(LPPOINT lpPoint, HDC hDC /* = NULL */)
{
TRACE(_T("OutputTooltipOnScreen()\n"));
CRect rect = m_rcBoundsTooltip;
rect.OffsetRect(*lpPoint);
//m_dwCurDirection = GetTooltipDirection(m_tiNextTool.nDirection, &pt, &ptAnchor, m_rcTooltip, m_rcBoundsTooltip, m_rcTipArea);
MoveWindow(rect);
} //End OutputTooltipOnScreen
////////////////////////////////////////////////////////////////////
// CPPToolTip::GetTooltipDirection()
// Gets a real direction of a tooltip.
//------------------------------------------------------------------
// Parameters:
// dwDirection - A default direction of a tooltip.
// lpPoint - A mouse position in the screen coordinates.
// lpAnchor - An anchor position in the client coordinates
// rcBody - A rectangle of a tooltip's body in the client coordinates
// rcFull - A rectangle of a full tooltip in the client coordinates
// rcTipArea - A rectangle of a tooltip's info area in the client coordinates
// Return values:
// A real direction of a tooltip
//------------------------------------------------------------------
// Explanation:
// 0
// 0 +------------------------------------+
// | |
// | rcBody |
// | |
// | +------------------------------+ |
// | | | |
// | | rcTipArea | |
// | | | |
// | +------------------------------+ |
// | |
// +--+...------------------------------+
// : | / :
// : | / rcFull :
// :..|/................................:
// +- lpAnchor
//
////////////////////////////////////////////////////////////////////
DWORD CPPToolTip::GetTooltipDirection(DWORD dwDirection, const CPoint & ptPoint, CPoint & ptAnchor, CRect & rcBody, CRect & rcFull, CRect & rcTipArea)
{
//ENG: Get Window's rectangle. The whole virtual desktop .... not only the primary screen.JFN
//RUS: Получаем полный прямоугольник экрана Windows
CRect rWindow;
rWindow.left = ::GetSystemMetrics(SM_XVIRTUALSCREEN);
rWindow.top = ::GetSystemMetrics(SM_YVIRTUALSCREEN);
rWindow.right = rWindow.left + ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
rWindow.bottom = rWindow.top + ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
//-------------------------------------------
//ENG: Initializing size of the bounds rect
//RUS: Инициализация полного размера ограничивающего тултип прямоугольника
rcFull = rcBody;
switch(dwDirection)
{
case PPTOOLTIP_LEFTEDGE_TOP:
case PPTOOLTIP_LEFTEDGE_VCENTER:
case PPTOOLTIP_LEFTEDGE_BOTTOM:
rcFull.right += m_nSizes [PPTTSZ_HEIGHT_ANCHOR];
break;
case PPTOOLTIP_RIGHTEDGE_TOP:
case PPTOOLTIP_RIGHTEDGE_VCENTER:
case PPTOOLTIP_RIGHTEDGE_BOTTOM:
rcFull.right += m_nSizes [PPTTSZ_HEIGHT_ANCHOR];
break;
case PPTOOLTIP_BOTTOMEDGE_LEFT:
case PPTOOLTIP_BOTTOMEDGE_CENTER:
case PPTOOLTIP_BOTTOMEDGE_RIGHT:
rcFull.bottom += m_nSizes [PPTTSZ_HEIGHT_ANCHOR];
break;
case PPTOOLTIP_TOPEDGE_LEFT:
case PPTOOLTIP_TOPEDGE_CENTER:
case PPTOOLTIP_TOPEDGE_RIGHT:
rcFull.bottom += m_nSizes [PPTTSZ_HEIGHT_ANCHOR];
break;
} //switch
//---------------------------------------------------
//ENG: If needed change a horizontal direction
//RUS: Проверка горизонтальных размеров на попадание в экран
CPoint pt(ptPoint);
switch(dwDirection)
{
case PPTOOLTIP_LEFTEDGE_TOP:
case PPTOOLTIP_LEFTEDGE_VCENTER:
case PPTOOLTIP_LEFTEDGE_BOTTOM:
pt.x += rcFull.right;
if (pt.x > rWindow.right)
dwDirection ^= 0x10;
break;
case PPTOOLTIP_RIGHTEDGE_TOP:
case PPTOOLTIP_RIGHTEDGE_VCENTER:
case PPTOOLTIP_RIGHTEDGE_BOTTOM:
pt.x -= rcFull.right;
if (pt.x < rWindow.left)
dwDirection ^= 0x10;
break;
case PPTOOLTIP_BOTTOMEDGE_LEFT:
case PPTOOLTIP_TOPEDGE_LEFT:
pt.x += rcFull.right;
pt.x -= m_nSizes [PPTTSZ_MARGIN_ANCHOR];
if (pt.x > rWindow.right)
{
pt.x = ptPoint.x - rcFull.right;
pt.x += m_nSizes [PPTTSZ_MARGIN_ANCHOR];
if (pt.x < rWindow.left)
dwDirection |= 0x02;
else
dwDirection ^= 0x01;
} //if
break;
case PPTOOLTIP_BOTTOMEDGE_RIGHT:
case PPTOOLTIP_TOPEDGE_RIGHT:
pt.x -= rcFull.right;
pt.x += m_nSizes [PPTTSZ_MARGIN_ANCHOR];
if (pt.x < rWindow.left)
{
pt.x = ptPoint.x + rcFull.right;
pt.x -= m_nSizes [PPTTSZ_MARGIN_ANCHOR];
if (pt.x > rWindow.right)
dwDirection ^= 0x03;
else
dwDirection ^= 0x01;
} //if
break;
case PPTOOLTIP_BOTTOMEDGE_CENTER:
case PPTOOLTIP_TOPEDGE_CENTER:
if ((ptPoint.x - rWindow.left) <= m_nSizes [PPTTSZ_MARGIN_ANCHOR])
dwDirection ^= 0x02;
else if ((rWindow.right - ptPoint.x) <= m_nSizes [PPTTSZ_MARGIN_ANCHOR])
dwDirection ^= 0x03;
break;
} //switch
//---------------------------------------------------
//ENG: If needed change a vertical direction
//RUS: Проверка вертикальных размеров на попадание в экран
switch(dwDirection)
{
case PPTOOLTIP_LEFTEDGE_TOP:
case PPTOOLTIP_RIGHTEDGE_TOP:
pt.y += rcFull.bottom;
pt.y -= m_nSizes [PPTTSZ_MARGIN_ANCHOR];
if (pt.y > rWindow.bottom)
{
pt.y = ptPoint.y - rcFull.bottom;
pt.y += m_nSizes [PPTTSZ_MARGIN_ANCHOR];
if (pt.y < rWindow.top)
dwDirection |= 0x02;
else
dwDirection ^= 0x01;
} //if
break;
case PPTOOLTIP_LEFTEDGE_BOTTOM:
case PPTOOLTIP_RIGHTEDGE_BOTTOM:
pt.y -= rcFull.bottom;
pt.y += m_nSizes [PPTTSZ_MARGIN_ANCHOR];
if (pt.y < rWindow.top)
{
pt.y = ptPoint.y + rcFull.bottom;
pt.y -= m_nSizes [PPTTSZ_MARGIN_ANCHOR];
if (pt.y > rWindow.bottom)
dwDirection ^= 0x03;
else
dwDirection ^= 0x01;
} //if
break;
case PPTOOLTIP_LEFTEDGE_VCENTER:
case PPTOOLTIP_RIGHTEDGE_VCENTER:
if ((ptPoint.y - rWindow.top) <= m_nSizes [PPTTSZ_MARGIN_ANCHOR])
dwDirection ^= 0x02;
else if ((rWindow.bottom - ptPoint.y) <= m_nSizes [PPTTSZ_MARGIN_ANCHOR])
dwDirection ^= 0x03;
break;
case PPTOOLTIP_BOTTOMEDGE_LEFT:
case PPTOOLTIP_BOTTOMEDGE_CENTER:
case PPTOOLTIP_BOTTOMEDGE_RIGHT:
pt.y -= rcFull.bottom;
if (pt.y < rWindow.top)
dwDirection ^= 0x10;
break;
case PPTOOLTIP_TOPEDGE_LEFT:
case PPTOOLTIP_TOPEDGE_CENTER:
case PPTOOLTIP_TOPEDGE_RIGHT:
pt.y += rcFull.bottom;
if (pt.y > rWindow.bottom)
dwDirection ^= 0x10;
break;
} //switch
//---------------------------------------------------
//ENG: Set the anchor's point
//RUS: Установка координаты кончика
switch(dwDirection)
{
case PPTOOLTIP_LEFTEDGE_TOP:
case PPTOOLTIP_LEFTEDGE_VCENTER:
case PPTOOLTIP_LEFTEDGE_BOTTOM:
ptAnchor.x = rcFull.left;
break;
case PPTOOLTIP_RIGHTEDGE_TOP:
case PPTOOLTIP_RIGHTEDGE_VCENTER:
case PPTOOLTIP_RIGHTEDGE_BOTTOM:
ptAnchor.x = rcFull.right;
break;
case PPTOOLTIP_BOTTOMEDGE_LEFT:
case PPTOOLTIP_BOTTOMEDGE_CENTER:
case PPTOOLTIP_BOTTOMEDGE_RIGHT:
ptAnchor.y = rcFull.bottom;
break;
case PPTOOLTIP_TOPEDGE_LEFT:
case PPTOOLTIP_TOPEDGE_CENTER:
case PPTOOLTIP_TOPEDGE_RIGHT:
ptAnchor.y = rcFull.top;
break;
} //switch
//
switch(dwDirection)
{
case PPTOOLTIP_LEFTEDGE_TOP:
case PPTOOLTIP_RIGHTEDGE_TOP:
ptAnchor.y = rcFull.top + m_nSizes [PPTTSZ_MARGIN_ANCHOR];
break;
case PPTOOLTIP_LEFTEDGE_BOTTOM:
case PPTOOLTIP_RIGHTEDGE_BOTTOM:
ptAnchor.y = rcFull.bottom - m_nSizes [PPTTSZ_MARGIN_ANCHOR];
break;
case PPTOOLTIP_LEFTEDGE_VCENTER:
case PPTOOLTIP_RIGHTEDGE_VCENTER:
ptAnchor.y = rcFull.bottom / 2;
if ((ptPoint.y + rcFull.bottom / 2) <= rWindow.bottom)
{
if ((ptPoint.y - rcFull.bottom / 2) < rWindow.top)
ptAnchor.y -= (rcFull.bottom / 2 - ptPoint.y + rWindow.top);
}
else if ((ptPoint.y - rcFull.bottom / 2) >= rWindow.top)
{
if ((ptPoint.y + rcFull.bottom / 2) > rWindow.bottom)
ptAnchor.y += (ptPoint.y + rcFull.bottom / 2 - rWindow.bottom);
} //if
break;
case PPTOOLTIP_BOTTOMEDGE_LEFT:
case PPTOOLTIP_TOPEDGE_LEFT:
ptAnchor.x = rcFull.left + m_nSizes [PPTTSZ_MARGIN_ANCHOR];
break;
case PPTOOLTIP_BOTTOMEDGE_RIGHT:
case PPTOOLTIP_TOPEDGE_RIGHT:
ptAnchor.x = rcFull.right - m_nSizes [PPTTSZ_MARGIN_ANCHOR];
break;
case PPTOOLTIP_BOTTOMEDGE_CENTER:
case PPTOOLTIP_TOPEDGE_CENTER:
ptAnchor.x = rcFull.right / 2;
if ((ptPoint.x + rcFull.right / 2) <= rWindow.right)
{
if ((ptPoint.x - rcFull.right / 2) < rWindow.left)
ptAnchor.x -= (rcFull.right / 2 - ptPoint.x + rWindow.left);
}
else if ((ptPoint.x - rcFull.right / 2) >= rWindow.left)
{
if ((ptPoint.x + rcFull.right / 2) > rWindow.right)
ptAnchor.x += (ptPoint.x + rcFull.right / 2 - rWindow.right);
} //if
break;
} //switch
//---------------------------------------------------
//If needed offset anchor
switch(dwDirection)
{
case PPTOOLTIP_LEFTEDGE_TOP:
case PPTOOLTIP_RIGHTEDGE_TOP:
case PPTOOLTIP_LEFTEDGE_VCENTER:
case PPTOOLTIP_RIGHTEDGE_VCENTER:
if ((ptPoint.y - ptAnchor.y) < rWindow.top)
ptAnchor.y = ptPoint.y - rWindow.top;
break;
case PPTOOLTIP_LEFTEDGE_BOTTOM:
case PPTOOLTIP_RIGHTEDGE_BOTTOM:
if ((ptPoint.y + rcFull.bottom - ptAnchor.y) > rWindow.bottom)
ptAnchor.y = rcFull.bottom - rWindow.bottom + ptPoint.y;
break;
case PPTOOLTIP_BOTTOMEDGE_LEFT:
case PPTOOLTIP_TOPEDGE_LEFT:
case PPTOOLTIP_BOTTOMEDGE_CENTER:
case PPTOOLTIP_TOPEDGE_CENTER:
if ((ptPoint.x - ptAnchor.x) < rWindow.left)
ptAnchor.x = ptPoint.x - rWindow.left;
break;
case PPTOOLTIP_BOTTOMEDGE_RIGHT:
case PPTOOLTIP_TOPEDGE_RIGHT:
if ((ptPoint.x + rcFull.right - ptAnchor.x) > rWindow.right)
ptAnchor.x = rcFull.right - rWindow.right + ptPoint.x;
break;
} //switch
//*!* I don't know why but without following lines application fails in Release mode!!!!
CString str;
str.Format("0x%08X", dwDirection);
//---------------------------------------------
// Offset the body rectangle
switch(dwDirection)
{
case PPTOOLTIP_LEFTEDGE_TOP:
case PPTOOLTIP_LEFTEDGE_VCENTER:
case PPTOOLTIP_LEFTEDGE_BOTTOM:
rcTipArea.OffsetRect(m_nSizes [PPTTSZ_HEIGHT_ANCHOR], 0);
rcBody.OffsetRect(m_nSizes [PPTTSZ_HEIGHT_ANCHOR], 0);
break;
case PPTOOLTIP_TOPEDGE_LEFT:
case PPTOOLTIP_TOPEDGE_CENTER:
case PPTOOLTIP_TOPEDGE_RIGHT:
rcTipArea.OffsetRect(0, m_nSizes [PPTTSZ_HEIGHT_ANCHOR]);
rcBody.OffsetRect(0, m_nSizes [PPTTSZ_HEIGHT_ANCHOR]);
break;
} //switch
return dwDirection;
} //End of GetTooltipDirection
HRGN CPPToolTip::GetTooltipRgn(DWORD dwDirection, int x, int y, int nWidth, int nHeight)
{
HRGN hRgn = NULL;
HRGN hrgnBody = NULL;
CRect rcBody(0, 0, nWidth, nHeight);
HRGN hrgnAnchor = NULL;
POINT ptAnchor [3];
ptAnchor [0].x = x;
ptAnchor [0].y = y;
HRGN hrgnRect = NULL;
//------------------------------
switch(dwDirection)
{
case PPTOOLTIP_LEFTEDGE_TOP:
case PPTOOLTIP_LEFTEDGE_VCENTER:
case PPTOOLTIP_LEFTEDGE_BOTTOM:
rcBody.left += m_nSizes [PPTTSZ_HEIGHT_ANCHOR];
ptAnchor [1].x = ptAnchor [2].x = rcBody.left;
break;
case PPTOOLTIP_RIGHTEDGE_TOP:
case PPTOOLTIP_RIGHTEDGE_VCENTER:
case PPTOOLTIP_RIGHTEDGE_BOTTOM:
rcBody.right -= m_nSizes [PPTTSZ_HEIGHT_ANCHOR];
ptAnchor [1].x = ptAnchor [2].x = rcBody.right;
break;
case PPTOOLTIP_TOPEDGE_LEFT:
case PPTOOLTIP_TOPEDGE_CENTER:
case PPTOOLTIP_TOPEDGE_RIGHT:
rcBody.top += m_nSizes [PPTTSZ_HEIGHT_ANCHOR];
ptAnchor [1].y = ptAnchor [2].y = rcBody.top;
break;
case PPTOOLTIP_BOTTOMEDGE_LEFT:
case PPTOOLTIP_BOTTOMEDGE_CENTER:
case PPTOOLTIP_BOTTOMEDGE_RIGHT:
rcBody.bottom -= m_nSizes [PPTTSZ_HEIGHT_ANCHOR];
ptAnchor [1].y = ptAnchor [2].y = rcBody.bottom;
break;
} //switch
//------------------------------
switch(dwDirection)
{
case PPTOOLTIP_LEFTEDGE_TOP:
case PPTOOLTIP_RIGHTEDGE_TOP:
ptAnchor [1].y = rcBody.top + m_nSizes [PPTTSZ_MARGIN_ANCHOR];
ptAnchor [2].y = ptAnchor [1].y + m_nSizes [PPTTSZ_WIDTH_ANCHOR];
break;
case PPTOOLTIP_LEFTEDGE_BOTTOM:
case PPTOOLTIP_RIGHTEDGE_BOTTOM:
ptAnchor [1].y = rcBody.bottom - m_nSizes [PPTTSZ_MARGIN_ANCHOR];
ptAnchor [2].y = ptAnchor [1].y - m_nSizes [PPTTSZ_WIDTH_ANCHOR];
break;
case PPTOOLTIP_LEFTEDGE_VCENTER:
case PPTOOLTIP_RIGHTEDGE_VCENTER:
ptAnchor [1].y = ptAnchor [0].y - m_nSizes [PPTTSZ_WIDTH_ANCHOR] / 2;
// ptAnchor [1].y = rcBody.top + (rcBody.Height() - m_nSizes [PPTTSZ_WIDTH_ANCHOR]) / 2;
ptAnchor [2].y = ptAnchor [1].y + m_nSizes [PPTTSZ_WIDTH_ANCHOR];
break;
case PPTOOLTIP_TOPEDGE_LEFT:
case PPTOOLTIP_BOTTOMEDGE_LEFT:
ptAnchor [1].x = rcBody.left + m_nSizes [PPTTSZ_MARGIN_ANCHOR];
ptAnchor [2].x = ptAnchor [1].x + m_nSizes [PPTTSZ_WIDTH_ANCHOR];
break;
case PPTOOLTIP_TOPEDGE_RIGHT:
case PPTOOLTIP_BOTTOMEDGE_RIGHT:
ptAnchor [1].x = rcBody.right - m_nSizes [PPTTSZ_MARGIN_ANCHOR];
ptAnchor [2].x = ptAnchor [1].x - m_nSizes [PPTTSZ_WIDTH_ANCHOR];
break;
case PPTOOLTIP_TOPEDGE_CENTER:
case PPTOOLTIP_BOTTOMEDGE_CENTER:
ptAnchor [1].x = ptAnchor [0].x - m_nSizes [PPTTSZ_WIDTH_ANCHOR] / 2;
// ptAnchor [1].x = rcBody.left + (rcBody.Width() - m_nSizes [PPTTSZ_WIDTH_ANCHOR]) / 2;
ptAnchor [2].x = ptAnchor [1].x + m_nSizes [PPTTSZ_WIDTH_ANCHOR];
break;
} //switch
//------------------------------
//Gets the tooltip body's region
hrgnBody = ::CreateRoundRectRgn(rcBody.left, rcBody.top, rcBody.right + 1, rcBody.bottom + 1,
m_nSizes[PPTTSZ_ROUNDED_CX], m_nSizes[PPTTSZ_ROUNDED_CY]);
//Gets the tooltip anchor's region
if (m_nSizes [PPTTSZ_HEIGHT_ANCHOR] && m_nSizes [PPTTSZ_WIDTH_ANCHOR])
hrgnAnchor = ::CreatePolygonRgn(ptAnchor, 3, ALTERNATE);
else
hrgnAnchor = ::CreateRectRgn(0, 0, 0, 0);
hRgn = ::CreateRectRgn(0, 0, 0, 0);
::CombineRgn(hRgn, hrgnBody, hrgnAnchor, RGN_OR);
if (NULL != hrgnBody)
::DeleteObject(hrgnBody);
if (NULL != hrgnAnchor)
::DeleteObject(hrgnAnchor);
return hRgn;
} //End GetTooltipRgn
BOOL CPPToolTip::IsCursorOverTooltip() const
{
ASSERT(m_hParentWnd);
// Is tooltip visible?
if (!IsVisible() || !IsWindow(m_hWnd))
return FALSE;
POINT pt;
GetCursorPos(&pt);
CPPToolTip * pWnd = (CPPToolTip*)WindowFromPoint(pt);
return (pWnd == this);
}
HWND CPPToolTip::GetWndFromPoint(const LPPOINT lpPoint, PPTOOLTIP_INFO & ti, BOOL bCheckTool /* = TRUE */)
{
// the default implementation of tooltips just calls WindowFromPoint
// which does not work for certain kinds of combo boxes
CPoint pt = *lpPoint;
::ClientToScreen(m_hParentWnd, &pt);
HWND hWnd = ::WindowFromPoint(pt);
if (NULL != hWnd)
{
// try to hit combobox instead of edit control for CBS_DROPDOWN styles
HWND hWndTemp = ::GetParent(hWnd);
if (NULL != hWndTemp)
{
if (!IsComboBoxControl(hWndTemp, CBS_DROPDOWN))
{
// handle special case of disabled child windows
::ScreenToClient(hWnd, &pt);
hWndTemp = ::ChildWindowFromPoint(hWnd, pt);
if (NULL == hWndTemp)
return NULL;
if ((!::IsWindowEnabled(hWndTemp)) && bCheckTool)
return NULL;
} //if
if (FindTool(hWndTemp, &pt, ti) || !bCheckTool)
return hWndTemp;
} //if
} //if
return NULL;
} //End GetWndFromPoint
BOOL CPPToolTip::IsComboBoxControl(HWND hWnd, UINT nStyle)
{
if (hWnd == NULL)
return FALSE;
// do cheap style compare first
if ((UINT)(::GetWindowLong(hWnd, GWL_STYLE) & 0x0F) != nStyle)
return FALSE;
// do expensive classname compare next
TCHAR szCompare[9];
::GetClassName(hWnd, szCompare, 9);
return lstrcmpi(szCompare, _T("combobox")) == 0;
}
CString CPPToolTip::GetDebugInfoTool(LPPOINT lpPoint)
{
PPTOOLTIP_INFO ti;
HWND hWnd = GetWndFromPoint(lpPoint, ti, FALSE);
HWND hParent = ::GetParent (hWnd);
_TCHAR ch[128];
CString str, strTemp;
CString strOutput = _T("");
///////////////////////////////////////////////////////////////////
//Table of a window
strOutput += _T("Window");
//1. Window's class name and Window Owner's class name
::GetClassName (hWnd, ch, 128);
strOutput += CreateDebugCell(_T("Class name"), ch);
//2. Window's title and Window Owner's title
::GetWindowText (hWnd, ch, 128);
strOutput += CreateDebugCell(_T("Title"), ch);
//3. Window's handle and Window Owner's handle
str.Format(_T("0x%08X"), hWnd);
strOutput += CreateDebugCell(_T("Handle"), str);
//4. Window's ID
str.Format(_T("%d"), GetWindowLong(hWnd, GWL_ID));
strOutput += CreateDebugCell(_T("Control ID"), str);
//5. Window's styles
str.Format(_T("0x%08X"), (DWORD)::GetWindowLong (hWnd, GWL_STYLE));
strOutput += CreateDebugCell(_T("Styles"), str);
//6. Window's rect
RECT rc;
::GetWindowRect(hWnd, &rc);
str.Format(_T("(%d, %d)-(%d, %d)"), rc.left, rc.top, rc.right, rc.bottom);
strOutput += CreateDebugCell(_T("RECT"), str);
//7. Window's width
str.Format(_T("%d"), rc.right - rc.left);
strOutput += CreateDebugCell(_T("Width"), str);
//8. Window's height
str.Format(_T("%d"), rc.bottom - rc.top);
strOutput += CreateDebugCell(_T("Height"), str);
//9. Window's has tooltip
HWND hwndTool = FindTool(lpPoint, ti);
str = (NULL != hwndTool) ? _T("Yes") : _T("No");
strOutput += CreateDebugCell(_T("Has Tooltip"), str);
strOutput += _T(" | ");
///////////////////////////////////////////////////////////////////
//Table of a window owner
strOutput += _T("Window Owner");
//1. Window's class name and Window Owner's class name
if (NULL != hParent)
{
::GetClassName (hParent, ch, 128);
str = GetMaxDebugString((CString)ch);
} //if
else str = _T("N/A");
strOutput += CreateDebugCell(_T("Class name"), str);
//2. Window's title and Window Owner's title
if (NULL != hParent)
{
::GetWindowText (hParent, ch, 128);
str = GetMaxDebugString((CString)ch);
} //if
else str = _T("N/A");
strOutput += CreateDebugCell(_T("Title"), str);
//3. Window's handle and Window Owner's handle
str.Format(_T("0x%08X"), hParent);
strOutput += CreateDebugCell(_T("Handle"), str);
strOutput += _T(" ");
///////////////////////////////////////////////////////////////////
//Table of a window owner
strOutput += _T(" Mouse Cursor");
//1.
str.Format(_T("%d"), lpPoint->x);
strOutput += CreateDebugCell(_T("X"), str);
//2.
str.Format(_T("%d"), lpPoint->y);
strOutput += CreateDebugCell(_T("Y"), str);
strOutput += _T(" |
");
///////////////////////////////////////////////////////////////////////////
return strOutput;
}
CString CPPToolTip::CreateDebugCell(CString sTitle, LPCTSTR lpszDescription)
{
CString str;
str.Format(_T("| %s | %s |
"),
sTitle, GetMaxDebugString(lpszDescription));
return str;
} //End of CreateDebugCell
CString CPPToolTip::GetMaxDebugString(LPCTSTR lpszText)
{
CString str = (CString)lpszText;
str.Replace(_T("<"), _T("?")); //Replaces the begins of the tags
if (str.GetLength() > MAX_LENGTH_DEBUG_STRING)
{
str = str.Left(MAX_LENGTH_DEBUG_STRING - 4);
str += _T(" ...");
} //if
return str;
} //End of GetMaxDebugString
HWND CPPToolTip::FindTool(const LPPOINT lpPoint, PPTOOLTIP_INFO & ti)
{
return GetWndFromPoint(lpPoint, ti, TRUE);
} //End of FindTool
BOOL CPPToolTip::FindTool(HWND hWnd, const LPPOINT lpPoint, PPTOOLTIP_INFO & ti)
{
//ENG: Searching a specified HWND
//RUS: Ищем указанный HWND
mapIter item = m_ToolMap.find(hWnd);
if (item == m_ToolMap.end())
{
//ENG: Specified HWND wasn't found
//RUS: Указанный HWND не найден
return FALSE;
} //if
//ENG: Gets the array with the hotarea's parameters
//RUS: Получаем массив с параметрами горячих зон указаного окна
arHotArea & hotarea = item->second;
if ((hotarea.size() == 1) && hotarea[0].rectBounds.IsRectEmpty())
{
//ENG: If a bounding rectangle of a hotarea wasn't define
//RUS: Если ограничивающий прямоугольник горячей зоны не определен
ti = hotarea[0];
return TRUE;
} //if
POINT ptClient = *lpPoint;
if (hWnd != m_hParentWnd)
{
//ENG: If HWND specified window isn't a parent
//RUS: Если HWND не относится к родительскому окну, то преобразуем координаты
::ScreenToClient(hWnd, &ptClient);
} //if
CScrollView * pScroll = (CScrollView*)CScrollView::FromHandle(hWnd);
if (pScroll->IsKindOf(RUNTIME_CLASS(CScrollView)))
{
//ENG: If HWND of CScrollView or derived class then corrects the coordinates
//RUS: Если HWND принадлежит CScrollView или производному от него классу, то корректируем координаты
CPoint ptScroll = pScroll->GetScrollPosition();
ptClient.x += ptScroll.x;
ptClient.y += ptScroll.y;
} //if
//ENG: Search a hotarea under the mouse
//RUS: Ищем горячую зону под курсором
arHotArea::iterator iter;
for (iter = hotarea.begin(); iter != hotarea.end(); ++iter)
{
ti = *iter;
if (ti.rectBounds.PtInRect(ptClient))
{
//ENG: A hotarea was found
//RUS: Зона найдена
return TRUE;
} //if
} //for
return FALSE;
} //End of FindTool
HWND CPPToolTip::FindToolBarItem(POINT point, PPTOOLTIP_INFO & ti)
{
//ENG: Toolbar control was disabled
//RUS: Контроль за подсказками к панелям инструментов отключен
if (!m_wndToolBars.size())
return NULL;
//ENG: Gets a window under mouse
//RUS: Определяем окно под курсором
HWND hWnd = ::WindowFromPoint(point);
if (NULL != hWnd)
{
//ENG: A window was found. Searching a coincidence with toolbar windows
//RUS: Окно обнаружено. Поиск совпадения с окнами панелей инструментов
for (int i = 0; i < (int)m_wndToolBars.size(); i++)
{
if (m_wndToolBars[i] == hWnd)
{
//ENG: A toolbar under mouse
//RUS: Панель инструментов под курсором
CToolBar * pBar = (CToolBar*)CToolBar::FromHandle(hWnd);
pBar->ScreenToClient(&point);
//ENG: Gets a item's count of the toolbar
//RUS: Получаем количество элементов панели инструментов
int count = pBar->GetCount();
CRect rect;
//ENG: Searching an toolbar's item under mouse
//RUS: Поиск элемента панели инструментов находящегося под курсором
for (int i = 0; i < count; i++)
{
pBar->GetItemRect(i, rect);
if (rect.PtInRect(point))
{
//ENG: Toolbar's item was found
//RUS: Элемент панели инструментов обнаружен
ti.nIDTool = pBar->GetItemID(i);
ti.rectBounds = rect;
ti.nMask = 0;
ti.sTooltip = m_drawer.GetResCommandPrompt(ti.nIDTool, 1);
return hWnd;
} //if
} //for
return NULL;
} //if
} //for
} //if
return NULL;
} //End of FindToolBarItem
////////////////////////////////////////////////////////////////////////////////////////////
// *** public methods ***
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// CPPToolTip::AddTool()
// Registers a tool with the tooltip control.
//------------------------------------------------------------------
// Parameters:
// pWnd - Pointer to the window that contains the tool.
// lpszString - Pointer to the text for the tool.
// dwIdString - ID of string resource
// hIcon - Handle of the icon
// dwIdIcon - ID of icon resource
// szIcon - Specifies the width and the height, in pixels, of the icon to load.
// lpRectBounds - Pointer to a RECT structure containing coordinates of the tool's bounding rectangle.
// The coordinates are relative to the upper-left corner of the client area of the window identified by pWnd.
// NULL if bounding rectangle don't uses for specified window
// dwIdTool - ID of the tool
// ti - Reference to PPTOOLTIP_INFO structure containing the parameters of the tooltip
//
// Remarks:
// A tooltip control can be associated with more than one tool. Call this function to register a tool
// with the tooltip control, so that the information stored in the tooltip is displayed when the cursor is on the tool.
////////////////////////////////////////////////////////////////////
void CPPToolTip::AddTool(CWnd * pWnd, DWORD dwIdString, HICON hIcon, LPCRECT lpRectBounds /*= NULL*/, DWORD dwIDTool /*= 0*/)
{
CString str;
str.LoadString(dwIdString);
AddTool(pWnd, (LPCTSTR)str, hIcon, lpRectBounds, dwIDTool);
}
void CPPToolTip::AddTool(CWnd * pWnd, LPCTSTR lpszString, HICON hIcon, LPCRECT lpRectBounds /*= NULL*/, DWORD dwIDTool /*= 0*/)
{
CString str;
str.Format(_T(""),
hIcon, lpszString);
AddTool(pWnd, str, lpRectBounds, dwIDTool);
}
void CPPToolTip::AddTool(CWnd * pWnd, DWORD dwIdString, DWORD dwIdIcon, CSize & szIcon /* = CSize(0, 0) */, LPCRECT lpRectBounds /*= NULL*/, DWORD dwIDTool /*= 0*/)
{
CString str;
str.LoadString(dwIdString);
AddTool(pWnd, (LPCTSTR)str, dwIdIcon, szIcon, lpRectBounds, dwIDTool);
}
void CPPToolTip::AddTool(CWnd * pWnd, LPCTSTR lpszString, DWORD dwIdIcon, CSize & szIcon /* = CSize(0, 0) */, LPCRECT lpRectBounds /*= NULL*/, DWORD dwIDTool /*= 0*/)
{
CString str;
str.Format(_T(""),
dwIdIcon, szIcon.cx, szIcon.cy, lpszString);
AddTool(pWnd, str, lpRectBounds, dwIDTool);
}
void CPPToolTip::AddTool(CWnd * pWnd, LPCTSTR lpszString, DWORD dwIdBitmap, COLORREF crMask, CSize & szBitmap /*= CSize(0, 0)*/, LPCRECT lpRectBounds /*= NULL*/, DWORD dwIDTool /*= 0*/)
{
CString str;
str.Format(_T(""),
dwIdBitmap, crMask, szBitmap.cx, szBitmap.cy, lpszString);
AddTool(pWnd, str, lpRectBounds, dwIDTool);
}
void CPPToolTip::AddTool(CWnd * pWnd, DWORD dwIdString, LPCRECT lpRectBounds /* = NULL */, DWORD dwIDTool /* = 0 */)
{
CString str;
str.LoadString(dwIdString);
AddTool(pWnd, (LPCTSTR)str, lpRectBounds, dwIDTool);
}
void CPPToolTip::AddTool(CWnd * pWnd, LPCTSTR lpszString /* = NULL */, LPCRECT lpRectBounds /* = NULL */, DWORD dwIDTool /* = 0 */)
{
PPTOOLTIP_INFO ti;
ti.nIDTool = dwIDTool;
if (NULL != lpRectBounds)
ti.rectBounds = *lpRectBounds;
else
ti.rectBounds.SetRectEmpty();
ti.sTooltip = (CString)lpszString;
ti.nMask = 0;
ti.nStyles = 0;
ti.nDirection = 0;
ti.nEffect = 0;
ti.nBehaviour = 0;
ti.nGranularity = 0;
ti.crBegin = RGB(0, 0, 0);
ti.crMid = RGB(0, 0, 0);
ti.crEnd = RGB(0, 0, 0);
AddTool(pWnd, ti);
}
void CPPToolTip::AddTool(CWnd * pWnd, PPTOOLTIP_INFO & ti)
{
TRACE(_T("CPPToolTip::AddTool(hWnd=0x%08X)\n"), pWnd->GetSafeHwnd());
ASSERT (pWnd);
//ENG: Gets HWND of a window
//RUS: Получаем HWND окна
HWND hWnd = pWnd->GetSafeHwnd();
//ENG: Searching a specified HWND
//RUS: Ищем указанный HWND
mapIter item = m_ToolMap.find(hWnd);
if (item == m_ToolMap.end())
{
//ENG: A tooltip for a specified HWND wasn't found therefore create it
//RUS: Тултип для указанного HWND не обнаружен, поэтому создаем его
arHotArea hotarea;
hotarea.push_back(ti);
m_ToolMap.insert(std::make_pair(hWnd, hotarea));
return;
} //if
//ENG: Gets parameters of the tooltip
//RUS: Получаем параметры тултипа
arHotArea & hotarea = item->second;
//ENG: A tooltip has more one rectangle areas. Check all theirs
//RUS: Тултип содержит более одной прямоугольной области, проверим всех их
arHotArea::iterator iter;
for (iter = hotarea.begin(); iter != hotarea.end(); ++iter)
{
if (ti.rectBounds == (*iter).rectBounds)
{
//ENG: Specified window's rect already exist and so updates him
//RUS: Указанный прямоугольник окна уже существует, поэтому просто обновляем его параметры
*iter = ti;
return;
} //if
} //for
//ENG: Adds a new tool
//RUS: Добавляем новый инструмент
hotarea.push_back(ti);
} //End of AddTool
////////////////////////////////////////////////////////////////////
// CPPToolTip::RemoveTool()
// Removes the tool specified by pWnd and lpRectBounds from the collection of
// tools supported by a tooltip control.
//------------------------------------------------------------------
// Parameters:
// pWnd - Pointer to the window that contains the tool.
// lpRectBounds - Pointer to a RECT structure containing coordinates of the tool's bounding rectangle.
// The coordinates are relative to the upper-left corner of the client area of the window identified by pWnd.
// NULL if bounding rectangle don't uses for specified window
////////////////////////////////////////////////////////////////////
void CPPToolTip::RemoveTool(CWnd * pWnd, LPCRECT lpRectBounds /* = NULL */)
{
TRACE (_T("CPPToolTip::RemoveTool(hWnd=0x%08X)\n"), pWnd->GetSafeHwnd());
ASSERT(pWnd);
//ENG: Gets HWND of a window
//RUS: Получаем HWND окна
HWND hWnd = pWnd->GetSafeHwnd();
//ENG: Searching a specified HWND
//RUS: Ищем указанный HWND
mapIter item = m_ToolMap.find(hWnd);
if (item == m_ToolMap.end())
{
//ENG: Specified HWND wasn't found
//RUS: Указанный HWND не найден
return;
} //if
if (NULL == lpRectBounds)
{
//ENG: Removes all tools for the specified window
//RUS: Удаляются все инструменты для указанного окна
m_ToolMap.erase(item);
}
else
{
//ENG: Search the tool to remove
//RUS: Поиск инструмента для удаления
arHotArea & hotarea = item->second;
arHotArea::iterator iter;
for (iter = hotarea.begin(); iter != hotarea.end(); ++iter)
{
if ((*iter).rectBounds == *lpRectBounds)
{
//ENG: The tool was found
//RUS: Инструмент найден
if (hotarea.size() > 1)
{
//ENG: If the specified window has more one rectangle areas then removes the specified area only
//RUS: Если указанное окно содержит более одной области, то удаляем только указанную область
hotarea.erase(iter);
}
else
{
//ENG: If the specified window has one rectangle area only then removes the tool for specified window
//RUS: Если указанное окно имеет только одну прямоугольную область, то удалить весь инструмент
m_ToolMap.erase(item);
} //if
return;
} //if
} //for
} //if
} //End of RemoveTool
////////////////////////////////////////////////////////////////////
// CPPToolTip::RemoveAllTools()
// Removes all tools from the collection of tools supported by a tooltip control.
////////////////////////////////////////////////////////////////////
void CPPToolTip::RemoveAllTools()
{
TRACE (_T("CPPToolTip::RemoveAllTools()\n"));
//ENG: Removes all tools
//RUS: Удаляем все инструменты
if (m_ToolMap.size())
m_ToolMap.clear();
//ENG: Removes all toolbars
//RUS: Удаляем все панели инструментов
if (m_wndToolBars.size())
m_wndToolBars.clear();
} //End of RemoveAllTools
////////////////////////////////////////////////////////////////////
// CPPToolTip::AddToolBar()
// Registers a toolbar to the tooltip control.
//------------------------------------------------------------------
// Parameters:
// pBar - Pointer to the toolbar window.
////////////////////////////////////////////////////////////////////
void CPPToolTip::AddToolBar(CToolBar * pBar)
{
TRACE (_T("CPPToolTip::AddToolBar(hWnd=0x%08X)\n"), pBar->GetSafeHwnd());
ASSERT(pBar);
//ENG: Gets HWND toolbar's window
//RUS: Получаем HWND окна панели инструментов
HWND hWnd = pBar->GetSafeHwnd();
//ENG: Searching a clone of a toolbar
//RUS: Поиск дубликата указанной панели инструментов
arToolBarWnd::iterator iter;
for (iter = m_wndToolBars.begin(); iter != m_wndToolBars.end(); ++iter)
{
if (*iter == hWnd)
{
//ENG: A clone was found
//RUS: Дубликат найден
return;
} //if
} //for
//ENG: Stores HWND toolbar's window
//RUS: Запоминаем HWND окна панели инструментов
m_wndToolBars.push_back(hWnd);
//ENG: Disables a standard tooltip for the specified toolbar
//RUS: Запрещаем стандартные подсказки для указаной панели инструментов
DWORD dwStyles = pBar->GetBarStyle();
dwStyles &= ~CBRS_TOOLTIPS;
pBar->SetBarStyle(dwStyles);
} //End of AddToolBar
BOOL CPPToolTip::GetToolInfo(PPTOOLTIP_INFO & ti, CWnd * pWnd, LPCRECT lpRectBounds /* = NULL */)
{
ASSERT(pWnd);
//ENG: Gets HWND of a window
//RUS: Получаем HWND окна
HWND hWnd = pWnd->GetSafeHwnd();
//ENG: Searching a specified HWND
//RUS: Ищем указанный HWND
mapIter item = m_ToolMap.find(hWnd);
if (item == m_ToolMap.end())
{
//ENG: Specified HWND wasn't found
//RUS: Указанный HWND не найден
return FALSE;
} //if
//ENG: Gets parameters of the tooltip
//RUS: Получаем параметры тултипа
arHotArea & hotarea = item->second;
//ENG: A tooltip has more one rectangle areas. Check all theirs
//RUS: Тултип содержит более одной прямоугольной области, проверим всех их
arHotArea::iterator iter;
for (iter = hotarea.begin(); iter != hotarea.end(); ++iter)
{
if (lpRectBounds == (*iter).rectBounds)
{
//ENG: Specified window's rect already exist and so updates him
//RUS: Указанный прямоугольник окна уже существует, поэтому просто обновляем его параметры
ti = *iter;
return TRUE ;
} //if
} //for
return FALSE;
}
BOOL CPPToolTip::GetToolInfo(PPTOOLTIP_INFO & ti, CWnd * pWnd, DWORD dwIDTool /* = 0 */)
{
ASSERT(pWnd);
//ENG: Gets HWND of a window
//RUS: Получаем HWND окна
HWND hWnd = pWnd->GetSafeHwnd();
//ENG: Searching a specified HWND
//RUS: Ищем указанный HWND
mapIter item = m_ToolMap.find(hWnd);
if (item == m_ToolMap.end())
{
//ENG: Specified HWND wasn't found
//RUS: Указанный HWND не найден
return FALSE;
} //if
//ENG: Gets parameters of the tooltip
//RUS: Получаем параметры тултипа
arHotArea & hotarea = item->second;
arHotArea::iterator iter;
for (iter = hotarea.begin(); iter != hotarea.end(); ++iter)
{
if (dwIDTool == (*iter).nIDTool)
{
ti = *iter;
return TRUE ;
} //if
} //for
return FALSE;
}
void CPPToolTip::UpdateTipText(LPCTSTR lpszText, CWnd * pWnd, DWORD dwIDTool /* = 0 */)
{
PPTOOLTIP_INFO ti;
if (GetToolInfo(ti, pWnd, dwIDTool))
{
ti.sTooltip = lpszText;
AddTool(pWnd, ti);
}
}
void CPPToolTip::DelTool(CWnd * pWnd, DWORD dwIDTool)
{
PPTOOLTIP_INFO ti;
if (GetToolInfo(ti, pWnd, dwIDTool))
{
RemoveTool(pWnd, ti.rectBounds);
}
}
void CPPToolTip::SetToolRect(CWnd * pWnd, DWORD dwIDTool, LPCRECT lpRectBounds)
{
PPTOOLTIP_INFO ti;
if (GetToolInfo(ti, pWnd, dwIDTool))
{
ti.rectBounds = *lpRectBounds;
AddTool(pWnd, ti);
}
}
////////////////////////////////////////////////////////////////////
// CPPToolTip::EnableHyperlink()
// Enables redrawing hyperlinks and hot areas.
////////////////////////////////////////////////////////////////////
void CPPToolTip::EnableHyperlink(BOOL bEnable /* = TRUE */)
{
m_bHyperlinkEnabled = bEnable;
} //End of EnableHyperlink
////////////////////////////////////////////////////////////////////
// CPPToolTip::SetCallbackHyperlink()
// Sets the callback message that will be sent to the specified window
// if user clicks a hyperlink or hotareas with a msg parameter.
//------------------------------------------------------------------
// Parameters:
// hWnd - Handle of the window that will receive the callback message.
// Pass NULL to remove any previously specified callback message.
// nMessage - Callback message to send to window.
// lParam - A 32 bits user specified value that will be passed to the callback function.
//
// Remarks:
// The callback function must be in the form:
// LRESULT On_MenuCallback(WPARAM wParam, LPARAM lParam)
// wParam - Pointer to the string specified as parameter in tag.
// lParam - The 32 bits user specified value.
////////////////////////////////////////////////////////////////////
void CPPToolTip::SetCallbackHyperlink(HWND hWnd, UINT nMessage, LPARAM lParam /* = 0 */)
{
TRACE(_T("CPPToolTip::SetCallbackHyperlink()\n"));
m_drawer.SetCallbackHyperlink(hWnd, nMessage, lParam);
} //End of SetCallbackHyperlink
/////////////////////////////////////////////////////////////////////
// CPPToolTip::SetNotify()
// This function sets or removes the notification messages from the control before display.
//-------------------------------------------------------------------
// Parameters:
// bParentNotify - If TRUE the tooltip will be send the notification to parent window
// Else the notification will not send
// hWnd - If non-NULL the tooltip will be send the notification to specified window
// Else the notification will not send
///////////////////////////////////////////////////////////////////////
void CPPToolTip::SetNotify(BOOL bParentNotify /* = TRUE */)
{
HWND hWnd = NULL;
if (bParentNotify)
hWnd = m_hParentWnd;
SetNotify(hWnd);
} //End of SetNotify
void CPPToolTip::SetNotify(HWND hWnd)
{
TRACE(_T("CPPToolTip::SetNotify\n"));
m_hNotifyWnd = hWnd;
} //End of SetNotify
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetSize()
// Sets the specified size
//---------------------------------------------------------------------------
// Parameters :
// nSizeIndex - index of the size. This parameter can be one
// of the following values:
// PPTTSZ_ROUNDED_CX - The width of the ellipse used
// to draw the rounded corners, in logical units.
// PPTTSZ_ROUNDED_CY - The height of the ellipse used
// to draw the rounded corners, in logical units.
// PPTTSZ_MARGIN_CX - The left and right margins of the tooltip's
// text from the tooltip's edges.
// PPTTSZ_MARGIN_CY - The top and bottom margins of the tooltip's
// text from the tooltip's edges.
// PPTTSZ_WIDTH_ANCHOR - The width of the tooltip's anchor
// PPTTSZ_HEIGHT_ANCHOR - The height of the tooltip's anchor
// PPTTSZ_MARGIN_ANCHOR - The margin of the tooltip's anchor from
// his edge.
// PPTTSZ_OFFSET_ANCHOR_CX - The horizontal offset of the tooltip's anchor
// from the hot spot of a cursor
// PPTTSZ_OFFSET_ANCHOR_CY - The vertical offset of the tooltip's anchor
// from the hot spot of a cursor
// nValue - size's value
/////////////////////////////////////////////////////////////////////////////
void CPPToolTip::SetSize(int nSizeIndex, int nValue)
{
TRACE(_T("CPPToolTip::SetSize(nSizeIndex = %d, nValue = %d)\n"), nSizeIndex, nValue);
if (nSizeIndex >= PPTTSZ_MAX_SIZES)
return;
m_nSizes [nSizeIndex] = nValue;
} //End of SetSize
/////////////////////////////////////////////////////////////////////////////
// CPPTootTip::GetSize()
// Gets the specified size
//---------------------------------------------------------------------------
// Parameters :
// nSizeIndex - An index of the sizes. See CPPToolTip::SetSize for a
// description of the valid values.
// Returns :
// size's value
//
/////////////////////////////////////////////////////////////////////////////
int CPPToolTip::GetSize(int nSizeIndex)
{
TRACE(_T("CPPToolTip::GetSize(nSizeIndex = %d)\n"), nSizeIndex);
if (nSizeIndex >= PPTTSZ_MAX_SIZES)
return 0;
return m_nSizes [nSizeIndex];
} //End of GetSize
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetDefaultSizes()
// Sets all sizes to default values
//---------------------------------------------------------------------------
// Parameters:
// bBalloonSize - If TRUE all sizes will be sets for balloon tooltip
// otherwise tooltip will look as standard
/////////////////////////////////////////////////////////////////////////////
void CPPToolTip::SetDefaultSizes(BOOL bBalloonSize /* = TRUE */)
{
TRACE(_T("CPPToolTip::SetDefaultSizes()\n"));
if (bBalloonSize)
{
SetSize(PPTTSZ_ROUNDED_CX, 16);
SetSize(PPTTSZ_ROUNDED_CY, 16);
SetSize(PPTTSZ_MARGIN_CX, 12);
SetSize(PPTTSZ_MARGIN_CY, 12);
SetSize(PPTTSZ_WIDTH_ANCHOR, 12);
SetSize(PPTTSZ_HEIGHT_ANCHOR, 16);
SetSize(PPTTSZ_MARGIN_ANCHOR, 16);
SetSize(PPTTSZ_OFFSET_ANCHOR_CX, 0);
SetSize(PPTTSZ_OFFSET_ANCHOR_CY, 0);
}
else
{
SetSize(PPTTSZ_ROUNDED_CX, 0);
SetSize(PPTTSZ_ROUNDED_CY, 0);
SetSize(PPTTSZ_MARGIN_CX, 3);
SetSize(PPTTSZ_MARGIN_CY, 1);
SetSize(PPTTSZ_WIDTH_ANCHOR, 0);
SetSize(PPTTSZ_HEIGHT_ANCHOR, 0);
SetSize(PPTTSZ_MARGIN_ANCHOR, 0);
SetSize(PPTTSZ_OFFSET_ANCHOR_CX, 0);
SetSize(PPTTSZ_OFFSET_ANCHOR_CY, 0);
} //if
} //End of SetDefaultSizes
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetColorBk()
// Sets background's colors
//---------------------------------------------------------------------------
// Parameters:
// color - A solid color for background's effect
// clrBegin - A begin color for background's effect
// clrMid - A middle color for background's effect
// clrEnd - A end color for background's effect
/////////////////////////////////////////////////////////////////////////////
void CPPToolTip::SetColorBk(COLORREF color)
{
SetColorBk(color, color, color);
} //End of SetColorBk
void CPPToolTip::SetColorBk(COLORREF clrBegin, COLORREF clrEnd)
{
SetColorBk(clrBegin, clrBegin, clrEnd);
} //End of SetColorBk
void CPPToolTip::SetColorBk(COLORREF clrBegin, COLORREF clrMid, COLORREF clrEnd)
{
m_clrBeginBk = clrBegin;
m_clrMidBk = clrMid;
m_clrEndBk = clrEnd;
} //End of SetColorBk
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetEffectBk()
// Sets a background's effect
//---------------------------------------------------------------------------
// Parameters:
// dwEffect - A background's effect
// nGranularity - Adds an uniform noise to the effect.
// A good value is from 5 to 20; 0 to disable the effect.
// The noise has a positive effect because it hides the palette steps.
/////////////////////////////////////////////////////////////////////////////
void CPPToolTip::SetEffectBk(DWORD dwEffect, BYTE nGranularity /* = 5 */)
{
m_dwEffectBk = dwEffect;
m_nGranularity = nGranularity;
} //End of SetEffectBk
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetBehaviour()
// Sets a tooltip's behaviour
//---------------------------------------------------------------------------
// Parameters:
// dwBehaviour - A tooltip's behaviour. 0 for normal tooltip without
// specific behaviours. This parameter can be any combination
// of CPPToolTip behaviours:
// PPTOOLTIP_MULTIPLE_SHOW - Multiple show for single control
// PPTOOLTIP_TRACKING_MOUSE - Tracking for mouse
// PPTOOLTIP_CLOSE_LEAVEWND - Close tooltip if mouse leave the control
// PPTOOLTIP_NOCLOSE_OVER - No close tooltip if mouse over him
// PPTOOLTIP_DISABLE_AUTOPOP - Disables autopop tooltip from timer
/////////////////////////////////////////////////////////////////////////////
void CPPToolTip::SetBehaviour(DWORD dwBehaviour /* = 0 */)
{
m_dwBehaviour = dwBehaviour;
} //End of SetBehaviour
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::GetBehaviour()
// Gets a tooltip's behaviour
//---------------------------------------------------------------------------
// Return value:
// A tooltip's behaviour. See CPPToolTip::SetBehaviour for a description of the
// valid values.
/////////////////////////////////////////////////////////////////////////////
DWORD CPPToolTip::GetBehaviour()
{
return m_dwBehaviour;
} //End of GetBehaviour
/////////////////////////////////////////////////////////////////////
// CPPToolTip::SetDelayTime()
// Call this function to set the delay time for a tooltip control.
// The delay time is the length of time the cursor must remain on a tool
// before the tooltip window appears. The default delay time is 500 milliseconds.
//-------------------------------------------------------------------
// Parameters:
// dwDuration - Flag that specifies which duration value will be retrieved.
// This parameter can be one of the following values:
// PPTOOLTIP_TIME_AUTOPOP - Retrieve the length of time the tooltip
// window remains visible if the pointer is
// stationary within a tool's bounding rectangle.
// PPTOOLTIP_TIME_INITIAL - Retrieve the length of time the pointer
// must remain stationary within a tool's bounding
// rectangle before the tool tip window appears.
// PPTOOLTIP_TIME_FADEIN - Retrieve the length of time for each step of
// fade-in effect
// PPTOOLTIP_TIME_FADEOUT - Retrieve the length of time for each step of
// fade-out effect
// PPTOOLTIP_TIME_ANIMATION Retrieve the speed for the animation
// For compatibility with 1.x versions of CPPToolTip a following values
// are available also:
// TTDT_AUTOPOP - Same PPTOOLTIP_TIME_AUTOPOP
// TTDT_INITIAL - Same PPTOOLTIP_TIME_INITIAL
// nTime - The specified delay time, in milliseconds.
/////////////////////////////////////////////////////////////////////
void CPPToolTip::SetDelayTime(DWORD dwDuration, DWORD dwTime)
{
switch (dwDuration)
{
case PPTOOLTIP_TIME_AUTOPOP:
m_dwTimeAutoPop = dwTime;
break;
case PPTOOLTIP_TIME_INITIAL:
m_dwTimeInitial = dwTime;
break;
case PPTOOLTIP_TIME_FADEIN:
m_dwTimeFadeIn = dwTime;
break;
case PPTOOLTIP_TIME_FADEOUT:
m_dwTimeFadeOut = dwTime;
break;
case PPTOOLTIP_TIME_ANIMATION:
KillTimer(TIMER_ANIMATION);
if (dwTime)
SetTimer(TIMER_ANIMATION, dwTime, NULL);
break;
}
} //End of SetDelayTime
/////////////////////////////////////////////////////////////////////
// CPPToolTip::GetDelayTime()
// Retrieves the initial, pop-up, and reshow durations currently set
// for a CPPToolTip control
//-------------------------------------------------------------------
// Parameters:
// dwDuration - Flag that specifies which duration value will be retrieved.
// See CPPToolTip::SetDelayTime for a description of the valid values.
// Return value:
// The specified delay time, in milliseconds
///////////////////////////////////////////////////////////////////////
DWORD CPPToolTip::GetDelayTime(DWORD dwDuration) const
{
DWORD dwTime = 0;
switch (dwDuration)
{
case PPTOOLTIP_TIME_AUTOPOP:
dwTime = m_dwTimeAutoPop;
break;
case PPTOOLTIP_TIME_INITIAL:
dwTime = m_dwTimeInitial;
break;
case PPTOOLTIP_TIME_FADEIN:
dwTime = m_dwTimeFadeIn;
break;
case PPTOOLTIP_TIME_FADEOUT:
dwTime = m_dwTimeFadeOut;
break;
}
return dwTime;
} //End of GetDelayTime
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetDirection()
// Sets a placement of the tooltip's anchor
//---------------------------------------------------------------------------
// Parameters :
// dwDirection - A placement of the tooltip's anchor. This parameter
// can be one of the following values:
// PPTOOLTIP_TOPEDGE_LEFT - A left corner of the top edge
// PPTOOLTIP_TOPEDGE_RIGHT - A right corner of the top edge
// PPTOOLTIP_TOPEDGE_CENTER - By center of the top edge
// PPTOOLTIP_BOTTOMEDGE_LEFT - A left corner of the bottom edge
// PPTOOLTIP_BOTTOMEDGE_RIGHT - A right corner of the bottom edge
// PPTOOLTIP_BOTTOMEDGE_CENTER - By center of the bottom edge
// PPTOOLTIP_LEFTEDGE_TOP - A top corner of the left edge
// PPTOOLTIP_LEFTEDGE_BOTTOM - A bottom corner of the left edge
// PPTOOLTIP_LEFTEDGE_VCENTER - By center of the left edge
// PPTOOLTIP_RIGHTEDGE_TOP - A top corner of the right edge
// PPTOOLTIP_RIGHTEDGE_BOTTOM - A bottom corner of the right edge
// PPTOOLTIP_RIGHTEDGE_VCENTER - By center of the right edge
// For compatibility with 1.x versions of CPPToolTip a following values
// are available also:
// PPTOOLTIP_LEFT_TOP - Same PPTOOLTIP_TOPEDGE_LEFT
// PPTOOLTIP_RIGHT_TOP - Same PPTOOLTIP_TOPEDGE_RIGHT
// PPTOOLTIP_LEFT_BOTTOM - Same PPTOOLTIP_BOTTOMEDGE_LEFT
// PPTOOLTIP_RIGHT_BOTTOM - Same PPTOOLTIP_BOTTOMEDGE_RIGHT
/////////////////////////////////////////////////////////////////////////////
void CPPToolTip::SetDirection(DWORD dwDirection /* = PPTOOLTIP_BOTTOMEDGE_LEFT */)
{
TRACE(_T("CPPToolTip::SetDirection(nDirection = %d)\n"), dwDirection);
m_dwDirection = dwDirection;
} //End of SetDirection
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::GetDirection()
// Gets a placement of the tooltip's anchor
//---------------------------------------------------------------------------
// Returns :
// A placement of the tooltip's anchor. See CPPToolTip::SetDirection for a description of
// the valid values.
/////////////////////////////////////////////////////////////////////////////
DWORD CPPToolTip::GetDirection()
{
TRACE(_T("CPPToolTip::GetDirection()\n"));
return m_dwDirection;
} //End of GetDirection
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetTextStyles()
// Applies a CSS-like style for the tooltip's HTML
//---------------------------------------------------------------------------
// Parameters:
// lpszStyleName - Pointer to a null-terminated string that specifies
// a name of CSS style
// lpszStyleValue - Pointer to a null-terminated string that specifies
// CSS-lite style for drawing a tooltip text.
/////////////////////////////////////////////////////////////////////////////
void CPPToolTip::SetTextStyle(LPCTSTR lpszStyleName, LPCTSTR lpszStyleValue)
{
m_drawer.SetTextStyle(lpszStyleName, lpszStyleValue);
}
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetCssStyles()
// Applies a CSS-like styles for the tooltip's HTML
//---------------------------------------------------------------------------
// Parameters:
// lpszCssStyles - Pointer to a null-terminated string that specifies
// CSS-lite styles for drawing a tooltip text.
/////////////////////////////////////////////////////////////////////////////
void CPPToolTip::SetCssStyles(LPCTSTR lpszCssStyles /* = NULL */)
{
m_drawer.SetCssStyles(lpszCssStyles);
} //End of SetCssStyles
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetCssStyles()
// Applies a CSS-like styles for the tooltip's HTML
//---------------------------------------------------------------------------
// Parameters:
// dwIdCssStyle - ID of string resource
// lpszPathDll -
/////////////////////////////////////////////////////////////////////////////
void CPPToolTip::SetCssStyles(DWORD dwIdCssStyle, LPCTSTR lpszPathDll /* = NULL */)
{
m_drawer.SetCssStyles(dwIdCssStyle, lpszPathDll);
} //End of SetCssStyles
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::GetCssStyles()
// Applies a CSS-like styles for the tooltip's HTML
//---------------------------------------------------------------------------
// Return value:
// Pointer to a null-terminated string that specifies CSS-lite styles
// for drawing a tooltip text.
/////////////////////////////////////////////////////////////////////////////
LPCTSTR CPPToolTip::GetCssStyles()
{
return m_drawer.GetCssStyles();
} //End of GetCssStyles
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetDebugMode()
// Sets a debug mode. In this mode tooltip will display for any control
// and will contain debug info about control.
//---------------------------------------------------------------------------
// Parameters:
// bDebug - TRUE set a debug mode.
/////////////////////////////////////////////////////////////////////////////
void CPPToolTip::SetDebugMode(BOOL bDebug /* = TRUE */)
{
m_bDebugMode = bDebug;
} //End of SetDebugMode
////////////////////////////////////////////////////////////////////
// CPPToolTip::ShowHelpTooltip()
// Shows the help tooltip in any place of screen.
//------------------------------------------------------------------
// Parameters:
// pt - Pointer to a POINT structure that receives the screen coordinates of the tooltip's anchor
// lpszString - Pointer to the text for the help tooltip.
// dwIdString - ID of string resource
// hIcon - Handle of the icon
// dwIdIcon - ID of icon resource
// szIcon - Specifies the width and the height, in pixels, of the icon to load.
// ti - Reference to PPTOOLTIP_INFO structure containing the parameters of the tooltip
////////////////////////////////////////////////////////////////////
void CPPToolTip::ShowHelpTooltip(LPPOINT pt, DWORD dwIdText, HICON hIcon /* = NULL */)
{
CString str;
str.LoadString(dwIdText);
ShowHelpTooltip(pt, (LPCTSTR)str, hIcon);
} //End ShowHelpTooltip
void CPPToolTip::ShowHelpTooltip(LPPOINT pt, DWORD dwIdText, DWORD dwIdIcon, CSize & szIcon /* = CSize(0, 0) */)
{
CString str;
str.LoadString(dwIdText);
ShowHelpTooltip(pt, (LPCTSTR)str, dwIdIcon, szIcon);
} //End ShowHelpTooltip
void CPPToolTip::ShowHelpTooltip(LPPOINT pt, LPCTSTR lpszString, HICON hIcon /* = NULL */)
{
PPTOOLTIP_INFO ti;
if (NULL == hIcon)
{
ti.sTooltip = (CString)lpszString;
}
else
{
ti.sTooltip.Format(_T(""),
hIcon, lpszString);
} //if
ti.nMask = 0;
ShowHelpTooltip(pt, ti);
} //End ShowHelpTooltip
void CPPToolTip::ShowHelpTooltip(LPPOINT pt, LPCTSTR lpszString, DWORD dwIdIcon, CSize & szIcon /* = CSize(0, 0) */)
{
CString str;
str.Format(_T(""),
dwIdIcon, szIcon.cx, szIcon.cy, lpszString);
ShowHelpTooltip(pt, (LPCTSTR)str);
} //End ShowHelpTooltip
void CPPToolTip::ShowHelpTooltip(LPPOINT pt, PPTOOLTIP_INFO & ti)
{
TRACE(_T("CPPToolTip::ShowHelpTooltip\n"));
m_ptOriginal = CPoint(pt->x, pt->y);
ti.nBehaviour = m_dwBehaviour | PPTOOLTIP_DISABLE_AUTOPOP;
ti.nMask = PPTOOLTIP_MASK_BEHAVIOUR;
SetNewTooltip(NULL, ti, FALSE, PPTOOLTIP_HELP);
} //End ShowHelpTooltip
////////////////////////////////////////////////////////////////////
// CPPToolTip::SetBorder()
// Sets a border of the tooltip.
//------------------------------------------------------------------
// Parameters:
// color - Color of the tooltip's border
// hbr - Brush for drawing tooltip's border
// nWidth - A width of the brush
// nHeight - A height of the brush
////////////////////////////////////////////////////////////////////
void CPPToolTip::SetBorder(COLORREF color, int nWidth /* = 1 */, int nHeight /* = 1 */)
{
HBRUSH hbr = ::CreateSolidBrush(color);
SetBorder(hbr, nWidth, nHeight);
} //End of SetBorder
void CPPToolTip::SetBorder(HBRUSH hbr, int nWidth /* = 1 */, int nHeight /* = 1 */)
{
HideBorder();
if (nWidth && nHeight && (NULL != hbr))
{
m_hbrBorder = hbr;
m_szBorder.cx = nWidth;
m_szBorder.cy = nHeight;
} //if
} //End of SetBorder
////////////////////////////////////////////////////////////////////
// CPPToolTip::HideBorder()
// Hides border of the tooltip.
////////////////////////////////////////////////////////////////////
void CPPToolTip::HideBorder()
{
if (NULL != m_hbrBorder)
{
::DeleteObject(m_hbrBorder);
m_hbrBorder = NULL;
} //if
m_szBorder.cx = 0;
m_szBorder.cy = 0;
} //End of HideBorder
////////////////////////////////////////////////////////////////////////////////
// Begin of the menu methods block. Build-in support for menu
#ifdef PPTOOLTIP_USE_MENU
//////////////////
// Need to handle WM_ENTERIDLE to cancel the tip if the user
// moved the mouse off the popup menu. For main menus, Windows
// will send a WM_MENUSELECT message for the parent menu when
// this happens, but for context menus there's no other way to
// know the user moved the mouse off the menu.
//
void CPPToolTip::OnEnterIdle(UINT nWhy, CWnd* pWho)
{
if ((MSGF_MENU == nWhy))
{
if (m_nTooltipType == PPTOOLTIP_MENU)
{
if (PPTOOLTIP_STATE_SHOWN == m_nTooltipState)
{
CPoint pt;
GetCursorPos(&pt);
if (pWho->GetSafeHwnd() != ::WindowFromPoint(pt))
{
HideTooltip();
} //if
} //if
} //if
} //if
} //End of OnEnterIdle
void CPPToolTip::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSubMenu)
{
if (((nFlags & 0xFFFF) == 0xFFFF) || (nFlags & MF_POPUP) || (nFlags & MF_SEPARATOR))
{
//HideTooltip();
Pop();
}
else if (nItemID && hSubMenu)
{
HWND hwndMenu = GetRunningMenuWnd(); //CWnd::WindowFromPoint(pt);
if (NULL != hwndMenu)
{
CRect rcMenu;
::GetWindowRect(hwndMenu, rcMenu); // whole menu rect
// find Item Rectangle and position
int count = ::GetMenuItemCount(hSubMenu);
int cy = rcMenu.top + GetSystemMetrics(SM_CYEDGE) + 1;
for(int nItem = 0; nItem < count; nItem++)
{
CRect rect;
::GetMenuItemRect(m_hParentWnd, hSubMenu, nItem, &rect);
if(nItemID == ::GetMenuItemID(hSubMenu, nItem))
{
UINT nState = GetMenuState(hSubMenu, nItemID, MF_BYCOMMAND);
CString str;
if (MF_DISABLED & nState)
str = m_drawer.GetResCommandPrompt(nItemID, 2); //String for disabled item
else
str = m_drawer.GetResCommandPrompt(nItemID, 0);
CPoint pt;
// found menu item: adjust rectangle to right and down
pt.x = rcMenu.left;
pt.y = cy;
if (m_dwMenuToolPos & PPTOOLTIP_MENU_CENTER)
pt.x += rect.Width() / 2;
else if (m_dwMenuToolPos & PPTOOLTIP_MENU_RIGHT)
pt.x += rect.Width();
if (m_dwMenuToolPos & PPTOOLTIP_MENU_VCENTER)
pt.y += rect.Height() / 2;
else if (m_dwMenuToolPos & PPTOOLTIP_MENU_BOTTOM)
pt.y += rect.Height();
PPTOOLTIP_INFO ti;
ti.rectBounds = rect;
ti.nMask = 0;
ti.sTooltip = str;
m_nNextTooltipType = PPTOOLTIP_MENU;
m_ptOriginal = pt;
SetNewTooltip(hwndMenu, ti, TRUE, PPTOOLTIP_MENU);
return;
} //if
cy += rect.Height(); // add height
} //for
} //if
//ENG: Menu item was not found
//RUS: Элемент меню не найден.
Pop();
} //if
} //End of OnMenuSelect
////////////////////////////////////////////////////////////////////
// CPPToolTip::GetRunningMenuWnd()
// Get running menu window.
////////////////////////////////////////////////////////////////////
HWND CPPToolTip::GetRunningMenuWnd()
{
HWND hwnd = NULL;
EnumWindows(MyEnumProc,(LPARAM)&hwnd);
return hwnd;
} //End of GetRunningMenuWnd
////////////////////////////////////////////////////////////////////
// CPPToolTip::MenuToolPosition()
// Sets a position of the tooltip's anchor about menu item.
//------------------------------------------------------------------
// Parameters:
// nPos - A tooltip's position. This parameter can be any combination
// of single horizontal value and single vertical value of CPPToolTip:
// --- Horizontal position ---
// PPTOOLTIP_MENU_LEFT 0x00
// PPTOOLTIP_MENU_RIGHT 0x01
// PPTOOLTIP_MENU_CENTER 0x02
// --- Vertical position ---
// PPTOOLTIP_MENU_TOP 0x00
// PPTOOLTIP_MENU_BOTTOM 0x10
// PPTOOLTIP_MENU_VCENTER 0x20
////////////////////////////////////////////////////////////////////
void CPPToolTip::MenuToolPosition(DWORD nPos /* = PPTOOLTIP_MENU_LEFT | PPTOOLTIP_MENU_TOP */)
{
m_dwMenuToolPos = nPos;
} //End of MenuToolPosition
// End of menu methods block
///////////////////////////////////////////////////////////
#endif //PPTOOLTIP_USE_MENU
////////////////////////////////////////////////////////////////////
// CPPToolTip::EnableEscapeSequences()
// Enables the escape sequences. If the escape sequences was disabled
// HTML-lite compiler will ignore the codes less then 0x20 (such \n, \r, \t).
////////////////////////////////////////////////////////////////////
void CPPToolTip::EnableEscapeSequences(BOOL bEnable)
{
m_drawer.EnableEscapeSequences(bEnable);
} //End of EnableEscapeSequences
////////////////////////////////////////////////////////////////////
// CPPToolTip::SetImageList()
// Sets an image list for using it into the HTML string with tag.
//------------------------------------------------------------------
// Parameters:
// nIdBitmap - Resource IDs of the bitmap to be associated with the image list.
// hBitmap - Handle of the bitmap to be associated with the image list.
// cx - Dimensions of each image, in pixels.
// cy - Dimensions of each image, in pixels.
// nCount - The number of images in the image list
// crMask - Color used to generate a mask. Each pixel of this color in
// the specified bitmap is changed to transparent, and the
// corresponding bit in the mask is set to one.
////////////////////////////////////////////////////////////////////
void CPPToolTip::SetImageList(UINT nIdBitmap, int cx, int cy, int nCount, COLORREF crMask /* = RGB(255, 0, 255) */)
{
m_drawer.SetImageList(nIdBitmap, cx, cy, nCount, crMask);
} //End of SetImageList
void CPPToolTip::SetImageList(HBITMAP hBitmap, int cx, int cy, int nCount, COLORREF crMask /* = RGB(255, 0, 255) */)
{
m_drawer.SetImageList(hBitmap, cx, cy, nCount, crMask);
} //End of SetImageList
////////////////////////////////////////////////////////////////////
// CPPToolTip::SetTransparency()
// Sets a transparency of the tooltip.
//------------------------------------------------------------------
// Parameters:
// nTransparency - A transparency value to be used on the tooltip.
// The default 0 assumes that your tooltip is opaque and 0xFF (255)
// for full transparency of the tooltip.
////////////////////////////////////////////////////////////////////
void CPPToolTip::SetTransparency(BYTE nTransparency /* = 0 */)
{
if (nTransparency <= PERCENT_MAX_TRANSPARENCY)
m_nTransparency = nTransparency;
} //End of SetTransparency
////////////////////////////////////////////////////////////////////
// CPPToolTip::SetTooltipShadow()
// Sets a tooltip's shadow.
//------------------------------------------------------------------
// Parameters:
// nOffsetX,
// nOffsetY - The offsets of the tooltip's shadow from the tooltip's window.
// nDarkenPercent - So far as colors under the shadow will be darken (0 - 100)
// bGradient - TRUE to use a gradient shadow.
// nDepthX,
// nDepthY - The gradient depths of the tooltip's shadow.
////////////////////////////////////////////////////////////////////
void CPPToolTip::SetTooltipShadow(int nOffsetX, int nOffsetY, BYTE nDarkenPercent /* = 50 */,
BOOL bGradient /* = TRUE */, int nDepthX /* = 7 */, int nDepthY /* = 7 */)
{
m_szOffsetShadow.cx = nOffsetX;
m_szOffsetShadow.cy = nOffsetY;
m_szDepthShadow.cx = nDepthX;
m_szDepthShadow.cy = nDepthY;
m_nDarkenShadow = min(100, nDarkenPercent);
m_bGradientShadow = bGradient;
} //End of SetTooltipShadow
void CPPToolTip::SetImageShadow(int nOffsetX, int nOffsetY, BYTE nDarkenPercent /* = 50 */,
BOOL bGradient /* = TRUE */, int nDepthX /* = 7 */, int nDepthY /* = 7 */)
{
m_drawer.SetImageShadow(nOffsetX, nOffsetY, nDarkenPercent, bGradient, nDepthX, nDepthY);
} //End of SetImageShadow