Click here to Skip to main content
15,885,771 members
Articles / Desktop Programming / WTL

Create a Convenient Toolbar Assistant Using WTL

Rate me:
Please Sign up or sign in to vote.
4.88/5 (30 votes)
11 Mar 2008GPL33 min read 61K   2.5K   58  
A more easy to generate toolbar images.
#pragma once

#include <atltheme.h>

class CTitleTip : public CWindowImpl< CTitleTip >
{
public:
	CTitleTip()
	{
		m_hWndParent = NULL;
		m_bShowThemed = TRUE;
	}
	
	~CTitleTip()
	{
	}
	
	DECLARE_WND_CLASS_EX( _T( "TitleTip" ), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_SAVEBITS, COLOR_WINDOW )

protected:
	HWND m_hWndParent;
	BOOL m_bShowThemed;
	CString 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, BOOL bShowThemed )
	{
		m_hWndParent = hWndParent;
		m_bShowThemed = bShowThemed;
		
		m_rgbBackground = GetSysColor( COLOR_INFOBK );
		m_rgbTextColour = ( m_bShowThemed && CTheme::IsThemingSupported() ) ? GetSysColor( COLOR_WINDOWTEXT ) : 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 );
		
		if ( CWindowImpl< CTitleTip >::Create( hWndParent, NULL, NULL, WS_POPUP, WS_EX_TOOLWINDOW | WS_EX_TOPMOST ) == NULL )
			return FALSE;
		
		// create the tooltip
		if ( !m_ttToolTip.Create( m_hWnd ) )
			return FALSE;
		m_ttToolTip.SetMaxTipWidth( SHRT_MAX );
		
		// get system message font
		CLogFont logFont;
		logFont.SetMessageBoxFont();
		if ( !m_fntTitleFont.IsNull() )
			m_fntTitleFont.DeleteObject();
		return ( m_fntTitleFont.CreateFontIndirect( &logFont ) != NULL );
	}
	
	BOOL Show( CRect& rcRect, LPCTSTR lpszItemText, LPCTSTR lpszToolTip )
	{
		CString strItemText = lpszItemText;
		
		if ( !IsWindow() || strItemText.IsEmpty() )
			return FALSE;
		
		m_strToolTip = lpszToolTip;
		SetWindowText( strItemText );
		
		CClientDC dcClient( m_hWnd );
		
		HFONT hOldFont = dcClient.SelectFont( m_fntTitleFont );
			
		CRect rcTextExtent( rcRect );
				
		// calculate item text extent...
		dcClient.DrawText( strItemText, strItemText.GetLength(), rcTextExtent, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_CALCRECT );
		
		dcClient.SelectFont( hOldFont );
		
		// do not show titletip if entire text is visible
		if ( rcTextExtent.Width() <= rcRect.Width() - 1 )
			return FALSE;
		
		if ( m_strToolTip.IsEmpty() )
			m_ttToolTip.Activate( FALSE );
		else
		{
			m_ttToolTip.Activate( TRUE );
			m_ttToolTip.AddTool( m_hWnd, (LPCTSTR)m_strToolTip.Left( SHRT_MAX ) );
		}
		
		// show titletip at new location
		if ( !SetWindowPos( NULL, 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_EX()
	
	void OnDestroy()
	{
		if ( m_ttToolTip.IsWindow() )
			m_ttToolTip.DestroyWindow();
		m_ttToolTip.m_hWnd = NULL;
	}
	
	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 = wndParent.SendMessage( WM_NCHITTEST, 0, MAKELPARAM( ptMouse.x, ptMouse.y ) );
		
		// forward notifcation 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 )
	{
		CPaintDC dcPaint( m_hWnd );
		
		int nContextState = dcPaint.SaveDC();
		
		CRect rcClient;
		GetClientRect( rcClient );
		
		CRect rcTitleTip( rcClient );
					
		if ( m_bShowThemed && CTheme::IsThemingSupported() )
		{
			CPen penBorder;
			penBorder.CreatePen( PS_SOLID, 1, m_rgbBorderOuter );
			
			dcPaint.SelectPen( penBorder );
			dcPaint.SelectStockBrush( HOLLOW_BRUSH );
			
			dcPaint.RoundRect( rcTitleTip, CPoint( 5, 5 ) );
			rcTitleTip.DeflateRect( 1, 1 );
			
			CPen penInnerBorder;
			penInnerBorder.CreatePen( PS_SOLID, 1, m_rgbBorderInner );
			dcPaint.SelectPen( penInnerBorder );
			
			dcPaint.RoundRect( rcTitleTip, CPoint( 2, 2 ) );
			rcTitleTip.DeflateRect( 1, 1 );
			
			GRADIENT_RECT grdRect = { 0, 1 };
			TRIVERTEX triVertext[ 2 ] = {
											rcTitleTip.left,
											rcTitleTip.top,
											GetRValue( m_rgbBackgroundTop ) << 8,
											GetGValue( m_rgbBackgroundTop ) << 8,
											GetBValue( m_rgbBackgroundTop ) << 8,
											0x0000,			
											rcTitleTip.right,
											rcTitleTip.bottom,
											GetRValue( m_rgbBackgroundBottom ) << 8,
											GetGValue( m_rgbBackgroundBottom ) << 8,
											GetBValue( m_rgbBackgroundBottom ) << 8,
											0x0000
										};
			
			dcPaint.GradientFill( triVertext, 2, &grdRect, 1, GRADIENT_FILL_RECT_V );
		}
		else
		{
			dcPaint.SetBkColor( m_rgbBackground );
			dcPaint.ExtTextOut( rcTitleTip.left, rcTitleTip.top, ETO_OPAQUE, rcTitleTip, _T( "" ), 0, NULL );
			
			CBrush bshTitleFrame;
			bshTitleFrame.CreateSolidBrush( m_rgbTextColour );
			dcPaint.FrameRect( rcTitleTip, bshTitleFrame );
		}
		
		int nTextLength = GetWindowTextLength() + 1;
		CString strItemText;
		GetWindowText( strItemText.GetBuffer( nTextLength ), nTextLength );
		strItemText.ReleaseBuffer();
		
		dcPaint.SelectFont( m_fntTitleFont );
		dcPaint.SetTextColor( m_rgbTextColour );
		dcPaint.SetBkMode( TRANSPARENT );
		
		CRect rcItemText( rcClient );
		rcItemText.OffsetRect( 4, 0 );
		
		dcPaint.DrawText( strItemText, strItemText.GetLength(), rcItemText, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER );
	
		dcPaint.RestoreDC( nContextState );
	}
};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Team Leader GreatStar Software Technology Development CO., Ltd
China China
Upcoming product - Roya LiveWorld
Integrate video, audio and data with powerful collaborative communication technologies.
Hope that we can let people around the world to communicate more convenient!

The wise choice of the 10 reasons
1, single server to support users far more than the general similar products
2, years of accumulation of professional video technology development, so that the effect of more realistic video
3, even if the dial-up Internet access, can also be smooth, clear, quality sound effects
4, adapt to the various complex network environment
5, the powerful, friendly interface, easy to operate
6, better stability and better, higher security
7, Universal Network File Sharing Technology (Global original) can be simple and efficient sharing of arbitrary files
8, close to the ordinary user's design
9, the hardware and software requirements are very low, server can even run in the virtual machine.
10, more personalized service

http://www.soft234.com

Comments and Discussions