Click here to Skip to main content
15,886,519 members
Articles / Desktop Programming / MFC

Microsoft WORD 2007 Style Semi-transparent Minibar

Rate me:
Please Sign up or sign in to vote.
4.96/5 (13 votes)
29 Jun 2010CPOL3 min read 33.8K   815   18  
Create a very basic Microsoft WORD 2007 style semi-transparent Minibar with tooltip like behaviour
#include "StdAfx.h"
#include "MiniToolBar.h"

#define ERR_MARGIN 1

CMiniToolBarBase::CMiniToolBarBase()
{
	m_pMiniToolBarWnd = NULL;

	m_bMouseTracking = FALSE;

	m_ptMouseCursor.x = -1;
	m_ptMouseCursor.y = -1;
	
	m_nDelayTime = DEFAULT_DELAY_TIME - ACTIVATION_DELAY_TIME;

	m_bLocked  = FALSE;
	m_bShow = FALSE;
	
	m_pMiniBarParentWnd = NULL;
	m_pPrevParentWnd = NULL;	

	m_rcHoverRect.SetRectEmpty();

	m_bHideOnClick = TRUE;
	m_bHideOnMouseLeave = FALSE;
}

CMiniToolBarBase::~CMiniToolBarBase(void)
{
}

void CMiniToolBarBase::MakeWindowTransparent(HWND hWnd, int nFactor, COLORREF rgbTransparencyKey /* = CLR_NONE*/)
{
	typedef BOOL (WINAPI* SLWA)(HWND, COLORREF, BYTE, DWORD);

	SLWA SetLayeredWindowAttributes = NULL;
	HMODULE hDLL = GetModuleHandle(_T("USER32.DLL"));
	SetLayeredWindowAttributes = (SLWA)GetProcAddress(hDLL, "SetLayeredWindowAttributes");
	if(SetLayeredWindowAttributes == NULL)
		return;

	DWORD dwStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
	dwStyle = dwStyle | WS_EX_LAYERED;
	SetWindowLong(hWnd, GWL_EXSTYLE, dwStyle);

	if(nFactor < 0)
	{
		SetLayeredWindowAttributes(hWnd, rgbTransparencyKey, 0, LWA_COLORKEY);
	}
	else
	{
		SetLayeredWindowAttributes(hWnd, 0, nFactor, LWA_ALPHA);
	}
}

BOOL CMiniToolBarBase::IsInSameRegion(CPoint& pt1, CPoint& pt2)
{
	BOOL bRet = FALSE;
	if( (abs(pt1.x - pt2.x) <= ERR_MARGIN) && (abs(pt1.y - pt2.y) <= ERR_MARGIN) )
	{
		bRet = TRUE;
	}

	return bRet;
}

void CMiniToolBarBase::ConvertToClientCoords(CPoint& ptMouseCursor)
{
	if(m_pMiniBarParentWnd != NULL)
	{
		m_pMiniBarParentWnd->ScreenToClient(&ptMouseCursor);
	}
}

void CMiniToolBarBase::Activate(CPoint ptMousePoint)
{
	// m_pMiniToolBarWnd should be defined and not NULLat this point	
	if(m_pMiniToolBarWnd && (m_pPrevParentWnd != m_pMiniBarParentWnd))
	{
		m_pPrevParentWnd = m_pMiniBarParentWnd;

		if(m_pMiniToolBarWnd && m_pMiniToolBarWnd->GetSafeHwnd() != NULL)
		{
			m_pMiniToolBarWnd->KillTimer(WM_ACTIVATE);
			m_pMiniToolBarWnd->KillTimer(WM_MOUSEMOVE);
			
			Lock(FALSE);
			m_bShow = FALSE;
			m_pMiniToolBarWnd->ShowWindow(SW_HIDE);
		}
	}	

	if(!m_bShow)
	{
		if(m_pMiniToolBarWnd == NULL)
		{
			CWnd* pWndFocus = CWnd::GetFocus();

			m_pMiniToolBarWnd = GetMiniToolBarWnd();
			if(m_pMiniToolBarWnd &&  m_pMiniToolBarWnd->GetSafeHwnd()
					&& pWndFocus != NULL)
			{
				pWndFocus->SetFocus();
			}
		}

		if(m_pMiniToolBarWnd && (m_pMiniToolBarWnd->GetSafeHwnd() != NULL))
		{
			if(!IsLocked())
			{
				if(m_pMiniBarParentWnd != NULL)
				{
					if(AllowActivation())
					{
						Lock(TRUE);						
						m_pMiniToolBarWnd->SetTimer(WM_ACTIVATE, ACTIVATION_DELAY_TIME, NULL);
					}
				}
			}		
		}
	}
	else // if showing
	{
		if(!NoHoverRects())
		{
			if(!PtInHoverRects(ptMousePoint))
			{
				HideMiniBar();
			}
		}
	}
}

void CMiniToolBarBase::ShowMiniBar(CPoint ptMouseCursor)
{	
	if(::IsWindow(m_pMiniToolBarWnd->GetSafeHwnd()) && (m_pMiniBarParentWnd != NULL))
	{
		int nSizeCursor = 20;

		ICONINFO iconInfo;
		if ( GetIconInfo(HICON(::GetCursor()), &iconInfo) )
		{
			nSizeCursor = 2 * iconInfo.yHotspot;
			
			::DeleteObject(iconInfo.hbmColor);
			::DeleteObject(iconInfo.hbmMask);
		}		
	
		CRect rcMiniDlg;
		m_pMiniToolBarWnd->GetWindowRect(rcMiniDlg);

		CSize size(rcMiniDlg.Width() + 1, rcMiniDlg.Height() + 1);

		// Show the tooltip
		m_pMiniBarParentWnd->ClientToScreen(&ptMouseCursor);
		
		// POSITION THE CURSOR PROPERLY
		CRect rcParent;
		m_pMiniBarParentWnd->GetWindowRect(rcParent);

		int nCursorX = ptMouseCursor.x;
		int nCursorY = ptMouseCursor.y;

		if((nCursorY + nSizeCursor + size.cy) < rcParent.bottom)
		{
			nCursorY += (nSizeCursor + 1);
		}
		else
		{
			nCursorY -= size.cy;
		}
		
		m_pMiniToolBarWnd->SetWindowPos(&CWnd::wndTop, nCursorX, nCursorY, 
			size.cx, size.cy, SWP_SHOWWINDOW | SWP_NOACTIVATE);

		OnShow(TRUE);
	}
}

void CMiniToolBarBase::HideMiniBar()
{
	if (::IsWindow(m_pMiniToolBarWnd->GetSafeHwnd()))
	{
		m_pMiniToolBarWnd->KillTimer(WM_ACTIVATE);
		m_pMiniToolBarWnd->KillTimer(WM_MOUSEMOVE);
		
		Lock(FALSE);

		m_pMiniToolBarWnd->ShowWindow( SW_HIDE );
		OnShow(FALSE);

		if((m_pMiniBarParentWnd != NULL) && ::IsWindow(m_pMiniBarParentWnd->GetSafeHwnd()))
		{	
			// It might happen that after the hiding of the mini bar
			// the user hasn't moved the mouse, so the call to Activate is not invoked
			// but the user is expecting that the minibar should pop up
			
			if(m_pMiniBarParentWnd != NULL)
			{				
				if(AllowActivation())
				{
					Lock(TRUE);						
					m_pMiniToolBarWnd->SetTimer(WM_ACTIVATE, ACTIVATION_DELAY_TIME, NULL);
				}
			}
		}
		else
		{
			m_pMiniBarParentWnd = NULL;
			m_pPrevParentWnd = NULL;
		}
	}
}

void CMiniToolBarBase::TrackMouseEvent()
{
	// Start tracking the mouse
	if (!m_bMouseTracking) 
	{
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.hwndTrack = m_pMiniToolBarWnd->GetSafeHwnd();
		tme.dwFlags = TME_LEAVE;
		tme.dwHoverTime = HOVER_DEFAULT;
		m_bMouseTracking = _TrackMouseEvent(&tme);
	}
}

