⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 a17too~1.cpp

📁 visual c++ 时尚编程百例 全部源代码
💻 CPP
字号:
//
// ToolTipWnd.cpp : implementation file
//

#include "stdafx.h"

#include "A17tooltip.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif



// --------------------------------------------------------------------------
CToolTipWnd::CToolTipWnd()
{
	m_lpWndCls = AfxRegisterWndClass(0);
	m_bStuck = false;
	m_bSkipNextMove = false;
	m_pCurrwnd = NULL;
	m_iTimer = 0;
	m_iTimer2 = 0;
	m_iDelay = 5;				// seconds
	m_iDelayShow = 1000;		// ms

	//Defaults
	m_clrFrameColor = RGB(0, 0, 255);  //blue
	m_clrBkColor = RGB(249, 254, 188); //light yellow
	m_iWidth = 160;
	m_iHeight = 80;

	m_clrTextColor = RGB( 0, 0, 0 ); //black
	m_iFontHeight = 14;
	m_strFontName = "Arial";
	m_strText = "";
}


// --------------------------------------------------------------------------
CToolTipWnd::~CToolTipWnd()
{
	if (m_iTimer > 0)
		KillTimer();

	if (m_iTimer2 > 0)
		KillShowTimer();

	// delete all BTOOLINFO entries put in the map
	BTOOLINFO*	stToolInfo = NULL;
	HWND*		pWnd;	// dummy
	for (POSITION pos = m_toolPtr.GetStartPosition(); pos != NULL;)
	{
		m_toolPtr.GetNextAssoc(pos, (void *&)pWnd, (void *&)stToolInfo);
		delete stToolInfo;
	}
	m_toolPtr.RemoveAll();
}


// --------------------------------------------------------------------------
BEGIN_MESSAGE_MAP(CToolTipWnd, CWnd)
	//{{AFX_MSG_MAP(CToolTipWnd)
	ON_WM_PAINT()
	ON_WM_CREATE()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


// --------------------------------------------------------------------------
BOOL CToolTipWnd::Create( CWnd* pParentWnd ) 
{
	BOOL bRet = CWnd::CreateEx(NULL, m_lpWndCls, NULL, WS_POPUP, 0, 0, m_iWidth, m_iHeight, 
							   pParentWnd->GetSafeHwnd(), NULL, NULL );
   
	m_hParentWnd = pParentWnd->GetSafeHwnd();

	if (bRet)
		SetOwner(pParentWnd);

	return bRet;
}


