VC 氣泡

創建方法

CXInfoTipWhenHit* g_pInfoTip;
 
 
//在入口處創建
	g_pInfoTip = new CXInfoTipWhenHit;
	g_pInfoTip->Create(this);

 

刪除方法

if(g_pInfoTip != NULL)
	{
		delete g_pInfoTip;
		g_pInfoTip = NULL;
	}


使用方法

g_pInfoTip->Show(strMsg);


 

 

以下是實現

//頭文件

#pragma once

/**
*顯示單擊按鈕、菜單執行結果的提示框
*/
class CXInfoTipWhenHit : public CWnd
{
protected:
	///////////////////////////////////////////////////////////////////////////
	// Tool information structure
	///////////////////////////////////////////////////////////////////////////
	typedef struct
	{
		CString	szText;											// Tooltip text
		HICON	hIcon;											// Tooltip icon
	} TipToolInfo;

	// Timer identifiers
	enum
	{
		timerShow			= 100,								// Show timer
		timerHide			= 101								// Hide timer
	};

	LPCTSTR		m_szClass;										// Window class

	int			m_nShowDelay;									// Show delay

	CPoint		m_ptOrigin;										// Popup origin

	CString		m_szText;										// Tip text

	UINT		m_nTimer;										// Show/hide timer

	HICON		m_hIcon;										// Tip icon
	CSize		m_IconSize;										// Tip icon size

	CFont		*m_pFont;										// Tip font

	CMap<HWND, HWND, TipToolInfo, TipToolInfo>	m_ToolMap;		// Tools map

public:
	CXInfoTipWhenHit();
	virtual ~CXInfoTipWhenHit();

	BOOL Create(CWnd *parent);

	void AddTool(CWnd *pWnd, LPCTSTR szTooltipText, HICON hIcon = NULL);
	void RemoveTool(CWnd *pWnd);

	void Show(CString szText);
	void Hide();

	// Sets the delay for the tooltip
	void SetShowDelay(int nDelay) { m_nShowDelay = nDelay; };

	void SetIcon(HICON hIcon);

	// Sets the tooltip font
	void SetFont(CFont *pFont) 
	{ 
		m_pFont = pFont; 
		if (IsWindow(m_hWnd))
			RedrawWindow();
	};

	void RelayEvent(LPMSG lpMsg);

protected:
	BOOL GetWindowRegion(CDC *pDC, HRGN* hRegion, CSize* Size = NULL);


protected:
	//{{AFX_MSG(CXInfoTip)
	afx_msg void OnPaint();
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnTimer(UINT nIDEvent);
	afx_msg void OnDestroy();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};


//源文件

#include "StdAfx.h"
#include "XInfoTipWhenHit.h"

#define CX_ROUNDED				12		// Tip horizontal roundness
#define CY_ROUNDED				10		// Tip vertical roundness
#define CX_LEADER				25		// Width of tip lead
#define CY_LEADER				25		// Height of tip lead
#define CX_ICON_MARGIN			5		// Width of margin between icon and tip text

#define DEFAULT_SHOW_DELAY		100		// Default show delay (ms)
#define TIMER_HIDE				1000	// Hide timer (ms)


/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::CXInfoTip()
// 
// DESCRIPTION
//     
//		Constructor
//     
/////////////////////////////////////////////////////////////////////
CXInfoTipWhenHit::CXInfoTipWhenHit()
{
	// Register the class
	m_szClass		= AfxRegisterWndClass(0);

	m_hIcon			= NULL;

	// Set the delay defaults
	m_nShowDelay	= DEFAULT_SHOW_DELAY;

	m_IconSize		= CSize(0, 0);
	m_ptOrigin		= CPoint(0, 0);
}

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::~CXInfoTip()
// 
// DESCRIPTION
//     
//		Deconstructor
//     
/////////////////////////////////////////////////////////////////////
CXInfoTipWhenHit::~CXInfoTipWhenHit()
{
}

// Message map
BEGIN_MESSAGE_MAP(CXInfoTipWhenHit, CWnd)
	//{{AFX_MSG_MAP(CXInfoTip)
	ON_WM_PAINT()
	ON_WM_CREATE()
	ON_WM_TIMER()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::Create()
// 
// DESCRIPTION
//     
//		Creates the tip window
//
// RETURNS
//
//		[BOOL]			- TRUE on success, FALSE on failure
//
// PARAMETERS
//
//		[pParentWnd]	- Pointer to parent window
//     
/////////////////////////////////////////////////////////////////////
BOOL CXInfoTipWhenHit::Create(CWnd* pParentWnd) 
{
	BOOL	bSuccess;

	// Must have a parent
	ASSERT(pParentWnd != NULL);

	bSuccess = CreateEx(NULL, m_szClass, NULL, WS_POPUP, 0, 0, 0, 0, pParentWnd->GetSafeHwnd(), NULL, NULL);

	// Use default GUI font for default font
	m_pFont = pParentWnd->GetFont();

	return bSuccess;
}

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::Show()
// 
// DESCRIPTION
//     
//		Shows the tip window
//
// RETURNS
//
//		[void]	
//
// PARAMETERS
//
//		[szText]	- Tip text
//		[pt]		- Coordinates to display tip window
//					or NULL to use the current cursor position
//     
/////////////////////////////////////////////////////////////////////
void CXInfoTipWhenHit::Show(CString szText)
{	
	GetCursorPos(&m_ptOrigin);		

	m_szText	= szText;
	// Start the show timer
	m_nTimer = SetTimer(timerShow, m_nShowDelay, NULL);
}

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::OnPaint()
// 
// DESCRIPTION
//     
//		Paint the window
//
// RETURNS
//
//		[void]
//
/////////////////////////////////////////////////////////////////////
void CXInfoTipWhenHit::OnPaint() 
{
	CPaintDC dc( this ); // device context for painting

	CRect	rc;
	CBrush	WindowBrush;
	CBrush	FrameBrush;
	CBrush	InnerFrameBrush;
	HRGN	hRegion;
	CRgn	*pRegion;
	CFont	*pSysFont;

	// Get the client rectangle
	GetClientRect(rc);

	// Create the brushes
	InnerFrameBrush.CreateSolidBrush(::GetSysColor(COLOR_SCROLLBAR));
	FrameBrush.CreateSolidBrush(::GetSysColor(COLOR_WINDOWTEXT));
	WindowBrush.CreateSolidBrush(::GetSysColor(COLOR_WINDOW));

	// Get the window region
	GetWindowRegion(&dc, &hRegion);
	pRegion = CRgn::FromHandle(hRegion);

	// Draw the frame
	dc.FillRgn(pRegion, &WindowBrush);
	dc.FrameRgn(pRegion, &InnerFrameBrush, 3, 3);
	dc.FrameRgn(pRegion, &FrameBrush, 1, 1);

	// Adjust the area for the icon
	rc.DeflateRect(CX_ROUNDED, CY_ROUNDED, 0, 0);
	if (m_hIcon != NULL)
		rc.left = rc.left + m_IconSize.cx + CX_ICON_MARGIN;
	
	// Set the font
	pSysFont = (CFont *)dc.SelectObject(m_pFont);
	// Draw the tip text	
	dc.SetBkMode( TRANSPARENT );
	dc.DrawText(m_szText, &rc, DT_TOP | DT_LEFT);

	// Draw the icon
	if (m_hIcon != NULL)
		DrawIconEx(dc.m_hDC, CX_ROUNDED, CY_ROUNDED, m_hIcon, m_IconSize.cx, m_IconSize.cy, 0, NULL, DI_NORMAL);

	// Clean up GDI
	::DeleteObject(hRegion);
	dc.SelectObject(pSysFont);

}

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::GetWindowRegion()
// 
// DESCRIPTION
//     
//		Retrieves the window region
//
// RETURNS
//
//		[BOOL]		- TRUE on success, FALSE on failure
//
// PARAMETERS
//
//		[pDC]		- Pointer to display device context
//		[hRegion]	- Filled with the calculated window region
//		[Size]		- Filled with the calculated window size
//					or NULL.
//     
/////////////////////////////////////////////////////////////////////
BOOL CXInfoTipWhenHit::GetWindowRegion(CDC* pDC, HRGN* hRegion, CSize *Size /* = NULL */)
{
	CRect	rcWnd;
	POINT	ptLeader[3];
	CRgn	LeaderRegion;
	CRgn	CaptionRegion;
	CFont	*pSysFont;
	
	ASSERT(pDC != NULL);
	ASSERT(hRegion != NULL);

	// Calculate the are for the tip text
	pSysFont = (CFont *)pDC->SelectObject(m_pFont);
	pDC->DrawText(m_szText, &rcWnd, DT_CALCRECT);
	pDC->SelectObject(pSysFont);

	// Adjust for the rounded corners
	rcWnd.InflateRect(CX_ROUNDED, CY_ROUNDED);

	// Adjust for icon
	if (m_hIcon != NULL)
		rcWnd.right = rcWnd.right + m_IconSize.cx + CX_ICON_MARGIN;
	if (rcWnd.Height() < m_IconSize.cy)
		rcWnd.bottom = rcWnd.top + m_IconSize.cy;

	int xCord= m_ptOrigin.x - rcWnd.Width() + CX_ROUNDED;
	
	int nOffset= 0;
	if (xCord < 0 ){
		nOffset= xCord;
	}
	// Calculate the leader triangle coordinates

	ptLeader[0].x	= rcWnd.Width() - CX_ROUNDED+ nOffset;
	ptLeader[0].y	= rcWnd.Height() - CY_ROUNDED;

	ptLeader[1].x	= ptLeader[0].x;
	ptLeader[1].y	= ptLeader[0].y + CY_LEADER;

	ptLeader[2].x	= ptLeader[0].x - CX_LEADER;
	ptLeader[2].y	= rcWnd.Height() - CY_ROUNDED;

	// Create the caption region
	CaptionRegion.CreateRoundRectRgn(0, 0, rcWnd.Width(), rcWnd.Height(), CX_ROUNDED, CY_ROUNDED);
	// Create the leader region
	LeaderRegion.CreatePolygonRgn(ptLeader, 3, ALTERNATE);
	// Create window region
	*hRegion =  ::CreateRectRgn(0, 0, rcWnd.Width(), rcWnd.Height() + CY_LEADER);
	// Combine the regions
	CombineRgn(*hRegion, CaptionRegion.operator HRGN(), LeaderRegion.operator HRGN(), RGN_OR);

	// Set the window size
	if (Size != NULL)
	{
		Size->cx	= rcWnd.Width();
		Size->cy	= rcWnd.Height() + CY_LEADER;
	}

	return TRUE;
}

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::OnCreate()
// 
// DESCRIPTION
//     
//		Window creation
//
// RETURNS
//
//		[int]				- Zero on success, -1 otherwise
//
// PARAMETERS
//
//		[lpCreateStruct]	- Pointer to creation structure
//     
/////////////////////////////////////////////////////////////////////
int CXInfoTipWhenHit::OnCreate( LPCREATESTRUCT lpCreateStruct ) 
{
   if ( CWnd::OnCreate( lpCreateStruct ) == -1 )
      return -1;
   
   return 0;
}

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::OnTimer()
// 
// DESCRIPTION
//     
//		Timer event
//
// RETURNS
//
//		[void]	
//
// PARAMETERS
//
//		[nIDEvent]	- Timer identifier
//     
/////////////////////////////////////////////////////////////////////
void CXInfoTipWhenHit::OnTimer( UINT nIDEvent ) 
{
	HRGN	hRegion;
	CSize	WindowSize;
	CDC		*pDC;
	CPoint	ptCursor;

	switch (nIDEvent)
	{
	/////////////////////////////////////////////////////////////////////
	// Show the tip window
	/////////////////////////////////////////////////////////////////////
	case timerShow:
	{
		KillTimer(m_nTimer);
		ShowWindow(SW_HIDE);

		pDC = GetDC();
		GetWindowRegion(pDC, &hRegion, &WindowSize);
		ReleaseDC(pDC);

		::SetWindowRgn(m_hWnd, hRegion, TRUE);

		POINT pointWnd;
		pointWnd.x= m_ptOrigin.x - WindowSize.cx + CX_ROUNDED;
		pointWnd.y= m_ptOrigin.y - WindowSize.cy + CY_ROUNDED;

		int nOffset= 0;
		if (pointWnd.x < 0 ){
			pointWnd.x= 0;
		}

		SetWindowPos(&wndTop, pointWnd.x , pointWnd.y ,
			WindowSize.cx, WindowSize.cy, SWP_NOACTIVATE | SWP_SHOWWINDOW);

		m_nTimer = SetTimer(timerHide, TIMER_HIDE, NULL);

		break;
	}
	/////////////////////////////////////////////////////////////////////
	// Hide the tip window
	/////////////////////////////////////////////////////////////////////
	case timerHide:
		GetCursorPos(&ptCursor);
		if (ptCursor != m_ptOrigin)
		{
			KillTimer(m_nTimer);
			ShowWindow(SW_HIDE);
		}

		break;
	}

	CWnd::OnTimer(nIDEvent);
}

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::OnDestroy()
// 
// DESCRIPTION
//     
//		Window destruction
//
// RETURNS
//
//		[void]	
//
/////////////////////////////////////////////////////////////////////
void CXInfoTipWhenHit::OnDestroy() 
{
	KillTimer(m_nTimer);

	CWnd::OnDestroy();
}

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::RelayEvent()
// 
// DESCRIPTION
//     
//		Call this in the parent's PreTranslateMessage() to 
//		relay tooltip event messages.
//
// RETURNS
//
//		[void]	
//
// PARAMETERS
//
//		[lpMsg]	- Pointer to message structure
//     
/////////////////////////////////////////////////////////////////////
void CXInfoTipWhenHit::RelayEvent(LPMSG lpMsg)
{
	CPoint			point;
	CWnd			*pWindow;
	CString			szTooltipText;
	TipToolInfo		Info;
		
	switch(lpMsg->message)
	{
	case WM_LBUTTONDOWN:
	case WM_RBUTTONDOWN:
	case WM_MBUTTONDOWN:
		ShowWindow(SW_HIDE);
		break;
	case WM_MOUSEMOVE:
		GetCursorPos(&point);

		if (point != m_ptOrigin)
		{
			// Find the tool
			CWnd* pParent= CWnd::FromHandle(lpMsg->hwnd);
			if (pParent)
			{
				POINT ptClient= point;
				pParent->ScreenToClient(&ptClient);
				pWindow = pParent->ChildWindowFromPoint(ptClient,CWP_SKIPINVISIBLE);
				if (pWindow != NULL)
				{
					if (m_ToolMap.Lookup(pWindow->m_hWnd, Info))
					{
						// Display the tooltip
						m_ptOrigin = point;
						SetIcon(Info.hIcon);
						Show(Info.szText);
					}
				}
			}
		}

		// Hide the tooltip
		if (point != m_ptOrigin)
		{
			Hide();
		}
		
		break;
	}
}

void CXInfoTipWhenHit::Hide() 
{ 
	KillTimer(m_nTimer);
	ShowWindow(SW_HIDE); 
};

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::SetIcon()
// 
// DESCRIPTION
//     
//		Sets the tip window icon
//
// RETURNS
//
//		[void]	
//
// PARAMETERS
//
//		[hIcon]	- Handle to the icon
//     
/////////////////////////////////////////////////////////////////////
void CXInfoTipWhenHit::SetIcon(HICON hIcon) 
{
	ICONINFO	IconInfo;

	m_hIcon = hIcon; 

	if (hIcon == NULL)
	{
		m_IconSize = CSize(0, 0);
		return;
	}
	
	// Get the icon sizes	
	ZeroMemory(&IconInfo, sizeof(ICONINFO));
	::GetIconInfo(m_hIcon, &IconInfo);

	m_IconSize.cx = (BYTE)(IconInfo.xHotspot * 2);
	m_IconSize.cy = (BYTE)(IconInfo.yHotspot * 2);
    
	::DeleteObject(IconInfo.hbmMask);
	::DeleteObject(IconInfo.hbmColor);

	if (IsWindow(m_hWnd))
		RedrawWindow();
}

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::AddTool()
// 
// DESCRIPTION
//     
//		Adds a tool
//
// RETURNS
//
//		[void]	
//
// PARAMETERS
//
//		[pWnd]			- Pointer to the tool window
//		[szTooltipText]	- Text to display when the cursor hovers
//						over the window (pWnd)
//		[hIcon]			- Icon to display in the tooltip, or NULL
//						to display no icon.
//     
/////////////////////////////////////////////////////////////////////
void CXInfoTipWhenHit::AddTool(CWnd *pWnd, LPCTSTR szTooltipText, HICON hIcon /* = NULL */)
{
	ASSERT(pWnd != NULL);

	// Store the tool information
	TipToolInfo Info;
	Info.szText = szTooltipText;
	Info.hIcon	= hIcon;

	// Add the tool 
	m_ToolMap.SetAt(pWnd->m_hWnd, Info);
};

/////////////////////////////////////////////////////////////////////
// 
// CXInfoTip::RemoveTool()
// 
// DESCRIPTION
//     
//		Removes a tool
//
// RETURNS
//
//		[void]	
//
// PARAMETERS
//
//		[pWnd]			- Pointer to the tool window to remove
//     
/////////////////////////////////////////////////////////////////////
void CXInfoTipWhenHit::RemoveTool(CWnd *pWnd)
{
	m_ToolMap.RemoveKey(pWnd->m_hWnd);
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章