void CMiniToolBarBase::HandleMouseMove(UINT nFlags, CPoint pt)
{
	TrackMouseEvent();
}

void CMiniToolBarBase::HandleMouseLeave()
{
	m_bMouseTracking = FALSE;

	if(m_bHideOnMouseLeave)
	{
		// should never arrive here if m_pMiniToolBarWnd = NULL
		ASSERT(m_pMiniToolBarWnd);
		if(m_pMiniToolBarWnd == NULL)
			return;

		CPoint pt;
		GetCursorPos(&pt);

		m_pMiniToolBarWnd->ScreenToClient(&pt);

		CRect	rect;
		m_pMiniToolBarWnd->GetClientRect(&rect);

		// This checking is necessary, because mouse leave might be invoked
		// if the mouse enters a child control of the m_pMiniToolBarWnd
		if(!rect.PtInRect(pt))
		{		
			HideMiniBar();
		}		
	}
}

void CMiniToolBarBase::HandleTimer(UINT_PTR nIDEvent)
{	
	// should never arrive here if m_pMiniToolBarWnd = NULL
	ASSERT(m_pMiniToolBarWnd);
	
	if(m_pMiniToolBarWnd == NULL)
		return;

	ASSERT(m_pMiniToolBarWnd ->GetSafeHwnd());
	if(m_pMiniToolBarWnd ->GetSafeHwnd() == NULL)
		return;

	if((m_pMiniBarParentWnd != NULL) 
		&& !::IsWindow(m_pMiniBarParentWnd->GetSafeHwnd()))
	{		
		m_pMiniToolBarWnd->KillTimer(nIDEvent);
		m_pMiniBarParentWnd = NULL;
		m_pPrevParentWnd = NULL;
		
		m_bShow = FALSE;
		m_pMiniToolBarWnd->ShowWindow( SW_HIDE );

		return;
	}

	if(nIDEvent == WM_ACTIVATE)
	{
		m_pMiniToolBarWnd->KillTimer(nIDEvent);

		CPoint ptMouseCursor;
		GetCursorPos(&ptMouseCursor);
		ConvertToClientCoords(ptMouseCursor);

		m_ptMouseCursor = ptMouseCursor;

		m_pMiniToolBarWnd->SetTimer(WM_MOUSEMOVE, GetDelayTime(), NULL);			
	}
	else if (nIDEvent == WM_MOUSEMOVE)
	{
		m_pMiniToolBarWnd->KillTimer(nIDEvent);

		CPoint ptMouseCursor;
		GetCursorPos(&ptMouseCursor);

		if(m_pMiniBarParentWnd != NULL)			
		{			
			CRect rcWnd;
			m_pMiniBarParentWnd->GetWindowRect(rcWnd);
			if((!rcWnd.PtInRect(ptMouseCursor)) || !AllowActivation())
			{
				m_ptMouseCursor.x = -1;
				m_ptMouseCursor.y = -1;
			}
		}

		ConvertToClientCoords(ptMouseCursor);

		if(IsInSameRegion(m_ptMouseCursor, ptMouseCursor))
		{
			if(NoHoverRects())
			{
				if(OnShowing())
				{
					ShowMiniBar(ptMouseCursor);					
				}
			}
			else if(PtInHoverRects(ptMouseCursor))
			{
				if(OnShowing())
				{
					ShowMiniBar(ptMouseCursor);					
				}
			}
			else
			{
				HideMiniBar();
			}
		}		
		else
		{
			HideMiniBar();
		}
	}	
}

void CMiniToolBarBase::HandleLButtonDown(UINT nFlags, CPoint pt)
{
	
}

void CMiniToolBarBase::HandleLButtonUp(UINT nFlags, CPoint pt)
{
	if(m_bHideOnClick)
		HideMiniBar();	
}

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 Code Project Open License (CPOL)


Written By
Technical Lead Kotha Technologies
Bangladesh Bangladesh
If you are not in - you are out !
- Chapter 1

Comments and Discussions