// --------------------------------------------------------------------------
void CToolTipWnd::OnPaint() 
{
   CPaintDC dc( this ); // device context for painting
   
   CRect rectCl;
   GetClientRect( &rectCl );
   
   CRgn rgnComb;	
   rgnComb.CreateRectRgn( rectCl.left+10,rectCl.top,rectCl.right,rectCl.bottom );
   
   int iRetComb = rgnComb.CombineRgn( &m_rgnTri, &m_rgn, RGN_OR );
   if ( iRetComb == ERROR )
   {
      AfxMessageBox( "ERROR in Combining Region" );
      return;
   }
   
   CBrush pBrush;
   pBrush.CreateSolidBrush( m_clrFrameColor );
   
   CBrush pBrush1;
   pBrush1.CreateSolidBrush( m_clrBkColor );
   
   dc.FillRgn( &rgnComb, &pBrush1 );
   dc.FrameRgn( &rgnComb, &pBrush, 2, 1 );
   
   dc.SetBkMode( TRANSPARENT );
   dc.SetTextColor( m_clrTextColor );
   
   CFont *pFont = dc.SelectObject( &m_strTextFont );
   
   CSize czTextWidth = dc.GetTextExtent( m_strText );
   
   if ( czTextWidth.cx < m_rectText.Width() )
      dc.DrawText( m_strText, m_rectText, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
   else
      dc.DrawText( m_strText, m_rectText, DT_CENTER | DT_WORDBREAK );

   dc.SelectObject( pFont );
}


// --------------------------------------------------------------------------
int CToolTipWnd::OnCreate( LPCREATESTRUCT lpCreateStruct ) 
{
   if ( CWnd::OnCreate( lpCreateStruct ) == -1 )
      return -1;
   
   CRect rectCl;
   GetClientRect( &rectCl );
   
   int x=0, y=0;
   CRect rectTemp;
   
   rectTemp = rectCl;
   rectTemp.left = rectTemp.left + 10;
   
   x = (int)( (float)( (float)rectTemp.Width() / 2.0 ) / 1.41421 );
   y = (int)( (float)( (float)rectTemp.Height() / 2.0 ) / 1.41421 );
   
   m_rectText.top = ( ( rectTemp.Height() / 2 ) - y );
   m_rectText.left = ( ( rectTemp.Width() / 2 ) - x ) + 10;
   m_rectText.right = ( ( rectTemp.Width() / 2 ) + x ) + 10;
   m_rectText.bottom = ( ( rectTemp.Height() / 2 ) + y );
   
   m_rgn.m_hObject = NULL;
   m_rgnTri.m_hObject = NULL;
   m_rgnComb.m_hObject = NULL;
   
   BOOL bRegRet = m_rgn.CreateEllipticRgn( rectCl.left+10,rectCl.top,rectCl.right,rectCl.bottom );
   
   CPoint ptTri[4];
   ptTri[0].x = rectCl.left;
   ptTri[0].y = ( rectCl.bottom / 2 ) - 10;
   
   ptTri[1].x = rectCl.left + 15;
   ptTri[1].y = ( rectCl.bottom / 2 ) - 5;
   
   ptTri[2].x = rectCl.left + 15;
   ptTri[2].y = ( rectCl.bottom / 2 ) + 5;
   
   ptTri[3].x = rectCl.left;
   ptTri[3].y = ( rectCl.bottom / 2 ) - 10;
   
   BOOL bRegTriRet = m_rgnTri.CreatePolygonRgn( ptTri, 3, ALTERNATE );
   
   m_rgnComb.CreateRectRgn( rectCl.left+10,rectCl.top,rectCl.right,rectCl.bottom );
   int iRetComb = m_rgnComb.CombineRgn( &m_rgnTri, &m_rgn, RGN_OR );
   
   if ( iRetComb == ERROR )
   {
      AfxMessageBox( "ERROR in Combining Region" );
      return -1;
   }
   
   int bRgnWnd = SetWindowRgn( m_rgnComb.operator HRGN( ), TRUE );	
   
   m_strTextFont.CreateFont( m_iFontHeight, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, m_strFontName );
   
   return 0;
}


// --------------------------------------------------------------------------
void CToolTipWnd::RelayEvent( LPMSG lpMsg )
{
   switch( lpMsg->message ) 
   {
      case WM_KEYDOWN:
         Hide();
         break;
  
      case WM_LBUTTONDOWN:
      case WM_RBUTTONDOWN:
      case WM_NCLBUTTONDOWN:
      case WM_NCRBUTTONDOWN:
         Hide();
         break;
      
      case WM_MOUSEMOVE:
      case WM_NCMOUSEMOVE:
      {
         // This is a fix to allow for messages to be made visible when not
         // using the mouse.
         if ( m_bSkipNextMove )
         { 
//            TRACE0("Move skipped\n");
            m_bSkipNextMove = false; 
            return;
         }
         else
		 {
//	         TRACE0("Move\n");
		 }

         HWND wndPt = lpMsg->hwnd;
         CPoint pt;
         pt.x = lpMsg->pt.x;
         pt.y = lpMsg->pt.y;

         // Don't show the tooltips if the application does not have the input focus
         CWnd *pFocusWnd = AfxGetApp()->m_pMainWnd->GetFocus();
         if ( pFocusWnd == NULL )
            break;

         // There are 3 possible states regarding tooltip controls:
         // a) moving outside any ctrl
         // b) going from outside a ctrl to inside
         // c) moving inside the control
         // d) going from inside a ctrl to outside

         BTOOLINFO *stToolInfo = NULL;
         BOOL found = m_toolPtr.Lookup( wndPt, (void *&)stToolInfo );

         if ( m_pCurrwnd == NULL ) // was not in a control
         {
            if ( found ) // enters a control (now in a control)
            {
//               TRACE0("OUT -> IN\n");
               m_clrTextColor = stToolInfo->clrToolTextClr;
               m_strText = stToolInfo->strToolText;
               Show( pt.x, pt.y, stToolInfo->iTimerDelay, stToolInfo->iTimerDelayShow );
               m_pCurrwnd = wndPt;
            }
            else // still not in a control
			{
//               TRACE0("OUT -> OUT\n");
			}
         }
         else // was in a control
         {
            ASSERT( m_pCurrwnd != NULL );
            CRect rect;
            ::GetWindowRect( m_pCurrwnd, &rect );
            if ( rect.PtInRect( lpMsg->pt ) ) // still in the same control
            {
//               TRACE0("IN -> IN (same)\n");
               if ( m_bStuck )
                  if ( IsWindowVisible() )
                  {
                     // may be over a tooltip, so look for previous control
                     if ( ! found )
                        found = m_toolPtr.Lookup( m_pCurrwnd, (void *&)stToolInfo );
                     ASSERT( found );
		               Show( pt.x, pt.y, stToolInfo->iTimerDelay, stToolInfo->iTimerDelayShow );
                  }
            }
            else // gone outside the control
            {
               Hide(); 
               m_pCurrwnd = NULL;

               if ( found )  // to another control
               {
//                  TRACE0("IN -> IN (other)\n");
                  m_clrTextColor = stToolInfo->clrToolTextClr;
                  m_strText = stToolInfo->strToolText;
	               Show( pt.x, pt.y, stToolInfo->iTimerDelay, stToolInfo->iTimerDelayShow );
                  m_pCurrwnd = wndPt;
               }
               else
			   {
//                  TRACE0("IN -> OUT\n");
			   }
            }
         }
      }	
      break; //WM_MOUSEMOVE
   }
}


// --------------------------------------------------------------------------
// Add or Replace tooltip if already present

void CToolTipWnd::AddTool(CWnd *pWnd, CString strText, COLORREF clrTextColor/*=NULL*/, int timerDelay /*= -1*/, int timerDelayShow /*=-1*/)
{
   ASSERT( pWnd->GetSafeHwnd() != NULL );

   BTOOLINFO *stToolInfo = NULL;
   if ( m_toolPtr.Lookup( pWnd->GetSafeHwnd(), (void *&)stToolInfo ) )
   {
      m_toolPtr.RemoveKey( pWnd );
      delete stToolInfo;
   }

   stToolInfo = new BTOOLINFO;
   stToolInfo->strToolText = strText;
	stToolInfo->clrToolTextClr = clrTextColor;
   if ( timerDelay < 0 )
      stToolInfo->iTimerDelay = m_iDelay; // default value
   else
      stToolInfo->iTimerDelay = timerDelay;

   if (timerDelayShow < 0)
      stToolInfo->iTimerDelayShow = m_iDelayShow;
   else
      stToolInfo->iTimerDelayShow = timerDelayShow;


   m_toolPtr.SetAt( pWnd->GetSafeHwnd(), stToolInfo );
}





//
// This callback is used by the EnumChildWindows function in the OnTimer Handler
//
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
{
	BOOL bStatus = TRUE;
	TTWNDSTRUCT* pws = (TTWNDSTRUCT*)lParam;
	if (pws)
	{
		HWND hWndToolTip = pws->hWndToolTip;
		HWND hWndToolTipParent = pws->hWndToolTipParent;

		// Are we over the same window as when the timer message was fired?
		if (hwnd == hWndToolTipParent)
		{
			// Display the tooltip
			::ShowWindow(hWndToolTip, SW_SHOWNOACTIVATE);

			// Stop enumerating
			bStatus = FALSE;
		}
	}

	return bStatus;
}
 
  


// --------------------------------------------------------------------------
void CToolTipWnd::OnTimer( UINT nIDEvent ) 
{
	if (nIDEvent == ID_TIMER_TOOLTIP_HIDE)
	{
		KillTimer();
		KillShowTimer();
		ShowWindow(SW_HIDE);

	}
	else if (nIDEvent == ID_TIMER_TOOLTIP_SHOW)
	{
		POINT pt;

		// Where is the mouse right now?
		if (GetCursorPos(&pt))
		{
			// Over which window?
			CWnd* pWnd = WindowFromPoint(pt);

			// Save the relevant window handles
			TTWNDSTRUCT ws;
			ZeroMemory(&ws, sizeof(ws));
			ws.hWndToolTip = GetSafeHwnd();
			ws.hWndToolTipParent = pWnd->GetSafeHwnd();

			// Now do the window handle comparisons
			EnumChildWindows(m_hParentWnd, EnumChildProc, (LPARAM)&ws); 
		}
 
	}


	CWnd::OnTimer(nIDEvent);
}


// --------------------------------------------------------------------------
void CToolTipWnd::SetTimer( int iDelay )
{
   KillTimer(); 
   if ( iDelay > 0 ) // no timer if <= 0
      m_iTimer = CWnd::SetTimer( ID_TIMER_TOOLTIP_HIDE, iDelay*1000, NULL );
}


void CToolTipWnd::SetShowTimer(int iTimeTillShow)
{
   KillShowTimer(); 
   if ( iTimeTillShow > 0 ) // no timer if <= 0
      m_iTimer2 = CWnd::SetTimer(ID_TIMER_TOOLTIP_SHOW, iTimeTillShow, NULL );
}

// --------------------------------------------------------------------------
void CToolTipWnd::KillTimer()
{
   if ( m_iTimer > 0 && m_hWnd != NULL ) 
      CWnd::KillTimer( m_iTimer ); 
   m_iTimer = 0;
}

void CToolTipWnd::KillShowTimer()
{
   if ( m_iTimer2 > 0 && m_hWnd != NULL ) 
      CWnd::KillTimer( m_iTimer2 ); 
   m_iTimer2 = 0;
}


// --------------------------------------------------------------------------
// Make the tooltip appear just as if the mouse just entered 'hWnd'
// 'hWnd' must be the active window.

void CToolTipWnd::Show( HWND hWnd, const char *overrideText, int timerDelayHide, int timerDelayShow )
{
   // make sure the window is active
   CWnd *pFocusWnd = AfxGetApp()->m_pMainWnd->GetFocus();
   if ( pFocusWnd == NULL )
      return;

   // If another one was present, hide it.
   Hide();

   // take the 'hWnd' coordinates and compute where the tooltip should appear
   RECT rect;
   ::GetWindowRect( hWnd, &rect );
   POINT pt;
   pt.x = rect.left + ( ( rect.right - rect.left ) / 2 );
   pt.y = rect.bottom;

   // Determine the text to dislay: 'overrideText' or original tooltip text
   if ( overrideText != NULL )
      m_strText = overrideText;
   else
   {
      // Reset 'm_strText' to original from tooltip
      BTOOLINFO *stToolInfo;
      if ( m_toolPtr.Lookup( hWnd, (void *&)stToolInfo ) )
         m_strText = stToolInfo->strToolText;
   }

   // Make it appear at 'pt'
   if ( timerDelayHide <= 0 ) // don't permit a tooltip to stay forever
      timerDelayHide = m_iDelay;
   Show( pt.x, pt.y, timerDelayHide, timerDelayShow);

   m_bSkipNextMove = true; // it seems we receive a WM_MOUSEMOVE whenever a window is displayed...
   m_pCurrwnd = hWnd;
}


// --------------------------------------------------------------------------
void CToolTipWnd::Show( int x, int y, int timerDelayToHide, int timerDelayToShow ) // force apparition of the tooltip
{
   // Check to see if the tooltip has a portion outside the
   // screen, if so, adjust.
   if (x < 0)
      x = 0;

   if (y < 0)
      y = 0;

   RECT r;
   r.left = x;
   r.right = r.left + m_iWidth;
   r.top = y;
   r.bottom = r.top + m_iHeight;

   // Compare to screen coordinates (don't take in account the desktop toolbar)
   int screenHeight = GetSystemMetrics( SM_CYSCREEN );
   if ( r.bottom > screenHeight )
      r.top = screenHeight - ( m_iHeight );

   int screenWidth = GetSystemMetrics( SM_CXSCREEN );
   if ( r.right > screenWidth )
      r.left = screenWidth - m_iWidth;

   // Move the window
   SetWindowPos( &wndTop, r.left, r.top, m_iWidth, m_iHeight, SWP_NOACTIVATE );

   // Only show after show delay has passed
   // ShowWindow( SW_SHOWNOACTIVATE );

    // Start the hide delay timer
	SetTimer( timerDelayToHide );

	// Start the show delay timer
	SetShowTimer(timerDelayToShow);
}


// --------------------------------------------------------------------------
void CToolTipWnd::Hide()
{
   if ( IsWindowVisible() )
   {
      ShowWindow( SW_HIDE );
      KillTimer();
	  KillShowTimer();
   }
}


// --------------------------------------------------------------------------
// Relay mouse messages occuring when and we move over a tooltip.
// Try doing a fast jump with the mouse into a control where the tooltip is first drawn...

BOOL CToolTipWnd::PreTranslateMessage( MSG *pMsg )
{
   RelayEvent( pMsg );

	return CWnd::PreTranslateMessage( pMsg );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -