創建方法
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);
}