2016-01-27 09:11:59 +00:00
|
|
|
#pragma once
|
|
|
|
#include <wtl/atlgdi.h>
|
|
|
|
|
|
|
|
class CTitleTip : public CWindowImpl< CTitleTip >
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CTitleTip()
|
|
|
|
{
|
2021-04-12 11:35:39 +00:00
|
|
|
m_hWndParent = nullptr;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
~CTitleTip()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
DECLARE_WND_CLASS_EX( _T( "TitleTip" ), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_SAVEBITS, COLOR_WINDOW )
|
|
|
|
|
|
|
|
protected:
|
|
|
|
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;
|
|
|
|
|
|
|
|
public:
|
|
|
|
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 );
|
|
|
|
|
2021-04-12 11:35:39 +00:00
|
|
|
CRect Area(nullptr);
|
|
|
|
if ( CWindowImpl< CTitleTip >::Create( hWndParent, Area, nullptr, WS_POPUP, WS_EX_TOOLWINDOW | WS_EX_TOPMOST ) == nullptr )
|
2016-01-27 09:11:59 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-03-17 09:28:54 +00:00
|
|
|
// Create the tooltip
|
2016-01-27 09:11:59 +00:00
|
|
|
if ( !m_ttToolTip.Create( m_hWnd ) )
|
|
|
|
return FALSE;
|
|
|
|
m_ttToolTip.SetMaxTipWidth( SHRT_MAX );
|
|
|
|
|
2021-03-17 09:28:54 +00:00
|
|
|
// Get system message font
|
2016-01-27 09:11:59 +00:00
|
|
|
WTL::CLogFont logFont;
|
|
|
|
logFont.SetMessageBoxFont();
|
|
|
|
if ( !m_fntTitleFont.IsNull() )
|
|
|
|
m_fntTitleFont.DeleteObject();
|
2021-04-12 11:35:39 +00:00
|
|
|
return ( m_fntTitleFont.CreateFontIndirect( &logFont ) != nullptr );
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL Show( CRect& rcRect, LPCTSTR lpszItemText, LPCTSTR lpszToolTip )
|
|
|
|
{
|
2020-05-12 12:19:05 +00:00
|
|
|
stdstr strItemText;
|
|
|
|
strItemText.FromUTF16(lpszItemText);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
if ( !IsWindow() || strItemText.empty() )
|
|
|
|
return FALSE;
|
|
|
|
|
2020-05-12 12:19:05 +00:00
|
|
|
m_strToolTip.FromUTF16(lpszToolTip);
|
|
|
|
SetWindowText(strItemText.ToUTF16().c_str() );
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
CClientDC dcClient( m_hWnd );
|
|
|
|
|
|
|
|
HFONT hOldFont = dcClient.SelectFont( m_fntTitleFont );
|
|
|
|
|
|
|
|
CRect rcTextExtent( rcRect );
|
|
|
|
|
2021-03-17 09:28:54 +00:00
|
|
|
// Calculate item text extent
|
2020-05-12 12:19:05 +00:00
|
|
|
dcClient.DrawTextW( strItemText.ToUTF16().c_str(), (int)strItemText.length(), rcTextExtent, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_CALCRECT );
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
dcClient.SelectFont( hOldFont );
|
|
|
|
|
2021-03-17 09:28:54 +00:00
|
|
|
// Do not show title tip if entire text is visible
|
2016-01-27 09:11:59 +00:00
|
|
|
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() );
|
|
|
|
}
|
|
|
|
|
2021-03-17 09:28:54 +00:00
|
|
|
// Show title tip at new location
|
2021-04-12 11:35:39 +00:00
|
|
|
if ( !SetWindowPos( nullptr, rcRect.left - 4, rcRect.top, rcTextExtent.Width() + 11, rcRect.Height(), SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS ) )
|
2016-01-27 09:11:59 +00:00
|
|
|
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();
|
2021-04-12 11:35:39 +00:00
|
|
|
m_ttToolTip.m_hWnd = nullptr;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 ) );
|
|
|
|
|
2021-03-17 09:28:54 +00:00
|
|
|
// Forward notification through to parent
|
2016-01-27 09:11:59 +00:00
|
|
|
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 );
|
2021-04-12 11:35:39 +00:00
|
|
|
dcPaint.ExtTextOut( rcTitleTip.left, rcTitleTip.top, ETO_OPAQUE, rcTitleTip, _T( "" ), 0, nullptr );
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
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 );
|
|
|
|
|
2020-05-12 12:19:05 +00:00
|
|
|
dcPaint.DrawTextW( strItemText.ToUTF16().c_str(), (int)strItemText.length(), rcItemText, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER );
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
dcPaint.RestoreDC( nContextState );
|
|
|
|
}
|
|
|
|
};
|