You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2267 lines
55 KiB
C++

2 years ago
// XTPToolTipContext.cpp: implementation of the CXTPToolTipContext class.
//
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#if _MSC_VER < 1200
#define _XTP_EXCLUDE_HTML
#else
#include <mshtml.h>
#include <mshtmhst.h>
#endif // !_MSC_VER < 1200
#include "XTPToolTipContext.h"
#include "XTPVC80Helpers.h"
#include "XTPDrawHelpers.h"
#include "XTPColorManager.h"
#include "XTPImageManager.h"
#include "XTPResourceImage.h"
#include "XTPSystemHelpers.h"
#include "XTPRichRender.h"
#include "XTPResourceManager.h"
#include "XTPMarkupRender.h"
#ifdef _INC_COMDEF
// Warning "ComDef.h" was included
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
#pragma warning (disable : 4097) // typedef-name 'CXTPToolTipContextTipOfficeCtrl' used as synonym for class-name 'CRichEditToolTip'
#define WM_SYSKEYFIRST WM_SYSKEYDOWN
#define WM_SYSKEYLAST WM_SYSDEADCHAR
#define VERSION_IE5 MAKELONG(80, 5)
#define TTS_NOANIMATE 0x10
#define TTS_NOFADE 0x20
#define TTS_BALLOON 0x40
#define CS_DROPSHADOW 0x00020000
#ifndef TTM_SETTITLE
#define TTM_SETTITLEA (WM_USER + 32) // wParam = TTI_*, lParam = char* szTitle
#define TTM_SETTITLEW (WM_USER + 33) // wParam = TTI_*, lParam = wchar* szTitle
#ifdef UNICODE
#define TTM_SETTITLE TTM_SETTITLEW
#else
#define TTM_SETTITLE TTM_SETTITLEA
#endif
#endif
#ifndef WF_TRACKINGTOOLTIPS
#define WF_TRACKINGTOOLTIPS 0x0400
#endif
#define SAFE_DELETEWINDOW(ptr) \
if (ptr) { ptr->DestroyWindow(); delete ptr; ptr = NULL; }
CXTPToolTipContext* CXTPToolTipContext::m_pModuleContext = 0;
IMPLEMENT_DYNAMIC(CXTPToolTipContextToolTip, CWnd)
void XTPStripEllipsis(LPTSTR lpszText)
{
if (lpszText == NULL || lpszText == LPSTR_TEXTCALLBACK)
return;
int len = (int)_tcslen(lpszText);
if (len > 3)
{
for (int i = len - 3; i < len; i++)
{
if (lpszText[i] != _T('.'))
return;
}
lpszText[len - 3] = 0;
}
};
//////////////////////////////////////////////////////////////////////////
// CXTPToolTipContextToolTip
CXTPToolTipContextToolTip::CXTPToolTipContextToolTip(CXTPToolTipContext* pContext)
: m_pContext(pContext)
{
m_bActive = FALSE;
m_toolVisible.Reset();
m_toolDisabled.Reset();
m_toolDelay.Reset();
m_pIcon = NULL;
m_bWindowRegion = FALSE;
m_nDelayTimer = 0;
m_nAutoPopTimer = 0;
m_dwLastTip = 0;
m_nDelayInitial = 500;
m_nDelayReshow = 200;
m_nDelayAutoPop = 0;
}
void CXTPToolTipContext::SetFont(CFont* pFont)
{
LOGFONT lf;
pFont->GetLogFont(&lf);
SetFontIndirect(&lf);
}
void CXTPToolTipContext::SetFontIndirect(LOGFONT* lpLogFont)
{
if (!lpLogFont)
return;
lpLogFont->lfWeight = FW_NORMAL;
m_fnt.DeleteObject();
m_fnt.CreateFontIndirect(lpLogFont);
lpLogFont->lfWeight = FW_BOLD;
m_fntTitle.DeleteObject();
m_fntTitle.CreateFontIndirect(lpLogFont);
if (m_pToolTip) m_pToolTip->DestroyWindow();
}
CXTPToolTipContextToolTip::~CXTPToolTipContextToolTip()
{
for (int i = 0; i < (int)m_arrTools.GetSize(); i++)
{
delete m_arrTools[i];
}
m_arrTools.RemoveAll();
HookMouseMove(FALSE);
}
BEGIN_MESSAGE_MAP(CXTPToolTipContextToolTip, CWnd)
//{{AFX_MSG_MAP(CXTPToolTipContextToolTip)
ON_MESSAGE(TTM_ADDTOOL, OnAddTool)
ON_MESSAGE(TTM_ACTIVATE, OnActivate)
ON_MESSAGE(TTM_DELTOOL, OnDelTool)
ON_MESSAGE(TTM_RELAYEVENT, OnRelayEvent)
ON_MESSAGE(TTM_SETTITLE, OnSetTitle)
ON_MESSAGE(TTM_UPDATETIPTEXT, OnUpdateTipText)
ON_MESSAGE(TTM_SETDELAYTIME, OnSetDelayTime)
ON_MESSAGE(XTP_TTM_SETIMAGE, OnSetImage)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_NCHITTEST_EX()
ON_WM_MOUSEACTIVATE()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_WM_DESTROY()
ON_MESSAGE(TTM_WINDOWFROMPOINT, OnWindowFromPoint)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CXTPToolTipContextToolTip message handlers
BOOL CXTPToolTipContextToolTip::Create(CWnd* pParentWnd, DWORD dwStyle)
{
UINT nClassStyle = (dwStyle & XTP_TTS_NOSHADOW ? 0 : CS_DROPSHADOW) | CS_SAVEBITS | CS_OWNDC;
if ((nClassStyle & CS_DROPSHADOW) && !XTPSystemVersion()->IsWinXPOrGreater()) // Windows XP only
{
nClassStyle &= ~CS_DROPSHADOW;
}
BOOL bResult = CWnd::CreateEx(WS_EX_TOOLWINDOW, AfxRegisterWndClass(nClassStyle, AfxGetApp()->LoadStandardCursor(IDC_ARROW)), NULL,
WS_POPUP | dwStyle, // force WS_POPUP
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
pParentWnd->GetSafeHwnd(), NULL, NULL);
if (bResult)
SetOwner(pParentWnd);
return bResult;
}
void CXTPToolTipContextToolTip::OnDestroy()
{
m_toolVisible.Reset();
m_toolDisabled.Reset();
m_toolDelay.Reset();
for (int i = 0; i < (int)m_arrTools.GetSize(); i++)
{
delete m_arrTools[i];
}
m_arrTools.RemoveAll();
m_strTitle.Empty();
m_pIcon = NULL;
Activate(FALSE);
HookMouseMove(FALSE);
CWnd::OnDestroy();
}
LRESULT CXTPToolTipContextToolTip::OnSetImage(WPARAM, LPARAM lParam)
{
m_pIcon = (CXTPImageManagerIcon*)lParam;
return 0;
}
LRESULT CXTPToolTipContextToolTip::OnSetTitle(WPARAM, LPARAM lParam)
{
m_strTitle = (LPCTSTR)lParam;
return 0;
}
LRESULT CXTPToolTipContextToolTip::OnSetDelayTime(WPARAM dwDuration, LPARAM lParam)
{
UINT iTime = LOWORD(lParam);
switch (dwDuration)
{
case TTDT_RESHOW:
m_nDelayReshow = iTime;
break;
case TTDT_INITIAL:
m_nDelayInitial = iTime;
break;
case TTDT_AUTOPOP:
m_nDelayAutoPop = iTime;
break;
}
return 0;
}
LRESULT CXTPToolTipContextToolTip::OnUpdateTipText(WPARAM, LPARAM lParam)
{
LPTOOLINFO lpToolInfo = LPTOOLINFO(lParam);
for (int i = 0; i < (int)m_arrTools.GetSize(); i++)
{
TOOLITEM* pItem = m_arrTools[i];
if ((pItem->uId == lpToolInfo->uId) && (pItem->hwnd == lpToolInfo->hwnd))
{
pItem->bAutoCaption = (lpToolInfo->lpszText == LPSTR_TEXTCALLBACK);
pItem->strCaption = pItem->bAutoCaption ? _T("") : lpToolInfo->lpszText;
break;
}
}
return 0;
}
LRESULT CXTPToolTipContextToolTip::OnAddTool(WPARAM, LPARAM lParam)
{
return AddTool((LPTOOLINFO)lParam);
}
LRESULT CXTPToolTipContextToolTip::OnActivate(WPARAM wParam, LPARAM)
{
Activate((BOOL)wParam);
return 0;
}
LRESULT CXTPToolTipContextToolTip::OnDelTool(WPARAM, LPARAM lParam)
{
DelTool((LPTOOLINFO)lParam);
return 0;
}
LRESULT CXTPToolTipContextToolTip::OnRelayEvent(WPARAM, LPARAM lParam)
{
RelayEvent((LPMSG)lParam);
return 0;
}
LRESULT CXTPToolTipContextToolTip::OnWindowFromPoint(WPARAM, LPARAM lParam)
{
LPPOINT lpPoint = (LPPOINT)lParam;
HWND hWnd = lpPoint ? ::WindowFromPoint(*lpPoint) : 0;
if ((hWnd != NULL) && (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) && (::SendMessage(hWnd, XTP_TTM_WINDOWFROMPOINT, 0, 0) == 1))
{
return (LRESULT)::GetParent(hWnd);
}
return (LRESULT)hWnd;
}
BOOL CXTPToolTipContextToolTip::AddTool(LPTOOLINFO lpToolInfo)
{
ASSERT(lpToolInfo);
if (!lpToolInfo)
return FALSE;
TOOLITEM* pti = new TOOLITEM;
pti->hwnd = lpToolInfo->hwnd;
pti->uFlags = lpToolInfo->uFlags;
pti->uId = lpToolInfo->uId;
pti->rect = lpToolInfo->rect;
pti->bAutoCaption = (lpToolInfo->lpszText == LPSTR_TEXTCALLBACK);
pti->strCaption = pti->bAutoCaption ? _T("") : lpToolInfo->lpszText;
pti->hinst = lpToolInfo->hinst;
pti->rectExclude.SetRectEmpty();
if (lpToolInfo->cbSize == sizeof(XTP_TOOLTIP_TOOLINFO_EX))
{
pti->rectExclude = ((XTP_TOOLTIP_TOOLINFO_EX*)lpToolInfo)->pToolInfo->rcExclude;
}
m_arrTools.Add(pti);
return TRUE;
}
void CXTPToolTipContextToolTip::Activate(BOOL bActivate)
{
m_bActive = bActivate;
if (!bActivate && GetSafeHwnd() && m_nDelayTimer)
{
KillTimer(m_nDelayTimer);
m_nDelayTimer = 0;
m_toolDelay.Reset();
}
if (!bActivate && GetSafeHwnd() && IsWindowVisible())
{
SetVisibleTool(NULL);
}
}
void CXTPToolTipContextToolTip::DelTool(LPTOOLINFO lpToolInfo)
{
ASSERT(lpToolInfo);
if (!lpToolInfo)
return;
for (int i = 0; i < (int)m_arrTools.GetSize(); i++)
{
TOOLITEM* pItem = m_arrTools[i];
if ((pItem->uId == lpToolInfo->uId) && (pItem->hwnd == lpToolInfo->hwnd))
{
if (m_toolVisible.IsEqual(pItem))
SetVisibleTool(0);
if (m_toolDisabled.IsEqual(pItem)) m_toolDisabled.Reset();
if (m_toolDelay.IsEqual(pItem)) m_toolDelay.Reset();
m_arrTools.RemoveAt(i);
delete pItem;
break;
}
}
}
CXTPToolTipContextToolTip::TOOLITEM* CXTPToolTipContextToolTip::FindTool()
{
if (!(GetKeyState(VK_LBUTTON) >= 0 && GetKeyState(VK_RBUTTON) >= 0 &&
GetKeyState(VK_MBUTTON) >= 0))
{
return NULL;
}
CPoint pt;
GetCursorPos(&pt);
for (int i = 0; i < m_arrTools.GetSize(); i++)
{
TOOLITEM* pItem = m_arrTools[i];
if (!::IsWindow(pItem->hwnd))
continue;
CWnd* pWnd = CWnd::FromHandle(pItem->hwnd);
CRect rcTool = pItem->rect;
if (pItem->uFlags & TTF_IDISHWND)
{
pWnd->GetWindowRect(rcTool);
}
else
{
pWnd->ClientToScreen(rcTool);
}
if (rcTool.PtInRect(pt) && ((pItem->uFlags & TTF_IDISHWND) || ((HWND)OnWindowFromPoint(0, (LRESULT)(LPPOINT)&pt) == pItem->hwnd)))
return pItem;
}
return NULL;
}
#ifndef IS_INTRESOURCE
#define IS_INTRESOURCE(x) (((size_t)(x) >> 16) == 0)
#endif
CString CXTPToolTipContextToolTip::GetToolText(TOOLITEM* lpToolInfo)
{
if (lpToolInfo->bAutoCaption)
{
UINT_PTR id = lpToolInfo->uId;
TOOLTIPTEXT tt = {0};
tt.hdr.hwndFrom = m_hWnd;
tt.hdr.idFrom = lpToolInfo->uId;
tt.hdr.code = TTN_NEEDTEXT;
tt.uFlags = lpToolInfo->uFlags;
tt.hinst = NULL;
tt.szText[0] = _T('\0');
tt.lpszText = tt.szText;
::SendMessage(lpToolInfo->hwnd, WM_NOTIFY, id, (LPARAM)&tt);
if (IS_INTRESOURCE(tt.lpszText))
{
XTPResourceManager()->LoadLocaleString(tt.hinst, (UINT)(UINT_PTR)tt.lpszText, lpToolInfo->strCaption);
}
else
{
lpToolInfo->strCaption = tt.lpszText;
}
if ((m_pContext->GetControlStyle() & TTS_NOPREFIX) == 0)
{
CXTPDrawHelpers::StripMnemonics(lpToolInfo->strCaption);
}
lpToolInfo->bAutoCaption = FALSE;
}
return lpToolInfo->strCaption;
}
int CXTPToolTipContextToolTip::GetMaxTipWidth() const
{
const int nWidth = m_pContext->GetMaxTipWidth();
if (nWidth == -1)
{
return ::GetSystemMetrics(SM_CXSCREEN);
}
return nWidth;
}
CSize CXTPToolTipContextToolTip::GetToolSize(TOOLITEM* lpToolInfo)
{
CClientDC dc(this);
CFont* pOldFont = dc.SelectObject(&m_pContext->m_fnt);
CString str = GetToolText(lpToolInfo);
if (str.IsEmpty())
{
dc.SelectObject(pOldFont);
return CSize(0);
}
int nMaxTipWidth = GetMaxTipWidth();
CRect rcMargin = m_pContext->GetMargin();
CSize szMargin(3 + rcMargin.left + rcMargin.right + 3, 3 + rcMargin.top + rcMargin.bottom + 3);
DWORD dwFlags = DT_NOPREFIX | DT_EXPANDTABS;
BOOL bDrawImage = m_pIcon != NULL;
BOOL bDrawTitle = !m_strTitle.IsEmpty();
BOOL bDrawImageTop = TRUE;
CSize szImage(0, 0);
CSize szTitle(0, 0);
if (bDrawTitle)
{
CXTPFontDC fntTitle(&dc, &m_pContext->m_fntTitle);
CRect rcTitle(0, 0, 0, 0);
dc.DrawText(m_strTitle, rcTitle, dwFlags | DT_CALCRECT | DT_SINGLELINE);
szTitle = CSize(rcTitle.Width() + 4, rcTitle.Height() + 10 + 10);
}
if (bDrawImage)
{
CSize szIcon(m_pIcon->GetWidth(), m_pIcon->GetHeight());
bDrawImageTop = (szIcon.cy <= 16);
if (bDrawImageTop)
{
if (!bDrawTitle)
{
szImage.cx = szIcon.cx + 3;
}
else
{
szTitle.cx += szIcon.cx + 1;
}
}
else
{
szImage.cx = szIcon.cx + 5;
}
szImage.cy = szIcon.cy;
}
CRect rcText(0, 0, nMaxTipWidth - szMargin.cx, 0);
if (bDrawTitle)
rcText.right = max(szTitle.cx, nMaxTipWidth - szMargin.cx) - (10 + 15);
dc.DrawText(str, rcText, dwFlags | DT_CALCRECT | DT_WORDBREAK);
dc.SelectObject(pOldFont);
CSize szText = rcText.Size();
CSize sz(0, 0);
sz.cy = max(szImage.cy, szText.cy);
sz.cx = szImage.cx + szText.cx;
if (bDrawTitle)
{
sz.cx = max(sz.cx + 10 + 15, szTitle.cx);
sz.cy += szTitle.cy;
}
sz += szMargin;
return sz;
}
HHOOK CXTPToolTipContextToolTip::m_hHookMouse = 0;
CXTPToolTipContextToolTip* CXTPToolTipContextToolTip::m_pWndMonitor = 0;
LRESULT CALLBACK CXTPToolTipContextToolTip::MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode != HC_ACTION || !m_pWndMonitor || m_pWndMonitor->m_toolVisible.IsEmpty())
return CallNextHookEx(m_hHookMouse, nCode, wParam, lParam);
POINT pt = ((PMOUSEHOOKSTRUCT)lParam)->pt;
HWND hWnd = (HWND)m_pWndMonitor->OnWindowFromPoint(0, (LPARAM)&pt);
if (hWnd != m_pWndMonitor->m_toolVisible.hwnd)
{
MSG msg;
msg.pt = pt;
msg.message = WM_MOUSEMOVE;
m_pWndMonitor->RelayEvent(&msg);
}
return CallNextHookEx(m_hHookMouse, nCode, wParam, lParam);
}
void CXTPToolTipContextToolTip::HookMouseMove(BOOL bSetupHook)
{
if (bSetupHook && m_hHookMouse == 0 && (m_pWndMonitor == NULL))
{
m_hHookMouse = SetWindowsHookEx(WH_MOUSE, MouseProc, 0, GetCurrentThreadId ());
m_pWndMonitor = this;
}
else if (!bSetupHook && m_hHookMouse && (m_pWndMonitor == this))
{
UnhookWindowsHookEx(m_hHookMouse);
m_hHookMouse = 0;
m_pWndMonitor = NULL;
}
}
void CXTPToolTipContextToolTip::EnsureVisible(CRect& rcToolTip)
{
CRect rcWork = XTPMultiMonitor()->GetWorkArea();
int nGap = 4;
if (rcWork.right - nGap < rcToolTip.right)
{
rcToolTip.OffsetRect(- rcToolTip.right + rcWork.right - nGap, 0);
}
if (rcWork.left > rcToolTip.left)
{
rcToolTip.OffsetRect(rcWork.left - rcToolTip.left, 0);
}
if (rcWork.bottom - nGap < rcToolTip.bottom)
{
CPoint pt;
GetCursorPos(&pt);
rcToolTip.OffsetRect(0, pt.y - rcToolTip.bottom - 3);
}
}
int CXTPToolTipContext::GetCursorHeight()
{
HCURSOR hCursor = GetCursor();
ICONINFO iconInfo;
if (!GetIconInfo(hCursor, &iconInfo))
return 21;
BITMAP bm;
if (!GetObject(iconInfo.hbmMask, sizeof(BITMAP), &bm))
return 21;
WORD curBits[16 * 8];
memset(&curBits, -1, sizeof(curBits));
if (!GetBitmapBits(iconInfo.hbmMask, sizeof(curBits), curBits))
return 21;
int nBitSize = sizeof(WORD) * 8;
int nCount = MulDiv(bm.bmWidth, bm.bmHeight, nBitSize);
int nXor = 0;
if (!iconInfo.hbmColor)
{
nXor = nCount - 1;
nCount = nCount / 2;
}
if (nCount >= sizeof(curBits)/sizeof(WORD)) nCount = sizeof(curBits)/sizeof(WORD) - 1;
if (nXor >= sizeof(curBits)/sizeof(WORD)) nXor = 0;
int i = nCount - 1;
for (; i >= 0; i--)
{
if (curBits[i] != 0xFFFF || (nXor && (curBits[nXor--] != 0)))
break;
}
if (iconInfo.hbmColor) DeleteObject(iconInfo.hbmColor);
if (iconInfo.hbmMask) DeleteObject(iconInfo.hbmMask);
return MulDiv(i + 1, nBitSize, (int)bm.bmWidth) - (int)iconInfo.yHotspot;
}
void CXTPToolTipContextToolTip::SetRoundRectRegion(CWnd* pWnd)
{
CXTPWindowRect rc(pWnd);
rc.OffsetRect(-rc.TopLeft());
int cx = rc.Width(), cy = rc.Height();
RECT rgn[] =
{
{1, 0, cx - 1, 1}, {0, 1, cx, cy - 1}, {1, cy - 1, cx - 1, cy}
};
int nSizeData = sizeof(RGNDATAHEADER) + sizeof(rgn);
RGNDATA* pRgnData = (RGNDATA*)malloc(nSizeData);
if (!pRgnData)
return;
MEMCPY_S(&pRgnData->Buffer, (void*)&rgn, sizeof(rgn));
pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER);
pRgnData->rdh.iType = RDH_RECTANGLES;
pRgnData->rdh.nCount = sizeof(rgn) / sizeof(RECT);
pRgnData->rdh.nRgnSize = 0;
pRgnData->rdh.rcBound = CRect(0, 0, cx, cy);
CRgn rgnResult;
VERIFY(rgnResult.CreateFromData(NULL, nSizeData, pRgnData));
free(pRgnData);
pWnd->SetWindowRgn((HRGN)rgnResult.Detach(), FALSE);
m_bWindowRegion = TRUE;
}
void CXTPToolTipContextToolTip::SetVisibleTool(TOOLITEM* pVisibleTool)
{
if (!m_toolVisible.IsEqual(pVisibleTool))
{
CSize sz(0);
if (pVisibleTool)
{
sz = GetToolSize(pVisibleTool);
if (sz == CSize(0)) pVisibleTool = 0;
}
if (m_hWnd)
{
SetWindowPos(0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
if (m_bWindowRegion)
{
SetWindowRgn(NULL, FALSE);
m_bWindowRegion = FALSE;
}
}
if (pVisibleTool)
{
CRect rcToolTip(0, 0, 0, 0);
if (!pVisibleTool->rectExclude.IsRectEmpty())
{
CWnd* pWnd = CWnd::FromHandle(pVisibleTool->hwnd);
//CRect rcExclude = pVisibleTool->rectExclude;
//rcToolTip = pVisibleTool->rect;
rcToolTip.SetRect(pVisibleTool->rect.left, pVisibleTool->rectExclude.bottom,
pVisibleTool->rect.left + sz.cx, pVisibleTool->rectExclude.bottom + sz.cy);
pWnd->ClientToScreen(rcToolTip);
}
else
{
CPoint pt;
GetCursorPos(&pt);
int nCursorHeight = CXTPToolTipContext::GetCursorHeight();
rcToolTip.SetRect(pt.x, pt.y + nCursorHeight, pt.x + sz.cx, pt.y + nCursorHeight + sz.cy);
if (GetWindowLong(pVisibleTool->hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
{
rcToolTip.OffsetRect(-sz.cx, 0);
}
}
EnsureVisible(rcToolTip);
SetWindowPos(&CWnd::wndTop, rcToolTip.left, rcToolTip.top,
rcToolTip.Width(), rcToolTip.Height(), SWP_NOACTIVATE | SWP_NOOWNERZORDER);
UINT_PTR id = pVisibleTool->uId;
NMHDR hdr = {0};
hdr.hwndFrom = m_hWnd;
hdr.idFrom = pVisibleTool->uId;
hdr.code = TTN_SHOW;
::SendMessage(pVisibleTool->hwnd, WM_NOTIFY, id, (LPARAM)&hdr);
if (GetStyle() & XTP_TTS_OFFICE2007FRAME)
{
SetRoundRectRegion(this);
}
SetWindowPos(0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
Invalidate(FALSE);
HookMouseMove(TRUE);
m_toolDisabled.Reset();
if (m_nDelayAutoPop > 0)
{
if (m_nAutoPopTimer > 0)
{
KillTimer(m_nAutoPopTimer);
m_nAutoPopTimer = 0;
}
m_nAutoPopTimer = SetTimer(3, m_nDelayAutoPop, NULL);
}
}
else
{
HookMouseMove(FALSE);
m_toolDelay.Reset();
if (m_nAutoPopTimer > 0)
{
if (m_hWnd) KillTimer(m_nAutoPopTimer);
m_nAutoPopTimer = 0;
}
}
m_toolVisible.Assign(pVisibleTool);
m_dwLastTip = GetTickCount();
OnVisibleChanged(pVisibleTool != NULL);
}
}
void CXTPToolTipContextToolTip::RelayEvent(LPMSG lpMsg)
{
if (!m_bActive)
return;
if (!((lpMsg->message >= WM_MOUSEFIRST && lpMsg->message <= WM_MOUSELAST) ||
(lpMsg->message >= WM_NCMOUSEMOVE && lpMsg->message <= WM_NCMBUTTONDBLCLK)))
return;
TOOLITEM* pVisibleTool = FindTool();
if (lpMsg->message == WM_LBUTTONDOWN)
{
if (pVisibleTool)
{
m_toolDisabled = *pVisibleTool;
pVisibleTool = 0;
}
}
if (pVisibleTool && (m_toolDisabled.IsEqual(pVisibleTool)))
{
pVisibleTool = 0;
}
if (m_nDelayTimer && !m_toolDelay.IsEqual(pVisibleTool))
{
KillTimer(m_nDelayTimer);
m_nDelayTimer = 0;
m_toolDelay.Reset();
}
if (pVisibleTool)
{
if (!m_toolVisible.IsEqual(pVisibleTool))
{
if (GetTickCount() - m_dwLastTip < m_nDelayReshow)
{
SetVisibleTool(pVisibleTool);
}
else if (!m_toolDelay.IsEqual(pVisibleTool))
{
m_toolDelay = *pVisibleTool;
m_nDelayTimer = SetTimer(1, m_nDelayInitial, NULL);
}
}
}
else
{
SetVisibleTool(0);
}
}
void CXTPToolTipContextToolTip::DrawEntry(CDC* pDC, TOOLITEM* lpToolInfo, CRect rc)
{
CString str = lpToolInfo->strCaption;
rc.DeflateRect(m_pContext->GetMargin());
rc.DeflateRect(3, 3, 3, 3);
DWORD dwFlags = DT_NOPREFIX | DT_EXPANDTABS;
BOOL bLayoutRTL = lpToolInfo->hwnd && GetWindowLong(lpToolInfo->hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL;
if (bLayoutRTL)
{
dwFlags |= DT_RTLREADING | DT_RIGHT;
}
CRect rcTitle(rc.left + 2, rc.top + 2, rc.right - 2, rc.bottom);
BOOL bDrawImage = m_pIcon != NULL;
BOOL bDrawTitle = !m_strTitle.IsEmpty();
BOOL bDrawImageTop = TRUE;
CSize szImage(0, 0);
if (bDrawImage)
{
szImage = CSize(m_pIcon->GetWidth(), m_pIcon->GetHeight());
bDrawImageTop = (szImage.cy <= 16);
if (bDrawImageTop)
{
CPoint ptIcon = bLayoutRTL ? CPoint(rc.right - szImage.cx, rc.top) : rc.TopLeft();
m_pIcon->Draw(pDC, ptIcon);
if (bLayoutRTL)
{
if (bDrawTitle) rcTitle.right -= szImage.cx + 1; else rc.right -= szImage.cx + 3;
}
else
{
if (bDrawTitle) rcTitle.left += szImage.cx + 1; else rc.left += szImage.cx + 3;
}
}
}
if (bDrawTitle)
{
CXTPFontDC fnt(pDC, &m_pContext->m_fntTitle);
pDC->DrawText(m_strTitle, rcTitle, dwFlags | DT_SINGLELINE);
rc.top += pDC->GetTextExtent(m_strTitle).cy;
if (bLayoutRTL)
{
rc.DeflateRect(15, 12, 10, 0);
}
else
{
rc.DeflateRect(10, 12, 15, 0);
}
}
if (bDrawImage && !bDrawImageTop)
{
CPoint ptIcon = bLayoutRTL ? CPoint(rc.right - szImage.cx, rc.top) : rc.TopLeft();
m_pIcon->Draw(pDC, ptIcon);
if (bLayoutRTL) rc.right -= szImage.cx + 5; else rc.left += szImage.cx + 5;
}
pDC->DrawText(str, rc, dwFlags | DT_WORDBREAK);
}
void CXTPToolTipContextToolTip::DrawBackground(CDC* pDC, TOOLITEM* /*lpToolInfo*/, CRect rc)
{
m_pContext->DrawBackground(pDC, rc);
}
void CXTPToolTipContextToolTip::OnPaint()
{
CPaintDC dc(this); // device context for painting
CXTPClientRect rc(this);
DrawBackground(&dc, &m_toolVisible, rc);
COLORREF clrTextColor = m_pContext->GetTipTextColor();
dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(clrTextColor);
CXTPFontDC font(&dc, &m_pContext->m_fnt);
DrawEntry(&dc, &m_toolVisible, rc);
}
void CXTPToolTipContext::DrawBackground(CDC* pDC, CRect rc)
{
if (m_dwStyle & XTP_TTS_OFFICE2007FRAME)
{
CXTPResourceImages* pImages = XTPResourceImages();
COLORREF clrLight = pImages->GetImageColor(_T("Window"), _T("TooltipLight"));
COLORREF clrDark = pImages->GetImageColor(_T("Window"), _T("TooltipDark"));
if (clrLight == COLORREF_NULL) clrLight = RGB(255, 255, 255);
if (clrDark == COLORREF_NULL) clrDark = RGB(201, 217, 239);
XTPDrawHelpers()->GradientFill(pDC, rc, clrLight, clrDark, FALSE);
CXTPResourceImage* pImage = pImages->LoadFile(_T("TOOLTIPFRAME"));
if (pImage)
{
pImage->DrawImage(pDC, rc, pImage->GetSource(0, 1), CRect(3, 3, 3, 3), 0xFF00FF);
}
else
{
COLORREF clrBorder = pImages->GetImageColor(_T("Window"), _T("TooltipBorder"));
if (clrBorder == COLORREF_NULL) clrBorder = RGB(118, 118, 118);
pDC->Draw3dRect(rc, clrBorder, clrBorder);
}
}
else
{
pDC->FillSolidRect(rc, GetTipBkColor());
if (m_dwStyle & XTP_TTS_OFFICEFRAME)
pDC->Draw3dRect(rc, GetSysColor(COLOR_3DFACE), 0);
else
pDC->Draw3dRect(rc, 0, 0);
}
pDC->SetTextColor(GetTipTextColor());
}
BOOL CXTPToolTipContextToolTip::OnEraseBkgnd(CDC* /*pDC*/)
{
return TRUE;
}
LRESULT CXTPToolTipContextToolTip::OnNcHitTest(CPoint /*point*/)
{
return (LRESULT)HTTRANSPARENT;
}
int CXTPToolTipContextToolTip::OnMouseActivate(CWnd* /*pDesktopWnd*/, UINT /*nHitTest*/, UINT /*message*/)
{
return MA_NOACTIVATE;
}
void CXTPToolTipContextToolTip::OnMouseMove(UINT /*nFlags*/, CPoint /*point*/)
{
SetVisibleTool(NULL);
}
void CXTPToolTipContextToolTip::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == m_nDelayTimer)
{
if (!m_toolDelay.IsEmpty())
{
TOOLITEM* pVisibleTool = FindTool();
if (m_toolDelay.IsEqual(pVisibleTool))
{
SetVisibleTool(pVisibleTool);
}
}
KillTimer(m_nDelayTimer);
m_nDelayTimer = 0;
m_toolDelay.Reset();
}
if (nIDEvent == m_nAutoPopTimer)
{
KillTimer(m_nAutoPopTimer);
m_nAutoPopTimer = 0;
Activate(FALSE);
}
CWnd::OnTimer(nIDEvent);
}
//////////////////////////////////////////////////////////////////////////
// CXTPToolTipContext::CStandardToolTip
class CXTPToolTipContext::CStandardToolTip : public CToolTipCtrl
{
DECLARE_MESSAGE_MAP()
LRESULT OnWindowFromPoint(WPARAM, LPARAM);
};
typedef CXTPToolTipContext::CStandardToolTip CXTPToolTipContextStandardTip;
BEGIN_MESSAGE_MAP(CXTPToolTipContextStandardTip, CToolTipCtrl)
ON_MESSAGE(TTM_WINDOWFROMPOINT, OnWindowFromPoint)
END_MESSAGE_MAP()
LRESULT CXTPToolTipContext::CStandardToolTip::OnWindowFromPoint(WPARAM, LPARAM)
{
HWND hWnd = (HWND)Default();
if ((hWnd != NULL) && (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) && (::SendMessage(hWnd, XTP_TTM_WINDOWFROMPOINT, 0, 0) == 1))
{
return (LRESULT)::GetParent(hWnd);
}
return (LRESULT)hWnd;
}
//////////////////////////////////////////////////////////////////////////
// CXTPToolTipContext::CLunaToolTip
class CXTPToolTipContext::CLunaToolTip : public CXTPToolTipContextToolTip
{
public:
CLunaToolTip(CXTPToolTipContext* pContext)
: CXTPToolTipContextToolTip(pContext)
{
}
void DrawBackground(CDC* pDC, TOOLITEM* /*lpToolInfo*/, CRect rc)
{
switch (XTPColorManager()->GetCurrentSystemTheme())
{
case xtpSystemThemeBlue:
case xtpSystemThemeRoyale:
case xtpSystemThemeAero:
XTPDrawHelpers()->GradientFill(pDC, rc, RGB(255, 212, 151), RGB(255, 242, 200), FALSE);
pDC->Draw3dRect(rc, RGB(0, 0, 128), RGB(0, 0, 128));
break;
case xtpSystemThemeOlive:
XTPDrawHelpers()->GradientFill(pDC, rc, RGB(255, 212, 151), RGB(255, 242, 200), FALSE);
pDC->Draw3dRect(rc, RGB(63, 93, 56), RGB(63, 93, 56));
break;
case xtpSystemThemeSilver:
XTPDrawHelpers()->GradientFill(pDC, rc, RGB(255, 212, 151), RGB(255, 242, 200), FALSE);
pDC->Draw3dRect(rc, RGB(75, 75, 111), RGB(75, 75, 111));
break;
default:
XTPDrawHelpers()->GradientFill(pDC, rc, m_pContext->GetTipBkColor(), RGB(255, 255, 255), FALSE);
pDC->Draw3dRect(rc, 0, 0);
}
}
};
//////////////////////////////////////////////////////////////////////////
// CXTPToolTipContext::CRichEditToolTip
class CXTPToolTipContext::CRichEditToolTip : public CXTPToolTipContextToolTip
{
public:
CRichEditToolTip(CXTPToolTipContext* pContext)
: CXTPToolTipContextToolTip(pContext)
{
}
protected:
virtual void DrawEntry(CDC* pDC, TOOLITEM* lpToolInfo, CRect rc);
virtual CSize GetToolSize(TOOLITEM* lpToolInfo);
protected:
CXTPRichRender m_render;
};
CSize CXTPToolTipContext::CRichEditToolTip::GetToolSize(TOOLITEM* lpToolInfo)
{
if (!m_render.GetTextService())
return CSize(0);
CString sText = GetToolText(lpToolInfo);
if (sText.IsEmpty())
return CSize(0);
CClientDC dc(this);
CXTPFontDC font(&dc, &m_pContext->m_fnt);
CHARFORMATW cf;
ZeroMemory(&cf, sizeof(CHARFORMATW));
cf.cbSize = sizeof(CHARFORMATW);
cf.dwMask = CFM_BOLD | CFM_COLOR | CFM_ITALIC | CFM_PROTECTED | CFM_STRIKEOUT | CFM_UNDERLINE;
cf.crTextColor = m_pContext->GetTipTextColor();
LOGFONT lf;
if (m_pContext->GetFont()->GetLogFont(&lf))
{
cf.yHeight = -MulDiv(lf.lfHeight, 1440, ::GetDeviceCaps(dc, LOGPIXELSY));
WCSNCPY_S(cf.szFaceName, LF_FACESIZE, XTP_CT2CW(lf.lfFaceName), LF_FACESIZE);
cf.dwMask |= CFM_FACE | CFM_SIZE;
}
m_render.SetText(NULL);
m_render.SetDefaultCharFormat(&cf);
m_render.SetText(sText);
CRect rcMargin = m_pContext->GetMargin();
CSize szMargin(3 + rcMargin.left + rcMargin.right + 3, 3 + rcMargin.top + rcMargin.bottom + 3);
CSize size = m_render.GetTextExtent(&dc, GetMaxTipWidth() - szMargin.cx);
size += szMargin;
return size;
}
void CXTPToolTipContext::CRichEditToolTip::DrawEntry(CDC* pDC, TOOLITEM* /*lpToolInfo*/, CRect rc)
{
rc.DeflateRect(m_pContext->GetMargin());
rc.DeflateRect(3, 3, 3, 3);
m_render.DrawText(pDC, rc);
}
class CXTPToolTipContext::CMarkupToolTip : public CXTPToolTipContextToolTip
{
public:
CMarkupToolTip(CXTPToolTipContext* pContext)
: CXTPToolTipContextToolTip(pContext)
{
m_pUIElement = NULL;
m_pMarkupContext = XTPMarkupCreateContext();
}
~CMarkupToolTip()
{
XTPMarkupReleaseElement(m_pUIElement);
XTPMarkupReleaseContext(m_pMarkupContext);
}
protected:
virtual void DrawEntry(CDC* pDC, TOOLITEM* lpToolInfo, CRect rc);
virtual CSize GetToolSize(TOOLITEM* lpToolInfo);
protected:
CXTPMarkupUIElement* m_pUIElement;
CXTPMarkupContext* m_pMarkupContext;
};
CSize CXTPToolTipContext::CMarkupToolTip::GetToolSize(TOOLITEM* lpToolInfo)
{
XTPMarkupReleaseElement(m_pUIElement);
CString sText = GetToolText(lpToolInfo);
if (sText.IsEmpty())
return CSize(0);
XTPMarkupSetDefaultFont(m_pMarkupContext, (HFONT)m_pContext->GetFont()->GetSafeHandle(), m_pContext->GetTipTextColor());
m_pUIElement = XTPMarkupParseText(m_pMarkupContext, sText);
if (!m_pUIElement)
{
return CXTPToolTipContextToolTip::GetToolSize(lpToolInfo);
}
CRect rcMargin = m_pContext->GetMargin();
CSize szMargin(3 + rcMargin.left + rcMargin.right + 3, 3 + rcMargin.top + rcMargin.bottom + 3);
CSize size = XTPMarkupMeasureElement(m_pUIElement, GetMaxTipWidth() - szMargin.cx);
size += szMargin;
return size;
}
void CXTPToolTipContext::CMarkupToolTip::DrawEntry(CDC* pDC, TOOLITEM* lpToolInfo, CRect rc)
{
if (m_pUIElement)
{
CRect rcMargin = m_pContext->GetMargin();
CRect rcText(rc);
rcText.DeflateRect(3 + rcMargin.left, 3 + rcMargin.top, rcMargin.right + 3, rcMargin.bottom + 3);
XTPMarkupRenderElement(m_pUIElement, pDC->GetSafeHdc(), rcText);
}
else
{
CXTPToolTipContextToolTip::DrawEntry(pDC, lpToolInfo, rc);
}
}
#ifndef _XTP_EXCLUDE_HTML
//////////////////////////////////////////////////////////////////////////
// CXTPToolTipContext::CHTMLToolTip
class CXTPToolTipContext::CHTMLToolTip : public CXTPToolTipContextToolTip
{
public:
CHTMLToolTip(CXTPToolTipContext* pContext);
~CHTMLToolTip();
protected:
virtual void DrawEntry(CDC* pDC, TOOLITEM* lpToolInfo, CRect rc);
virtual CSize GetToolSize(TOOLITEM* lpToolInfo);
virtual void OnVisibleChanged(BOOL bVisble);
protected:
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(OleClientSite, IOleClientSite)
STDMETHOD(SaveObject)( void) { return E_NOTIMPL;}
STDMETHOD (GetMoniker)(
/* [in] */ DWORD /*dwAssign*/,
/* [in] */ DWORD /*dwWhichMoniker*/,
/* [out] */ IMoniker ** /*ppmk*/) { return E_NOTIMPL;}
STDMETHOD(GetContainer)(
/* [out] */ IOleContainer ** /*ppContainer*/) { return E_NOTIMPL;}
STDMETHOD(ShowObject)( void) { return E_NOTIMPL;}
STDMETHOD(OnShowWindow)(
/* [in] */ BOOL /*fShow*/) { return E_NOTIMPL;}
STDMETHOD(RequestNewObjectLayout)( void) { return E_NOTIMPL;}
END_INTERFACE_PART(OleClientSite)
BEGIN_INTERFACE_PART(DocHostUIHandler, IDocHostUIHandler)
STDMETHOD(ShowContextMenu)(/* [in] */ DWORD dwID,
/* [in] */ POINT __RPC_FAR *ppt,
/* [in] */ IUnknown __RPC_FAR *pcmdtReserved,
/* [in] */ IDispatch __RPC_FAR *pdispReserved);
STDMETHOD(GetHostInfo)(
/* [out][in] */ DOCHOSTUIINFO __RPC_FAR *pInfo);
STDMETHOD(ShowUI)(
/* [in] */ DWORD dwID,
/* [in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
/* [in] */ IOleCommandTarget __RPC_FAR *pCommandTarget,
/* [in] */ IOleInPlaceFrame __RPC_FAR *pFrame,
/* [in] */ IOleInPlaceUIWindow __RPC_FAR *pDoc);
STDMETHOD(HideUI)(void);
STDMETHOD(UpdateUI)(void);
STDMETHOD(EnableModeless)(/* [in] */ BOOL fEnable);
STDMETHOD(OnDocWindowActivate)(/* [in] */ BOOL fEnable);
STDMETHOD(OnFrameWindowActivate)(/* [in] */ BOOL fEnable);
STDMETHOD(ResizeBorder)(
/* [in] */ LPCRECT prcBorder,
/* [in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
/* [in] */ BOOL fRameWindow);
STDMETHOD(TranslateAccelerator)(
/* [in] */ LPMSG lpMsg,
/* [in] */ const GUID __RPC_FAR *pguidCmdGroup,
/* [in] */ DWORD nCmdID);
STDMETHOD(GetOptionKeyPath)(
/* [out] */ LPOLESTR __RPC_FAR *pchKey,
/* [in] */ DWORD dw);
STDMETHOD(GetDropTarget)(
/* [in] */ IDropTarget __RPC_FAR *pDropTarget,
/* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget);
STDMETHOD(GetExternal)(
/* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch);
STDMETHOD(TranslateUrl)(
/* [in] */ DWORD dwTranslate,
/* [in] */ OLECHAR __RPC_FAR *pchURLIn,
/* [out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut);
STDMETHOD(FilterDataObject)(
/* [in] */ IDataObject __RPC_FAR *pDO,
/* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDORet);
END_INTERFACE_PART(DocHostUIHandler)
protected:
CBitmap m_bmpScreen;
CWnd m_wndBrowser;
IWebBrowser2* m_pBrowserApp;
};
//////////////////////////////////////////////////////////////////////////
// CWebBrowserSite
BEGIN_INTERFACE_MAP(CXTPToolTipContext::CHTMLToolTip, CWnd)
INTERFACE_PART(CXTPToolTipContext::CHTMLToolTip, IID_IOleClientSite, OleClientSite)
INTERFACE_PART(CXTPToolTipContext::CHTMLToolTip, IID_IDocHostUIHandler, DocHostUIHandler)
END_INTERFACE_MAP()
#define IMPLEMENT_INTERFACE_PART(theClass, localClass)\
STDMETHODIMP_(ULONG) theClass::X##localClass::AddRef()\
{\
METHOD_PROLOGUE(theClass, localClass)\
return pThis->ExternalAddRef();\
}\
STDMETHODIMP_(ULONG) theClass::X##localClass::Release()\
{\
METHOD_PROLOGUE(theClass, localClass)\
return pThis->ExternalRelease();\
}\
STDMETHODIMP theClass::X##localClass::QueryInterface(REFIID riid, void **ppvObj)\
{\
METHOD_PROLOGUE(theClass, localClass)\
HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);\
return hr;\
}
IMPLEMENT_INTERFACE_PART(CXTPToolTipContext::CHTMLToolTip, OleClientSite)
IMPLEMENT_INTERFACE_PART(CXTPToolTipContext::CHTMLToolTip, DocHostUIHandler)
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::GetHostInfo( DOCHOSTUIINFO* pInfo )
{
pInfo->dwFlags = 0x40000 | DOCHOSTUIFLAG_NO3DBORDER;
pInfo->dwFlags |= DOCHOSTUIFLAG_DIALOG;
pInfo->dwFlags |= DOCHOSTUIFLAG_SCROLL_NO;
pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
return S_OK;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::ShowUI(
DWORD /*dwID*/,
IOleInPlaceActiveObject * /*pActiveObject*/,
IOleCommandTarget * /*pCommandTarget*/,
IOleInPlaceFrame * /*pFrame*/,
IOleInPlaceUIWindow * /*pDoc*/)
{
return S_OK;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::HideUI(void)
{
return S_OK;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::UpdateUI(void)
{
return S_OK;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::EnableModeless(BOOL /*fEnable*/)
{
return E_NOTIMPL;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::OnDocWindowActivate(BOOL /*fActivate*/)
{
return E_NOTIMPL;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::OnFrameWindowActivate(BOOL /*fActivate*/)
{
return E_NOTIMPL;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::ResizeBorder(
LPCRECT /*prcBorder*/,
IOleInPlaceUIWindow* /*pUIWindow*/,
BOOL /*fRameWindow*/)
{
return E_NOTIMPL;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::ShowContextMenu(
DWORD /*dwID*/,
POINT* /*pptPosition*/,
IUnknown* /*pCommandTarget*/,
IDispatch* /*pDispatchObjectHit*/)
{
return S_OK;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::TranslateAccelerator(LPMSG /*lpMsg*/,
/* [in] */ const GUID __RPC_FAR* /*pguidCmdGroup*/,
/* [in] */ DWORD /*nCmdID*/)
{
return S_FALSE;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::GetOptionKeyPath(BSTR* /*pbstrKey*/, DWORD)
{
return E_NOTIMPL;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::GetDropTarget(
/* [in] */ IDropTarget __RPC_FAR* /*pDropTarget*/,
/* [out] */ IDropTarget __RPC_FAR *__RPC_FAR* /*ppDropTarget*/)
{
return E_NOTIMPL;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::GetExternal(
/* [out] */ IDispatch __RPC_FAR *__RPC_FAR* /*ppDispatch*/)
{
return E_NOTIMPL;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::TranslateUrl(
/* [in] */ DWORD /*dwTranslate*/,
/* [in] */ OLECHAR __RPC_FAR* /*pchURLIn*/,
/* [out] */ OLECHAR __RPC_FAR *__RPC_FAR* /*ppchURLOut*/)
{
return E_NOTIMPL;
}
STDMETHODIMP CXTPToolTipContext::CHTMLToolTip::XDocHostUIHandler::FilterDataObject(
/* [in] */ IDataObject __RPC_FAR* /*pDO*/,
/* [out] */ IDataObject __RPC_FAR *__RPC_FAR* /*ppDORet*/)
{
return E_NOTIMPL;
}
CXTPToolTipContext::CHTMLToolTip::CHTMLToolTip(CXTPToolTipContext* pContext)
: CXTPToolTipContextToolTip(pContext)
{
AfxEnableControlContainer();
m_pBrowserApp = 0;
}
CXTPToolTipContext::CHTMLToolTip::~CHTMLToolTip()
{
SAFE_RELEASE(m_pBrowserApp);
}
CSize CXTPToolTipContext::CHTMLToolTip::GetToolSize(TOOLITEM* lpToolInfo)
{
m_bmpScreen.DeleteObject();
if (m_wndBrowser.GetSafeHwnd() == 0)
{
// create the control window
// AFX_IDW_PANE_FIRST is a safe but arbitrary ID
if (!m_wndBrowser.CreateControl(CLSID_WebBrowser, 0,
WS_VISIBLE | WS_CHILD, CRect(0, 0, 200, 200), this, AFX_IDW_PANE_FIRST))
{
return 0;
}
LPUNKNOWN lpUnk = m_wndBrowser.GetControlUnknown();
HRESULT hr = lpUnk->QueryInterface(IID_IWebBrowser2, (void**) &m_pBrowserApp);
if (!SUCCEEDED(hr) || !m_pBrowserApp)
{
m_pBrowserApp = NULL;
m_wndBrowser.DestroyWindow();
return 0;
}
IOleObject* spOleObj = NULL;
m_pBrowserApp->QueryInterface(IID_IOleObject, (void**)&spOleObj);
if (spOleObj)
{
spOleObj->SetClientSite((IOleClientSite*)GetInterface(&IID_IOleClientSite));
spOleObj->Release();
}
CString strFaceName = _T("Arial");
int nFontSize = 11;
LOGFONT lf;
if (m_pContext->GetFont()->GetLogFont(&lf))
{
strFaceName = lf.lfFaceName;
nFontSize = lf.lfHeight < 0 ? -lf.lfHeight : lf.lfHeight;
}
CString strBackColor; COLORREF clrBack = m_pContext->GetTipBkColor();
strBackColor.Format(_T("#%0.2x%0.2x%0.2x"), GetRValue(clrBack), GetGValue(clrBack), GetBValue(clrBack));
CString strBody;
strBody.Format(
_T("about:<head><style> body {font-family:%s; font-size:%i;}")
_T("table {font-family:%s; font-size:%i;}</style></head>")
_T("<body topmargin=0 leftmargin=0 bottommargin=0 rightmargin=0 bgColor=%s></body>"),
(LPCTSTR)strFaceName, nFontSize, (LPCTSTR)strFaceName, nFontSize, (LPCTSTR)strBackColor);
COleVariant varEmpty;
BSTR bstrBody = strBody.AllocSysString();
m_pBrowserApp->Navigate(bstrBody,
(VARIANT*)&varEmpty,
(VARIANT*)&varEmpty,
(VARIANT*)&varEmpty,
(VARIANT*)&varEmpty);
SysFreeString(bstrBody);
READYSTATE rs;
do
{
AfxGetApp()->PumpMessage();
m_pBrowserApp->get_ReadyState (&rs);
}
while (rs != READYSTATE_COMPLETE);
}
CString strText = GetToolText(lpToolInfo);
if (strText.IsEmpty())
return CSize(0);
IDispatch* lpDocument = NULL;
m_pBrowserApp->get_Document(&lpDocument);
if (lpDocument == 0)
return 0;
// Verify that what we get is a pointer to a IHTMLDocument2
// interface. To be sure, let's query for
// the IHTMLDocument2 interface (through smart pointers)
IHTMLDocument2* lpHTML = NULL;
lpDocument->QueryInterface(IID_IHTMLDocument2, (void**)&lpHTML);
if (lpHTML == 0)
{
lpDocument->Release();
return 0;
}
// The previous step is sufficient to keep Explorer aside
// without an explicit check against the loader module
// Extract the source code of the document
IHTMLElement* lpBody = NULL;
// Get the BODY object
HRESULT hr = lpHTML->get_body(&lpBody);
if (FAILED(hr) || (lpBody == 0))
{
lpHTML->Release();
lpDocument->Release();
return 0;
}
BSTR bstrText = strText.AllocSysString();
lpBody->put_innerHTML(bstrText);
SysFreeString(bstrText);
m_wndBrowser.MoveWindow(0, 0, 650, 200);
IHTMLTextContainer* lpHTMLContainer = NULL;
lpBody->QueryInterface(IID_IHTMLTextContainer, (void**)&lpHTMLContainer);
if (lpHTMLContainer == 0)
{
lpBody->Release();
lpHTML->Release();
lpDocument->Release();
return 0;
}
long nScrollHeight, nScrollWidth;
lpHTMLContainer->get_scrollHeight(&nScrollHeight);
int nBestWidth = m_pContext->GetMaxTipWidth();
int nBestHeight = nScrollHeight;
int cxFirst = 0;
int cxLast = nBestWidth * 2;
do
{
// Taking a guess
int cx = (cxFirst + cxLast) / 2;
m_wndBrowser.MoveWindow(0, 0, cx, nScrollHeight);
lpHTMLContainer->get_scrollHeight(&nScrollHeight);
lpHTMLContainer->get_scrollWidth(&nScrollWidth);
if (nScrollWidth > cx && nScrollHeight <= nBestHeight)
{
nBestWidth = nScrollWidth;
break;
}
if (nScrollHeight > nBestHeight)
{
// If the control required a larger height, then
// it's too narrow.
cxFirst = cx + 1;
}
else
{
// If the control didn't required a larger height,
// then it's too wide.
cxLast = cx - 1;
nBestWidth = cx;
}
}
while (cxFirst <= cxLast);
m_wndBrowser.MoveWindow(0, 0, nBestWidth, nBestHeight);
CSize sz(nBestWidth, nBestHeight);
CRect rcMargin = m_pContext->GetMargin();
#if 0
if (sz.cx > 0 && sz.cy > 0)
{
CWindowDC dcPaint(this);
CDC dc;
dc.CreateCompatibleDC(&dcPaint);
m_bmpScreen.CreateCompatibleBitmap(&dcPaint, sz.cx, sz.cy);
CBitmap* pOldBitmap = dc.SelectObject(&m_bmpScreen);
dc.FillSolidRect(0, 0, sz.cx, sz.cy, m_pContext->GetTipBkColor());
m_wndBrowser.SendMessage(WM_PRINT, (WPARAM)dc.GetSafeHdc(), PRF_CLIENT | PRF_CHILDREN);
dc.SelectObject(pOldBitmap);
}
m_wndBrowser.MoveWindow(0, 0, 0, 0);
#else
m_wndBrowser.MoveWindow(3 + rcMargin.left, 3 + rcMargin.top, nBestWidth, nBestHeight);
#endif
CSize szMargin(3 + rcMargin.left + rcMargin.right + 3, 3 + rcMargin.top + rcMargin.bottom + 3);
sz += szMargin;
lpHTMLContainer->Release();
lpBody->Release();
lpHTML->Release();
lpDocument->Release();
return sz;
}
void CXTPToolTipContext::CHTMLToolTip::DrawEntry(CDC* pDC, TOOLITEM* /*lpToolInfo*/, CRect rc)
{
rc.DeflateRect(m_pContext->GetMargin());
rc.DeflateRect(3, 3, 3, 3);
if (m_bmpScreen.GetSafeHandle())
{
pDC->DrawState(rc.TopLeft(), CSize(0, 0), &m_bmpScreen, DSS_NORMAL, 0);
}
}
void CXTPToolTipContext::CHTMLToolTip::OnVisibleChanged(BOOL bVisble)
{
if (!bVisble)
{
m_bmpScreen.DeleteObject();
}
}
#endif // _XTP_EXCLUDE_HTML
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CXTPToolTipContext::CXTPToolTipContext()
{
m_pToolTip = 0;
m_bShowTitleAndDescription = FALSE;
m_bShowImage = FALSE;
m_nImageSize = ICON_BIG;
m_nImageBase = 0;
m_toolStyle = xtpToolTipStandard;
m_nMaxTipWidth = ::GetSystemMetrics(SM_CXSCREEN) / 2;
ZeroMemory(&m_lastInfo, sizeof(m_lastInfo));
m_dwComCtlVersion = XTPSystemVersion()->GetComCtlVersion();
m_clrTipTextColor = m_clrTipBkColor = COLORREF_NULL;
m_nIconTitle = TTI_INFO;
m_dwStyle = TTS_NOPREFIX;
m_rcMargin.SetRect(0, 0, 0, 0);
m_nDelayAutoPop = m_nDelayInitial = m_nDelayReshow = -1;
NONCLIENTMETRICS ncm;
::ZeroMemory(&ncm, sizeof(NONCLIENTMETRICS));
ncm.cbSize = sizeof(NONCLIENTMETRICS);
VERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
sizeof(NONCLIENTMETRICS), &ncm, 0));
ncm.lfStatusFont.lfWeight = FW_NORMAL;
ncm.lfStatusFont.lfCharSet = XTPResourceManager()->GetFontCharset();
m_fnt.CreateFontIndirect(&ncm.lfStatusFont);
ncm.lfStatusFont.lfWeight = FW_BOLD;
m_fntTitle.CreateFontIndirect(&ncm.lfStatusFont);
m_bStripEllipsisFromToolTip = TRUE;
}
CXTPToolTipContext::~CXTPToolTipContext()
{
SAFE_DELETEWINDOW(m_pToolTip);
if (m_pModuleContext == this)
{
m_pModuleContext = 0;
}
}
BOOL CXTPToolTipContext::IsBalloonStyleSupported() const
{
return m_dwComCtlVersion >= VERSION_IE5;
}
void CXTPToolTipContext::ShowTitleAndDescription(BOOL bShowTitleAndDescription, int nIconTitle)
{
m_bShowTitleAndDescription = bShowTitleAndDescription;
m_nIconTitle = nIconTitle;
}
void CXTPToolTipContext::ShowImage(BOOL bShowImage, int nImageBase, int nImageSize)
{
m_bShowImage = bShowImage;
m_nImageBase = nImageBase;
m_nImageSize = nImageSize;
SAFE_DELETEWINDOW(m_pToolTip);
}
void CXTPToolTipContext::FillInToolInfo(TOOLINFO* pTI, HWND hWnd, CRect rect, INT_PTR nHit, const CString& strToolTip)
{
#if _MSC_VER < 1200 // MFC 5.0
if (pTI != NULL && pTI->cbSize >= sizeof(TOOLINFO))
#else
if (pTI != NULL && pTI->cbSize >= sizeof(XTP_TOOLTIP_TOOLINFO))
#endif
{
pTI->hwnd = hWnd;
pTI->rect = rect;
pTI->uId = nHit;
pTI->lpszText = (LPTSTR) ::calloc(strToolTip.GetLength() + 1, sizeof(TCHAR));
if (pTI->lpszText != NULL) STRCPY_S(pTI->lpszText, strToolTip.GetLength() + 1, (LPCTSTR)strToolTip);
}
}
void CXTPToolTipContext::FillInToolInfo(TOOLINFO* pTI, HWND hWnd, CRect rect, INT_PTR nHit,
const CString& strToolTip, const CString& strTitle, const CString& strDescription, CXTPImageManager* pImageManager)
{
FillInToolInfo(pTI, hWnd, rect, nHit, strToolTip);
if (pTI != NULL && pTI->cbSize == sizeof(XTP_TOOLTIP_TOOLINFO_EX))
{
XTP_TOOLTIP_CONTEXT* ptc = ((XTP_TOOLTIP_TOOLINFO_EX*)pTI)->pToolInfo;
if (!ptc)
return;
if (!strDescription.IsEmpty() && !strTitle.IsEmpty())
{
ptc->lpszDescription = (LPTSTR)::calloc(strDescription.GetLength() + 1, sizeof(TCHAR));
if (ptc->lpszDescription != NULL) STRCPY_S(ptc->lpszDescription, strDescription.GetLength() + 1, (LPCTSTR)strDescription);
ptc->lpszTitle = (LPTSTR)::calloc(strTitle.GetLength() + 1, sizeof(TCHAR));
if (ptc->lpszTitle != NULL) STRCPY_S(ptc->lpszTitle, strTitle.GetLength() + 1, (LPCTSTR)strTitle);
}
ptc->pImageManager = pImageManager;
}
}
void CXTPToolTipContext::SetMargin(LPCRECT lprc)
{
if (lprc)
{
m_rcMargin = *lprc;
if (m_pToolTip) m_pToolTip->DestroyWindow();
}
}
void CXTPToolTipContext::SetStyle(XTPToolTipStyle toolStyle)
{
if (m_toolStyle != toolStyle && (toolStyle != xtpToolTipBalloon || IsBalloonStyleSupported()))
{
m_toolStyle = toolStyle;
SAFE_DELETEWINDOW(m_pToolTip);
ModifyToolTipStyle(XTP_TTS_OFFICEFRAME | XTP_TTS_NOSHADOW, m_toolStyle == xtpToolTipOffice ? XTP_TTS_OFFICEFRAME | XTP_TTS_NOSHADOW : 0);
ModifyToolTipStyle(XTP_TTS_OFFICE2007FRAME, m_toolStyle == xtpToolTipResource ? XTP_TTS_OFFICE2007FRAME : 0);
}
}
XTPToolTipStyle CXTPToolTipContext::GetStyle() const
{
return m_toolStyle;
}
void CXTPToolTipContext::SetMaxTipWidth(int iWidth)
{
m_nMaxTipWidth = iWidth;
if (m_pToolTip) m_pToolTip->DestroyWindow();
}
int CXTPToolTipContext::GetMaxTipWidth() const
{
return m_nMaxTipWidth;
}
COLORREF CXTPToolTipContext::GetTipBkColor() const
{
return m_clrTipBkColor != COLORREF_NULL ? m_clrTipBkColor :GetXtremeColor(COLOR_INFOBK);
}
void CXTPToolTipContext::SetTipBkColor(COLORREF clr)
{
m_clrTipBkColor = clr;
if (m_pToolTip) m_pToolTip->DestroyWindow();
}
void CXTPToolTipContext::ModifyToolTipStyle(DWORD dwRemove, DWORD dwAdd)
{
DWORD dwStyle = (m_dwStyle & ~dwRemove) | dwAdd;
if (m_dwStyle != dwStyle)
{
m_dwStyle = dwStyle;
SAFE_DELETEWINDOW(m_pToolTip);
}
}
COLORREF CXTPToolTipContext::GetTipTextColor() const
{
return m_clrTipTextColor != COLORREF_NULL ? m_clrTipTextColor :
m_dwStyle & XTP_TTS_OFFICE2007FRAME ? RGB(76, 76, 76) : GetXtremeColor(COLOR_INFOTEXT);
}
void CXTPToolTipContext::SetTipTextColor(COLORREF clr)
{
m_clrTipTextColor = clr;
if (m_pToolTip) m_pToolTip->DestroyWindow();
}
void CXTPToolTipContext::SetDelayTime(DWORD dwDuration, int iTime)
{
switch (dwDuration)
{
case TTDT_RESHOW:
m_nDelayReshow = iTime;
break;
case TTDT_INITIAL:
m_nDelayInitial = iTime;
break;
case TTDT_AUTOPOP:
m_nDelayAutoPop = iTime;
break;
default:
ASSERT(FALSE);
}
if (m_pToolTip) m_pToolTip->DestroyWindow();
}
void CXTPToolTipContext::RelayToolTipMessage(CWnd* pToolTip, MSG* pMsg)
{
// transate the message based on TTM_WINDOWFROMPOINT
MSG msg = *pMsg;
msg.hwnd = (HWND)pToolTip->SendMessage(TTM_WINDOWFROMPOINT, 0, (LPARAM)&msg.pt);
CPoint pt = pMsg->pt;
if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST)
::ScreenToClient(msg.hwnd, &pt);
msg.lParam = MAKELONG(pt.x, pt.y);
// relay mouse event before deleting old tool
pToolTip->SendMessage(TTM_RELAYEVENT, 0, (LPARAM)&msg);
}
void CXTPToolTipContext::FilterToolTipMessage(CWnd* pWndHost, UINT message, WPARAM wParam, LPARAM lParam)
{
MSG msg;
msg.wParam = wParam;
msg.lParam = lParam;
msg.message = message;
msg.hwnd = pWndHost->m_hWnd;
GetCursorPos(&msg.pt);
FilterToolTipMessage(pWndHost, &msg);
}
void CXTPToolTipContext::FilterToolTipMessage(CWnd* pWndHost, MSG* pMsg)
{
FilterToolTipMessageHelper(pWndHost, pMsg, TRUE);
}
void PASCAL CXTPToolTipContext::FilterToolTipMessageStatic(MSG* pMsg, CWnd* pWnd)
{
if (m_pModuleContext)
{
m_pModuleContext->FilterToolTipMessageHelper(pWnd, pMsg, FALSE);
}
else
{
pWnd->FilterToolTipMessage(pMsg);
}
}
void CXTPToolTipContext::SetModuleToolTipContext()
{
AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
pModuleState->m_pfnFilterToolTipMessage = &CXTPToolTipContext::FilterToolTipMessageStatic;
m_pModuleContext = this;
}
CWnd* CXTPToolTipContext::CreateToolTip(CWnd* /*pOwner*/)
{
switch (m_toolStyle)
{
case xtpToolTipOffice:
return new CXTPToolTipContextToolTip(this);
case xtpToolTipRTF:
return new CRichEditToolTip(this);
case xtpToolTipLuna:
return new CLunaToolTip(this);
case xtpToolTipResource:
return new CXTPToolTipContextToolTip(this);
#ifndef _XTP_EXCLUDE_HTML
case xtpToolTipHTML:
return new CHTMLToolTip(this);
#endif
case xtpToolTipMarkup:
return new CMarkupToolTip(this);
}
return new CStandardToolTip();
}
void CXTPToolTipContext::SetToolTipCtrl(CXTPToolTipContextToolTip* pToolTipCtrl)
{
SAFE_DELETEWINDOW(m_pToolTip);
m_pToolTip = pToolTipCtrl;
}
void CXTPToolTipContext::CancelToolTips()
{
if (m_pToolTip->GetSafeHwnd() != NULL)
m_pToolTip->SendMessage(TTM_ACTIVATE, FALSE);
}
INT_PTR CXTPToolTipContext::OnToolHitTest(CWnd* pWnd, CPoint point, TOOLINFO* pToolInfo)
{
return pWnd->OnToolHitTest(point, pToolInfo);
}
void CXTPToolTipContext::FilterToolTipMessageHelper(CWnd* pWndHost, MSG* pMsg, BOOL bIgnoreFlags)
{
// this CWnd has tooltips enabled
UINT message = pMsg->message;
if ((message == WM_MOUSEMOVE || message == WM_NCMOUSEMOVE || message == WM_MOUSELEAVE ||
message == WM_LBUTTONUP || message == WM_RBUTTONUP ||
message == WM_MBUTTONUP) &&
(GetKeyState(VK_LBUTTON) >= 0 && GetKeyState(VK_RBUTTON) >= 0 &&
GetKeyState(VK_MBUTTON) >= 0))
{
if (!bIgnoreFlags)
{
// make sure that tooltips are not already being handled
CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);
while (pWnd != NULL && !(pWnd->m_nFlags & (WF_TOOLTIPS | WF_TRACKINGTOOLTIPS)))
{
pWnd = pWnd->GetParent();
}
if (pWnd != pWndHost)
{
return;
}
}
BOOL bTopParentActive = CXTPDrawHelpers::IsTopParentActive(pWndHost->GetSafeHwnd());
if (m_pToolTip->GetSafeHwnd() && m_pToolTip->IsWindowVisible() && !bTopParentActive)
{
m_pToolTip->SendMessage(TTM_ACTIVATE, FALSE);
return;
}
CWnd* pOwner = pWndHost->GetParentOwner();
if (m_pToolTip != NULL && m_pToolTip->GetOwner() != pOwner)
{
m_pToolTip->DestroyWindow();
}
if (m_pToolTip == NULL || m_pToolTip->GetSafeHwnd() == NULL)
{
if (m_pToolTip == NULL)
{
m_pToolTip = CreateToolTip(pOwner);
}
if (!m_pToolTip)
return;
if (!m_pToolTip->GetSafeHwnd())
{
if (DYNAMIC_DOWNCAST(CXTPToolTipContextToolTip, m_pToolTip))
{
((CXTPToolTipContextToolTip*)m_pToolTip)->Create(pOwner, m_dwStyle | TTS_ALWAYSTIP | TTS_NOPREFIX);
}
else if (DYNAMIC_DOWNCAST(CToolTipCtrl, m_pToolTip))
{
((CToolTipCtrl*)m_pToolTip)->Create(pOwner, m_dwStyle | TTS_ALWAYSTIP | TTS_NOPREFIX | (m_toolStyle == xtpToolTipBalloon ? TTS_BALLOON : 0));
}
else
{
ASSERT(FALSE);
return;
}
}
if (!m_pToolTip->GetSafeHwnd())
return;
m_pToolTip->SetFont(&m_fnt);
m_pToolTip->SendMessage(TTM_SETMAXTIPWIDTH, 0, m_nMaxTipWidth);
m_pToolTip->SendMessage(TTM_SETMARGIN, 0, (LPARAM)(LPRECT)&m_rcMargin);
if (m_clrTipBkColor != COLORREF_NULL)
m_pToolTip->SendMessage(TTM_SETTIPBKCOLOR, m_clrTipBkColor);
if (m_clrTipTextColor != COLORREF_NULL)
m_pToolTip->SendMessage(TTM_SETTIPTEXTCOLOR, m_clrTipTextColor);
if (m_nDelayReshow != -1)
m_pToolTip->SendMessage(TTM_SETDELAYTIME, TTDT_RESHOW, MAKELPARAM(m_nDelayReshow, 0));
if (m_nDelayInitial != -1)
m_pToolTip->SendMessage(TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(m_nDelayInitial, 0));
if (m_nDelayAutoPop != -1)
m_pToolTip->SendMessage(TTM_SETDELAYTIME, TTDT_AUTOPOP, MAKELPARAM(m_nDelayAutoPop, 0));
m_pToolTip->SendMessage(TTM_ACTIVATE, FALSE);
}
CWnd* pToolTip = m_pToolTip;
ASSERT_VALID(pToolTip);
ASSERT(::IsWindow(pToolTip->m_hWnd));
XTP_TOOLTIP_CONTEXT tc;
ZeroMemory(&tc, sizeof(tc));
// determine which tool was hit
CPoint point = pMsg->pt;
::ScreenToClient(pWndHost->m_hWnd, &point);
XTP_TOOLTIP_TOOLINFO_EX tiHit;
memset(&tiHit, 0, sizeof(XTP_TOOLTIP_TOOLINFO_EX));
tiHit.cbSize = m_bShowTitleAndDescription || m_bShowImage ? sizeof(XTP_TOOLTIP_TOOLINFO_EX) : sizeof(XTP_TOOLTIP_TOOLINFO);
tiHit.pToolInfo = &tc;
INT_PTR nHit = OnToolHitTest(pWndHost, point, (TOOLINFO*)&tiHit);
if (m_bShowTitleAndDescription && tc.lpszDescription &&
tc.lpszTitle && (_tcscmp(tc.lpszDescription, tc.lpszTitle) == 0))
{
free(tc.lpszDescription);
tc.lpszDescription = 0;
}
if ((m_dwStyle & TTS_NOPREFIX) == 0)
{
CXTPDrawHelpers::StripMnemonics(tiHit.lpszText);
CXTPDrawHelpers::StripMnemonics(tiHit.pToolInfo->lpszTitle);
}
if (m_bStripEllipsisFromToolTip)
{
XTPStripEllipsis(tiHit.lpszText);
XTPStripEllipsis(tiHit.pToolInfo->lpszTitle);
}
// build new toolinfo and if different than current, register it
BOOL bTipInfoChanged = m_lastInfo.uId != tiHit.uId || m_lastInfo.hwnd != tiHit.hwnd;
if (bTipInfoChanged || CRect(m_lastInfo.rect) != CRect(tiHit.rect))
{
if (m_lastInfo.cbSize >= sizeof(XTP_TOOLTIP_TOOLINFO) && !bTipInfoChanged)
pToolTip->SendMessage(TTM_DELTOOL, 0, (LPARAM)&m_lastInfo);
if (nHit != -1)
{
// add new tool and activate the tip
XTP_TOOLTIP_TOOLINFO_EX ti = tiHit;
ti.uFlags &= ~(TTF_NOTBUTTON | TTF_ALWAYSTIP);
VERIFY(pToolTip->SendMessage(TTM_ADDTOOL, 0, (LPARAM)&ti));
if ((m_toolStyle != xtpToolTipRTF && m_toolStyle != xtpToolTipHTML && m_toolStyle != xtpToolTipMarkup) && ((m_dwComCtlVersion >= VERSION_IE5) || (m_toolStyle != xtpToolTipStandard)))
{
if (m_bShowTitleAndDescription && tc.lpszDescription && tc.lpszTitle)
{
pToolTip->SendMessage(TTM_SETTITLE, m_nIconTitle, (LPARAM)(LPCTSTR)tc.lpszTitle);
ti.lpszText = tc.lpszDescription;
pToolTip->SendMessage(TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);
}
else
{
pToolTip->SendMessage(TTM_SETTITLE, 0, 0);
}
}
if (m_bShowImage)
{
CXTPImageManagerIcon* pIcon = NULL;
pIcon = tc.pImageManager ? tc.pImageManager->GetImage(UINT(m_nImageBase + nHit), m_nImageSize) : 0;
if (pIcon)
{
pToolTip->SendMessage(XTP_TTM_SETIMAGE, 0, (LPARAM)pIcon);
}
else
{
pToolTip->SendMessage(XTP_TTM_SETIMAGE, 0, NULL);
}
}
if ((tiHit.uFlags & TTF_ALWAYSTIP) || bTopParentActive)
{
// allow the tooltip to popup when it should
pToolTip->SendMessage(TTM_ACTIVATE, TRUE);
// bring the tooltip window above other popup windows
::SetWindowPos(pToolTip->m_hWnd, HWND_TOP, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOOWNERZORDER);
}
}
else
{
pToolTip->SendMessage(TTM_ACTIVATE, FALSE);
}
// relay mouse event before deleting old tool
RelayToolTipMessage(pToolTip, pMsg);
//// now safe to delete the old tool
if (m_lastInfo.cbSize >= sizeof(XTP_TOOLTIP_TOOLINFO) && bTipInfoChanged)
pToolTip->SendMessage(TTM_DELTOOL, 0, (LPARAM)&m_lastInfo);
m_lastInfo = tiHit;
}
else
{
// relay mouse events through the tooltip
if (nHit != -1)
RelayToolTipMessage(pToolTip, pMsg);
}
if ((tiHit.lpszText != LPSTR_TEXTCALLBACK) && (tiHit.hinst == 0))
free(tiHit.lpszText);
if (tc.lpszDescription != 0)
free(tc.lpszDescription);
if (tc.lpszTitle != 0)
free(tc.lpszTitle);
}
else
{
if (!bIgnoreFlags)
{
// make sure that tooltips are not already being handled
CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);
while (pWnd != NULL && pWnd != pWndHost && !(pWnd->m_nFlags & (WF_TOOLTIPS | WF_TRACKINGTOOLTIPS)))
{
pWnd = pWnd->GetParent();
}
if (pWnd != pWndHost)
return;
}
BOOL bKeys = (message >= WM_KEYFIRST && message <= WM_KEYLAST) ||
(message >= WM_SYSKEYFIRST && message <= WM_SYSKEYLAST);
if ((bKeys ||
(message == WM_LBUTTONDOWN || message == WM_LBUTTONDBLCLK) ||
(message == WM_RBUTTONDOWN || message == WM_RBUTTONDBLCLK) ||
(message == WM_MBUTTONDOWN || message == WM_MBUTTONDBLCLK) ||
(message == WM_NCLBUTTONDOWN || message == WM_NCLBUTTONDBLCLK) ||
(message == WM_NCRBUTTONDOWN || message == WM_NCRBUTTONDBLCLK) ||
(message == WM_NCMBUTTONDOWN || message == WM_NCMBUTTONDBLCLK)))
{
CancelToolTips();
}
}
}