2016-01-27 09:11:59 +00:00
|
|
|
#pragma once
|
|
|
|
#include <wtl/atlgdi.h>
|
|
|
|
|
2022-09-26 02:31:54 +00:00
|
|
|
class CTitleTip : public CWindowImpl<CTitleTip>
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
public:
|
2022-09-26 02:31:54 +00:00
|
|
|
CTitleTip()
|
|
|
|
{
|
|
|
|
m_hWndParent = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
~CTitleTip()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
DECLARE_WND_CLASS_EX(_T( "TitleTip" ), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_SAVEBITS, COLOR_WINDOW)
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
protected:
|
2022-09-26 02:31:54 +00:00
|
|
|
HWND m_hWndParent;
|
|
|
|
stdstr m_strToolTip;
|
|
|
|
|
|
|
|
COLORREF m_rgbBackground;
|
|
|
|
COLORREF m_rgbTextColour;
|
|
|
|
COLORREF m_rgbBorderOuter;
|
|
|
|
COLORREF m_rgbBorderInner;
|
|
|
|
COLORREF m_rgbBackgroundTop;
|
|
|
|
COLORREF m_rgbBackgroundBottom;
|
|
|
|
|
|
|
|
CFont m_fntTitleFont;
|
|
|
|
CToolTipCtrl m_ttToolTip;
|
|
|
|
|
2016-01-27 09:11:59 +00:00
|
|
|
public:
|
2022-09-26 02:31:54 +00:00
|
|
|
BOOL Create(HWND hWndParent)
|
|
|
|
{
|
|
|
|
m_hWndParent = hWndParent;
|
|
|
|
|
|
|
|
m_rgbBackground = GetSysColor(COLOR_INFOBK);
|
|
|
|
m_rgbTextColour = GetSysColor(COLOR_INFOTEXT);
|
|
|
|
m_rgbBorderOuter = RGB(220, 220, 220);
|
|
|
|
m_rgbBorderInner = RGB(245, 245, 245);
|
|
|
|
m_rgbBackgroundTop = RGB(250, 250, 250);
|
|
|
|
m_rgbBackgroundBottom = RGB(235, 235, 235);
|
|
|
|
|
|
|
|
CRect Area(nullptr);
|
|
|
|
if (CWindowImpl<CTitleTip>::Create(hWndParent, Area, nullptr, WS_POPUP, WS_EX_TOOLWINDOW | WS_EX_TOPMOST) == nullptr)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
// Create the tooltip
|
|
|
|
if (!m_ttToolTip.Create(m_hWnd))
|
|
|
|
return FALSE;
|
|
|
|
m_ttToolTip.SetMaxTipWidth(SHRT_MAX);
|
|
|
|
|
|
|
|
// Get system message font
|
|
|
|
WTL::CLogFont logFont;
|
|
|
|
logFont.SetMessageBoxFont();
|
|
|
|
if (!m_fntTitleFont.IsNull())
|
|
|
|
m_fntTitleFont.DeleteObject();
|
|
|
|
return (m_fntTitleFont.CreateFontIndirect(&logFont) != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL Show(CRect & rcRect, LPCTSTR lpszItemText, LPCTSTR lpszToolTip)
|
|
|
|
{
|
2020-05-12 12:19:05 +00:00
|
|
|
stdstr strItemText;
|
|
|
|
strItemText.FromUTF16(lpszItemText);
|
2022-09-26 02:31:54 +00:00
|
|
|
|
|
|
|
if (!IsWindow() || strItemText.empty())
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
m_strToolTip.FromUTF16(lpszToolTip);
|
|
|
|
SetWindowText(strItemText.ToUTF16().c_str());
|
|
|
|
|
|
|
|
CClientDC dcClient(m_hWnd);
|
|
|
|
|
|
|
|
HFONT hOldFont = dcClient.SelectFont(m_fntTitleFont);
|
|
|
|
|
|
|
|
CRect rcTextExtent(rcRect);
|
|
|
|
|
|
|
|
// Calculate item text extent
|
|
|
|
dcClient.DrawTextW(strItemText.ToUTF16().c_str(), (int)strItemText.length(), rcTextExtent, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_CALCRECT);
|
|
|
|
|
|
|
|
dcClient.SelectFont(hOldFont);
|
|
|
|
|
|
|
|
// Do not show title tip if entire text is visible
|
|
|
|
if (rcTextExtent.Width() <= rcRect.Width() - 1)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (m_strToolTip.empty())
|
|
|
|
m_ttToolTip.Activate(FALSE);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_ttToolTip.Activate(TRUE);
|
|
|
|
m_ttToolTip.AddTool(m_hWnd, (LPCTSTR)m_strToolTip.substr(0, SHRT_MAX).c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show title tip at new location
|
|
|
|
if (!SetWindowPos(nullptr, rcRect.left - 4, rcRect.top, rcTextExtent.Width() + 11, rcRect.Height(), SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
SetCapture();
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL Hide()
|
|
|
|
{
|
|
|
|
if (GetCapture() == m_hWnd)
|
|
|
|
ReleaseCapture();
|
|
|
|
return IsWindow() ? ShowWindow(SW_HIDE) : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BEGIN_MSG_MAP_EX(CTitleTip)
|
|
|
|
MSG_WM_DESTROY(OnDestroy)
|
|
|
|
MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
|
|
|
|
MSG_WM_ERASEBKGND(OnEraseBkgnd)
|
|
|
|
MSG_WM_PAINT(OnPaint)
|
|
|
|
END_MSG_MAP()
|
|
|
|
|
|
|
|
void OnDestroy()
|
|
|
|
{
|
|
|
|
if (m_ttToolTip.IsWindow())
|
|
|
|
m_ttToolTip.DestroyWindow();
|
|
|
|
m_ttToolTip.m_hWnd = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
LRESULT OnMouseRange(UINT nMessage, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
SetMsgHandled(FALSE);
|
|
|
|
|
|
|
|
if (m_ttToolTip.IsWindow())
|
|
|
|
{
|
|
|
|
MSG msgRelay = {m_hWnd, nMessage, wParam, lParam};
|
|
|
|
m_ttToolTip.RelayEvent(&msgRelay);
|
|
|
|
}
|
|
|
|
|
|
|
|
CPoint ptMouse(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
|
|
|
ClientToScreen(&ptMouse);
|
|
|
|
|
|
|
|
if (nMessage == WM_MOUSEMOVE)
|
|
|
|
{
|
|
|
|
CRect rcWindow;
|
|
|
|
GetWindowRect(rcWindow);
|
|
|
|
if (!rcWindow.PtInRect(ptMouse))
|
|
|
|
Hide();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
CWindow wndParent(m_hWndParent);
|
|
|
|
UINT nHitTest = (UINT)wndParent.SendMessage(WM_NCHITTEST, 0, MAKELPARAM(ptMouse.x, ptMouse.y));
|
|
|
|
|
|
|
|
// Forward notification through to parent
|
|
|
|
if (nHitTest == HTCLIENT)
|
|
|
|
{
|
|
|
|
wndParent.ScreenToClient(&ptMouse);
|
|
|
|
wndParent.PostMessage(nMessage, wParam, MAKELPARAM(ptMouse.x, ptMouse.y));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (nMessage)
|
|
|
|
{
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
wndParent.PostMessage(WM_NCLBUTTONDOWN, nHitTest, MAKELPARAM(ptMouse.x, ptMouse.y));
|
|
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
|
|
wndParent.PostMessage(WM_NCLBUTTONUP, nHitTest, MAKELPARAM(ptMouse.x, ptMouse.y));
|
|
|
|
break;
|
|
|
|
case WM_LBUTTONDBLCLK:
|
|
|
|
wndParent.PostMessage(WM_NCLBUTTONDBLCLK, nHitTest, MAKELPARAM(ptMouse.x, ptMouse.y));
|
|
|
|
break;
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
wndParent.PostMessage(WM_NCRBUTTONDOWN, nHitTest, MAKELPARAM(ptMouse.x, ptMouse.y));
|
|
|
|
break;
|
|
|
|
case WM_RBUTTONUP:
|
|
|
|
wndParent.PostMessage(WM_NCRBUTTONUP, nHitTest, MAKELPARAM(ptMouse.x, ptMouse.y));
|
|
|
|
break;
|
|
|
|
case WM_RBUTTONDBLCLK:
|
|
|
|
wndParent.PostMessage(WM_NCRBUTTONDBLCLK, nHitTest, MAKELPARAM(ptMouse.x, ptMouse.y));
|
|
|
|
break;
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
wndParent.PostMessage(WM_NCMBUTTONDOWN, nHitTest, MAKELPARAM(ptMouse.x, ptMouse.y));
|
|
|
|
break;
|
|
|
|
case WM_MBUTTONUP:
|
|
|
|
wndParent.PostMessage(WM_NCMBUTTONUP, nHitTest, MAKELPARAM(ptMouse.x, ptMouse.y));
|
|
|
|
break;
|
|
|
|
case WM_MBUTTONDBLCLK:
|
|
|
|
wndParent.PostMessage(WM_NCMBUTTONDBLCLK, nHitTest, MAKELPARAM(ptMouse.x, ptMouse.y));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL OnEraseBkgnd(HDC /*dc*/)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnPaint(HDC /*dc*/)
|
|
|
|
{
|
|
|
|
CPaintDC dcPaint(m_hWnd);
|
|
|
|
|
|
|
|
int nContextState = dcPaint.SaveDC();
|
|
|
|
|
|
|
|
CRect rcClient;
|
|
|
|
GetClientRect(rcClient);
|
|
|
|
|
|
|
|
CRect rcTitleTip(rcClient);
|
|
|
|
|
|
|
|
dcPaint.SetBkColor(m_rgbBackground);
|
|
|
|
dcPaint.ExtTextOut(rcTitleTip.left, rcTitleTip.top, ETO_OPAQUE, rcTitleTip, _T( "" ), 0, nullptr);
|
|
|
|
|
|
|
|
CBrush bshTitleFrame;
|
|
|
|
bshTitleFrame.CreateSolidBrush(m_rgbTextColour);
|
|
|
|
dcPaint.FrameRect(rcTitleTip, bshTitleFrame);
|
|
|
|
|
|
|
|
int nTextLength = GetWindowTextLength();
|
|
|
|
stdstr strItemText;
|
|
|
|
strItemText.reserve(nTextLength + 1);
|
|
|
|
strItemText.resize(nTextLength);
|
|
|
|
GetWindowText((LPTSTR)strItemText.c_str(), nTextLength + 1);
|
|
|
|
|
|
|
|
dcPaint.SelectFont(m_fntTitleFont);
|
|
|
|
dcPaint.SetTextColor(m_rgbTextColour);
|
|
|
|
dcPaint.SetBkMode(TRANSPARENT);
|
|
|
|
|
|
|
|
CRect rcItemText(rcClient);
|
|
|
|
rcItemText.OffsetRect(4, 0);
|
|
|
|
|
|
|
|
dcPaint.DrawTextW(strItemText.ToUTF16().c_str(), (int)strItemText.length(), rcItemText, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
|
|
|
|
|
|
|
|
dcPaint.RestoreDC(nContextState);
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
};
|