www.pudn.com > OSDemo.rar > BalloonTip.cpp


/******************************************************************************* 
File:        BalloonTip.cpp 
 
Description: This file contains the module for creating a a balloon tip which can 
             be shown anywhere on a parent window 
              
 
Created: Nov 1, 2001 
Author:  Prateek Kaul 
e-mail:  kaulpr@yahoo.com 
 
Compiler with version number : Visual C++ 6.0 
 
 
Copyright (c) 2001, Prateek Kaul 
All rights Reserved. 
 
The copyright to the computer program(s) herein is the property of Prateek Kaul 
The program(s) may be used and/or copied only with the written permission of  
Prateek Kaul or in accordance with the terms and conditions stipulated 
in the agreement/contract under which the program(s) have been supplied. 
********************************************************************************/ 
 
#include "stdafx.h" 
#include "BalloonTip.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
 
/*---------------------------------------------------------------------------- 
   Message map 
----------------------------------------------------------------------------*/ 
 
BEGIN_MESSAGE_MAP(CBalloonTip, CFrameWnd) 
	//{{AFX_MSG_MAP(CBalloonTip) 
	ON_WM_TIMER() 
	ON_WM_LBUTTONDOWN() 
	ON_WM_RBUTTONDOWN() 
	ON_WM_CREATE() 
	ON_WM_PAINT() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::CBalloonTip() 
 
 Created: Nov 1, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Constructor 
 
 Parameters :  
    1. strMessage -> Message to be shown in the balloon 
    2. lf         -> LOGFONT structure from which the the message font 
                     will be created. 
    3. bBalloonUp -> Is the balloon up or upside down? 
     
 Return Value : none 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
CBalloonTip::CBalloonTip(CString strMessage, LOGFONT lf, BOOL bBalloonUp) 
{ 
    m_strMessage       = strMessage; 
    m_bBalloonUp       = bBalloonUp; 
     
    VERIFY(m_fontBalloonText.CreateFontIndirect(&lf)); 
} 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::~CBalloonTip() 
 
 Created: Nov 1, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Destructor 
 
 Parameters : none 
     
 Return Value : none 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
CBalloonTip::~CBalloonTip() 
{ 
} 
 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::Show() 
 
 Created: Nov 1, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Creates the CBalloonTip on the heap, forces heap creation 
 
 Parameters :  
    1. pt -> Point of the balloon tip 
    2. size -> Size of the window(width and height) 
    3. strMessage -> Message to be shown in the balloon 
    4. nSecs -> Seconds for which the balloon will be shown 
    5. lf -> LOGFONT structure from which the the message font 
             will be created. 
    6. bBalloonUp -> Is balloon up or upside down? 
 
 Return Value : void 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
CBalloonTip* CBalloonTip::Show(CPoint pt, CSize size, CString strMessage, LOGFONT lf, UINT nSecs, BOOL bBalloonUp) 
{ 
    if( CBalloonTip::nBalloonInstances != 0) // No window creation if already one instance of the class 
    { 
        return NULL; 
    } 
 
    CBalloonTip* pBalloonTip = new CBalloonTip(strMessage, lf, bBalloonUp); 
     
    CBalloonTip::nBalloonInstances = 1; // Only one instance of window possible. 
         
    UINT nRectLeft; 
	UINT nRectRight; 
	UINT nRectTop;   
	UINT nRectBottom; 
	 
    // Rectangle co-ordinates w.r.t balloon tip point 
	// Balloon tip at CPoint pt shold remain there without change in window size 
    if (bBalloonUp) 
    { 
        nRectLeft   = pt.x - (size.cx * 0.65); 
	    nRectRight  = pt.x + (size.cx * 0.35); 
	    nRectTop    = pt.y - size.cy; 
	    nRectBottom = pt.y; 
    } 
    else 
    { 
        nRectLeft   = pt.x - (size.cx * 0.35); 
	    nRectRight  = pt.x + (size.cx * 0.65); 
	    nRectTop    = pt.y; 
	    nRectBottom = pt.y + (size.cy); 
    } 
         
	pBalloonTip->Create(CRect(nRectLeft, nRectTop, nRectRight, nRectBottom));     
    pBalloonTip->MakeVisisble(nSecs); 
 
    return pBalloonTip; 
} 
 
 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::MakeVisible() 
 
 Created: Nov 1, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Shows the balloon and sets the timer for it's eventual destruction. 
 
 Parameters :  
    1. nSecs -> Seconds for the balloon to be shown 
     
 Return Value : none 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
void CBalloonTip::MakeVisisble(UINT nSecs) 
{ 
    ASSERT(nSecs > 0); 
 
    SetTimer(ID_TIMER, (nSecs * 1000), NULL); 
         
    CRect rect; 
    GetWindowRect(&rect); 
 
    // Caption bar height to offeset when the balloon is shown 
    int nCaptionBarSize = ::GetSystemMetrics(SM_CYCAPTION); 
    int nVerticalBorderSize = ::GetSystemMetrics(SM_CYSIZEFRAME); 
 
    if(m_bBalloonUp) 
    { 
        // Account for the missing title bar and border thickness in the 3rd parameter 
        // as the balloon shifts up by the height of title bar and window tickness 
        SetWindowPos( 
            &wndTopMost, 
            m_rectWindow.left,  
            (m_rectWindow.top + nCaptionBarSize + (2 * nVerticalBorderSize)), 
            m_rectWindow.right, 
            m_rectWindow.bottom,  
            SWP_SHOWWINDOW | SWP_NOACTIVATE 
        ); 
    } 
    else 
    { 
        // Account for the missing title bar and border thickness in the 3rd parameter 
        // as the balloon shifts up by the height of window tickness. 
        SetWindowPos( 
            &wndTopMost,  
            m_rectWindow.left, 
            m_rectWindow.top - nVerticalBorderSize, 
            m_rectWindow.right,  
            m_rectWindow.bottom, 
            SWP_SHOWWINDOW | SWP_NOACTIVATE 
        ); 
    } 
} 
 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::OnTimer() 
 
 Created: Nov 1, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Gets called by MFC for an WM_TIMER message 
 
 Parameters :  
        1. nIDEvent -> Timer ID     
 
 Return Value : void 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
void CBalloonTip::OnTimer(UINT nIDEvent)  
{ 
    KillTimer(ID_TIMER); 
    DestroyWindow(); 
} 
 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::OnLButtonDown() 
 
 Created: Nov 1, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Gets called by MFC for an WM_LBUTTONDOWN message 
 
 Parameters :  
        See MFC documentation 
 
 Return Value : void 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
void CBalloonTip::OnLButtonDown(UINT nFlags, CPoint point)  
{ 
   	KillTimer(ID_TIMER); 
    DestroyWindow(); 
} 
 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::OnRButtonDown() 
 
 Created: Nov 1, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Gets called by MFC for an WM_RBUTTONDOWN message 
 
 Parameters :  
        See MFC documentation 
 
 Return Value : void 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
void CBalloonTip::OnRButtonDown(UINT nFlags, CPoint point)  
{ 
    KillTimer(ID_TIMER); 
    DestroyWindow(); 
} 
 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::OnCreate() 
 
 Created: Nov 1, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Gets called by MFC for an WM_CREATE message 
 
 Parameters :  
        See MFC documentation 
 
 Return Value : int 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
int CBalloonTip::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1) 
    { 
        return -1; 
    } 
	 
    // Remove caption and thick frame for proper shading 
    ModifyStyle(WS_CAPTION | WS_THICKFRAME, 0);  
 
    CRect t_Rect; 
	GetClientRect(&t_Rect);  // Get the client rectangle to set the balloon region 
 
    if (m_bBalloonUp) 
    { 
        // Calculation of Text window, where to write text in the balloon 
        m_rectText.left   = t_Rect.Width() * 0.10;  
        m_rectText.right  = t_Rect.Width() * 0.90; 
        m_rectText.top    = t_Rect.Height() * 0.10;  
        m_rectText.bottom = t_Rect.Height()* 0.70;  
            	 
        // Create an elliptical region out of the client rectangle 
	    m_rgnRoundRect.CreateRoundRectRgn( 
            t_Rect.left,  
            t_Rect.top,  
            t_Rect.right, 
            t_Rect.bottom - (t_Rect.Height() * 0.25),  
            abs(t_Rect.left - t_Rect.right) * 0.18, 
            t_Rect.Height() * 0.25 
        ); 
    
        // Start the process of creating the balloon tip 
	    CPoint ptTri[4]; 
	    ptTri[0].x = (t_Rect.left) + (t_Rect.Width() * 0.93); 
	    ptTri[0].y = (t_Rect.bottom) - (t_Rect.Height() * 0.40); 
     
	    ptTri[1].x = (t_Rect.left) + (t_Rect.Width() * 0.65); 
	    ptTri[1].y = t_Rect.bottom; 
 
	    ptTri[2].x = (t_Rect.left) + (t_Rect.Width() * 0.70); 
	    ptTri[2].y = (t_Rect.bottom) - (t_Rect.Height() * 0.40); 
    
	    ptTri[3].x = (t_Rect.left) + (t_Rect.Width() * 0.93); 
	    ptTri[3].y = (t_Rect.bottom) - (t_Rect.Height() * 0.40); 
    
	    m_rgnTip.CreatePolygonRgn(ptTri, 3, ALTERNATE); 
    } 
    else 
    { 
        // Calculation of Text window, where to write text in the balloon 
        m_rectText.left   = t_Rect.Width() * 0.10; 
        m_rectText.right  = t_Rect.Width() * 0.90; 
        m_rectText.top    = t_Rect.Height() * 0.30; 
        m_rectText.bottom = t_Rect.Height() * 0.90; 
         
        // Create an elliptical region out of the client rectangle 
	    m_rgnRoundRect.CreateRoundRectRgn( 
            t_Rect.left, 
            t_Rect.bottom - (t_Rect.Height() * 0.75),  
            t_Rect.right,  
            t_Rect.bottom,  
            abs(t_Rect.left - t_Rect.right) * 0.18, 
            t_Rect.Height() * 0.25 
        ); 
 
        // Start the process of creating the balloon tip 
	    CPoint ptTri[4]; 
	    ptTri[0].x = (t_Rect.left) + (t_Rect.Width() * 0.07); 
	    ptTri[0].y = (t_Rect.Height() * 0.40); 
             
	    ptTri[1].x = (t_Rect.left) + (t_Rect.Width() * 0.35); 
	    ptTri[1].y = t_Rect.bottom - t_Rect.Height(); 
 
	    ptTri[2].x = (t_Rect.left) + (t_Rect.Width() * 0.30); 
	    ptTri[2].y = t_Rect.Height() * 0.40; 
            
	    ptTri[3].x = (t_Rect.left) + (t_Rect.Width() * 0.07); 
	    ptTri[3].y = t_Rect.Height() * 0.40; 
            
	    m_rgnTip.CreatePolygonRgn(ptTri, 3, ALTERNATE); 
    } 
     
    // Create the combined region with ellipse and tip 
	CRgn rgnComb;	 
     
    rgnComb.CreateRectRgn(t_Rect.left, t_Rect.top, t_Rect.right, t_Rect.bottom); 
		 
	int iRetComb = rgnComb.CombineRgn(&m_rgnTip, &m_rgnRoundRect, RGN_OR); 
	 
    if (iRetComb == ERROR) 
	{ 
        ::AfxMessageBox( "ERROR in Combining Region" ); 
		return -1; 
	} 
    
    SetWindowRgn(rgnComb.operator HRGN(), TRUE); 
	 
	return 0; 
} 
 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::OnPaint() 
 
 Created: Nov 1, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Gets called by MFC for a WM_PAINT message 
 
 Parameters :  
        See MFC documentation 
 
 Return Value : void 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
void CBalloonTip::OnPaint()  
{ 
	CPaintDC dc(this); // device context for painting 
 
    CRect t_Rect; 
    GetClientRect(&t_Rect); 
 
    // Get the total balloon, inclding all cut out regions 
	CRgn rgnComb;	 
    rgnComb.CreateRectRgn(t_Rect.left, t_Rect.top, t_Rect.right, t_Rect.bottom); 
    
    // Create a balloon tip from this total region 
    int iRetComb = rgnComb.CombineRgn(&m_rgnTip, &m_rgnRoundRect, RGN_OR ); 
    if (iRetComb == ERROR) 
	{ 
        ::AfxMessageBox( "ERROR in Combining Region" ); 
        return; 
	} 
 
	CBrush brOutlineBrush; 
    brOutlineBrush.CreateSolidBrush(RGB(0, 0, 0)); // blue 
    
    CBrush brFillBrush; 
    brFillBrush.CreateSolidBrush(RGB(249, 254, 188)); // light yellow 
    
    
    dc.FillRgn(&rgnComb, &brFillBrush);  // Fill the balloon 
    dc.FrameRgn(&rgnComb, &brOutlineBrush, 2, 1); // Outline the balloon 
 
    int nBkMode          = dc.SetBkMode(TRANSPARENT); 
    COLORREF clrPrevious =  dc.SetTextColor(RGB(255, 0, 0)); 
    CFont *pFont = dc.SelectObject(&m_fontBalloonText); 
    
    CSize czTextWidth = dc.GetTextExtent(m_strMessage); 
    
    if (czTextWidth.cx < m_rectText.Width()) 
    { 
       dc.DrawText(m_strMessage, m_rectText, DT_CENTER | DT_VCENTER | DT_SINGLELINE); 
    } 
      
    else 
    { 
        dc.DrawText(m_strMessage, m_rectText, DT_CENTER | DT_WORDBREAK); 
    } 
     
    // Restore the DC to its oroginal state 
    dc.SelectObject(pFont); 
    dc.SetBkColor(nBkMode); 
    dc.SetTextColor(clrPrevious); 
} 
 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::PreCreateWindow(CREATESTRUCT& cs) 
 
 Created: Dec 07, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Called by MFC when a before WM_CREATE message is received by the 
            window. 
 
            We override this function so that the window so created is not 
            visible in the Taskbar. We make this window the child of an 
            invisible parent m_wndInvisibleParent. 
 
 Parameters : Look in MFC documentation 
 
 Return Value : BOOL 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
BOOL CBalloonTip::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	if (!CWnd::PreCreateWindow(cs)) 
    { 
		return FALSE; 
    } 
 
 	// Create invisible parent window 
 	if (!::IsWindow(m_wndInvisibleParent.m_hWnd)) 
 	{ 
        // Try creating the invisible parent window 
        PCSTR pstrOwnerClass = ::AfxRegisterWndClass(0); 
        
        BOOL bError = m_wndInvisibleParent.CreateEx( 
                          0, 
                          pstrOwnerClass,  
                          _T(""),  
                          WS_POPUP, 
				          0, 
                          0, 
                          0, 
                          0, 
				          NULL, 
                          0 
                      ); 
 
        if (bError == FALSE) 
        { 
			return FALSE; 
        } 
 	} 
 
    // Set the invisible window as the parent of "this" window 
	cs.hwndParent = m_wndInvisibleParent.m_hWnd; 
 
	return TRUE; 
} 
 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::Create() 
 
 Created: Dec 07, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Called by the static CBalloonTip to create a Windows(R) window  
 
 Parameters : rect-> a rectangle in screen co ordinates where the balloon 
              will be displayed. 
 
 Return Value : BOOL 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
BOOL CBalloonTip::Create(CRect rect) 
{ 
    m_rectWindow = rect; 
 
    PCSTR pstrOwnerClass = ::AfxRegisterWndClass(0); 
    BOOL bResult = CFrameWnd::Create(pstrOwnerClass, NULL, WS_OVERLAPPED, m_rectWindow); 
     
    return bResult; 
} 
 
 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::Hide() 
 
 Created: Dec 08, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Provided to destroy a balloon before it self destructs. If it is  
            already hidden, it will have no effect. 
             
 Parameters : CBalloonTip* 
 
 Return Value : void 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
void CBalloonTip::Hide(CBalloonTip* pBalloonTip) 
{ 
    if (CBalloonTip::nBalloonInstances != 0) 
    { 
        pBalloonTip->ShowWindow(SW_HIDE); 
        pBalloonTip->KillTimer(ID_TIMER); 
        pBalloonTip->DestroyWindow(); 
    } 
} 
 
 
 
 
/*----------------------------------------------------------------------------- 
  int CBalloonTip::nBalloonInstances; 
 
  Abstract: Used for preventing more than one instance of the class CBalloonTip 
-----------------------------------------------------------------------------*/ 
 
int CBalloonTip::nBalloonInstances = 0; 
 
 
 
 
/*----------------------------------------------------------------------------- 
 Function : CBalloonTip::PostNcDestroy() 
 
 Created: Dec 08, 2001 
 Author:  Prateek Kaul 
 e-mail:  kaulpr@yahoo.com 
 
 Abstract : Last function the window receives when it is destroyed. 
            Used for resetting the counter CBalloonTip::nBalloonInstances to 0, 
            so that a new instance of this class can be created. 
             
 Parameters : void 
 
 Return Value : void 
 
 Exceptions : none 
 
 Revisions : none 
----------------------------------------------------------------------------*/ 
 
void CBalloonTip::PostNcDestroy() 
{ 
    CBalloonTip::nBalloonInstances = 0; 
    CFrameWnd::PostNcDestroy(); 
}