基于mfc的输入检查弹出式警告框类

效果图:



代码:

InputCheckTip.h 

#pragma once
#include "Resource.h"
#include "SSWnd.h"

// CWndInputCheck 窗口

#define TIMER_HIDETIP	1001

class CWndInputCheck : public CSSWnd
{
	DECLARE_DYNAMIC(CWndInputCheck)

public:
	CWndInputCheck(CWnd* pParent = NULL); // 标准构造函数
	virtual ~CWndInputCheck();

protected:
	DYNAMIC_FONT	m_lf;			//静态文字字体

	CString 	m_strText;

	DYNAMIC_RGB	m_clrBkg;
	DYNAMIC_RGB m_clrStcTips;   //白

	CRect		m_rcMain;
	int			m_nalainside;
	int			m_nalainoffset;

	DYNAMIC_IMAGE		m_pimgWarning;

protected:
	DECLARE_MESSAGE_MAP()
	afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnPaint();
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnTimer(UINT_PTR nIDEvent);
public:
	void SetFont(DYNAMIC_FONT	lf);
	void SetText(const CString &str);
	void SetMainRect(int alainside, int alainoffst, const CRect &mainrc);
	const CRect &GetMainRect();
};

enum TIPTYPE{
	/*
 	  0 - 自己指定的任意字符串。
	  1 - 请确保输入在"x1" - "x2"范围内。
	  2 - 请确保输入内容形如以下形式:
  			"xxxxxxxxxxx" 
	*/
	TIP_ERR_CUSTOM,
	TIP_ERR_RANGE,
	TIP_ERR_LIKE,
};

//CWndInputCheckTip 窗口

class SSCOMMON_API CInputCheckTip
{
public:
	//公共的tip
	static CInputCheckTip *GetTipInstance();
	//关联窗口的tip
	static CInputCheckTip *GetTipInstance(HWND hWnd);
	//注销
	static void UnInitInstance();//GdiplusShutdown之前调用
	// 外部接口
	// 关联窗口的tip需要额外调用:
	static void AddInputCheckTip(CWnd *pWnd);//在OnCreate中调用
	//公共,关联tip共有接口
	/*
	 nTipType取值 参考 enum TIPTYPE
	*/
	void PopTip(HWND hWnd, CPoint &point, TIPTYPE nTipType, const CString &sText1,const CString &sText2 = CString(_T("")),const CString &sText3 = CString(_T("")));
	void PopTip(HWND hWnd, CRect  &rect,  TIPTYPE nTipType, const CString &sText1,const CString &sText2 = CString(_T("")),const CString &sText3 = CString(_T("")));
	void HideTip();
protected:
	CInputCheckTip(CWnd* pParent = NULL); // 标准构造函数
	virtual ~CInputCheckTip();

	const CString &strWndInputCheck(int i);

	static LRESULT MyMsgProc(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam);
	static LRESULT MyMsgProcHwnd(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam);
protected:
	CWndInputCheck* m_pWndInputCheck;
	HWND			m_hWnd;
	WNDPROC			m_OldMsgProc;

	bool			m_bMoving;
	CRect			m_rcOld;

	static CInputCheckTip* m_instance; 
	static std::map<HWND,CInputCheckTip*> m_tipmap;
};

InputCheckTip.cpp 

#include "stdafx.h"//-支持关联窗口的多实例
#include "InputCheckTip.h"
#include "SSCommonApp.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif // _DEBUG

IMPLEMENT_DYNAMIC(CWndInputCheck, CSSWnd)

CWndInputCheck::CWndInputCheck( CWnd* pParent /*= NULL*/ )
{
	m_clrBkg	  = SkinMgr::GetColor(clrCheckTipBack);//0x00BAE9FF;
	m_clrStcTips  = SkinMgr::GetColor(clrCheckTipText);
	m_pimgWarning =	SkinMgr::AddImage(PNG_INPUT_CHECK_WARNING);
}

CWndInputCheck::~CWndInputCheck()
{
	SkinMgr::DelImage(m_pimgWarning);
}

BEGIN_MESSAGE_MAP(CWndInputCheck, CSSWnd)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
	ON_WM_TIMER()
	ON_WM_PAINT()
END_MESSAGE_MAP()

int CWndInputCheck::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
	if (CSSWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	m_lf = SkinMgr::GetFont(fnt3);

	return 0;
}

void CWndInputCheck::OnPaint()
{
	
	CPaintDC dc(this); // device context for painting
	// TODO: 在此处添加消息处理程序代码
	Graphics graph(dc.GetSafeHdc());
	
	CRect rcClient;
	GetClientRect(&rcClient);
	Color clrBkg;
	clrBkg.SetFromCOLORREF(TORGB(m_clrBkg));
	SolidBrush brush(clrBkg);
	graph.FillRectangle(&brush,rcClient.left,rcClient.top,rcClient.Width(),rcClient.Height());

	Rect rc;

	rc.X = m_rcMain.left + 8;
	rc.Y = (m_rcMain.top + m_rcMain.bottom - TOPIMAGE(m_pimgWarning)->GetHeight())/2;
	rc.Width = TOPIMAGE(m_pimgWarning)->GetWidth();
	rc.Height = TOPIMAGE(m_pimgWarning)->GetHeight();

	graph.DrawImage(TOPIMAGE(m_pimgWarning),rc);

	int nTextleft  = rc.X+TOPIMAGE(m_pimgWarning)->GetWidth() + 10;
	int nTextwidth = m_rcMain.Width()-nTextleft-4;

	StringFormat sf;
	sf.SetAlignment(StringAlignmentNear);
	sf.SetLineAlignment(StringAlignmentCenter);
	sf.SetTrimming(StringTrimmingNone);
	sf.SetFormatFlags(StringFormatFlagsNoWrap);

	Color txtColor;
	txtColor.SetFromCOLORREF(TORGB(m_clrStcTips));
	SolidBrush txtBrush(txtColor);
	Gdiplus::Font font(dc.GetSafeHdc(), m_lf);


	RectF rf = RectF(nTextleft,m_rcMain.top+8,nTextwidth,m_rcMain.Height()-16);
	graph.DrawString(m_strText,m_strText.GetLength(),&font,rf,&sf,&txtBrush);

//  	RectF rf = RectF(nTextleft,m_rcMain.top+4,nTextwidth,m_lf.lfHeight);
// 	graph.DrawString(StringTable.strWndInputCheck(0),StringTable.strWndInputCheck(0).GetLength(),&font,rf,&sf,&txtBrush);
// 
// 	Color lineColor;
// 	lineColor.SetFromCOLORREF(0x808080);
// 	Pen pen(lineColor);
// 	graph.DrawLine(&pen,Point(nTextleft,m_rcMain.top + 4 + m_lf.lfHeight + 3),Point(m_rcMain.Width()-4,m_rcMain.top + 4 + m_lf.lfHeight + 3));
// //	graph.DrawLine(&pen,Point(nTextleft-5,m_rcMain.top + 4),Point(nTextleft-5,m_rcMain.bottom - 4));
// 
// 	rf = RectF(nTextleft,m_rcMain.top + 4 + m_lf.lfHeight + 7,nTextwidth,m_rcMain.bottom-4-(m_rcMain.top + 4 + m_lf.lfHeight + 7));
// 	graph.DrawString(m_strText,m_strText.GetLength(),&font,rf,&sf,&txtBrush);

	// 不为绘图消息调用 CSSWnd::OnPaint()
}

BOOL CWndInputCheck::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	return TRUE;
//	return CSSWnd::OnEraseBkgnd(pDC);
}

void CWndInputCheck::OnSize( UINT nType, int cx, int cy )
{
	if(cx <=0 || cy <= 0)
	{
		return;
	}
	CPoint ptVertex[3];
	switch (m_nalainside)
	{
	case 0://left
		{
			ptVertex[0].x = 0;  ptVertex[0].y = m_nalainoffset;
			ptVertex[1].x = m_rcMain.left; ptVertex[1].y = m_nalainoffset - 10;
			ptVertex[2].x = m_rcMain.left; ptVertex[2].y = m_nalainoffset + 10;
		}
		break;
	case 1://top
		{
			ptVertex[0].x = m_nalainoffset;  ptVertex[0].y = 0;
			ptVertex[1].x = m_nalainoffset - 10; ptVertex[1].y = m_rcMain.top;
			ptVertex[2].x = m_nalainoffset + 10; ptVertex[2].y = m_rcMain.top;
		}
		break;
	case 2://right
		{
			ptVertex[0].x = cx;  ptVertex[0].y = m_nalainoffset;
			ptVertex[1].x = m_rcMain.right; ptVertex[1].y = m_nalainoffset - 10;
			ptVertex[2].x = m_rcMain.right; ptVertex[2].y = m_nalainoffset + 10;
		}
		break;
	case 3://bottom
		{
			ptVertex[0].x = m_nalainoffset;  ptVertex[0].y = cy;
			ptVertex[1].x = m_nalainoffset - 10; ptVertex[1].y = m_rcMain.bottom;
			ptVertex[2].x = m_nalainoffset + 10; ptVertex[2].y = m_rcMain.bottom;
		}
		break;
	default:
		break;
	}
	HRGN rgn1 = CreateRectRgn(m_rcMain.left,m_rcMain.top,m_rcMain.right,m_rcMain.bottom);
	HRGN rgn2 = CreatePolygonRgn(ptVertex,3,ALTERNATE);
	CombineRgn(rgn1,rgn1,rgn2,RGN_OR);
	SetWindowRgn((HRGN)rgn1,TRUE);
	DeleteObject(rgn1);
	DeleteObject(rgn2);
	Invalidate(TRUE);
}

void CWndInputCheck::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (nIDEvent == TIMER_HIDETIP)
	{
		KillTimer(nIDEvent);
		ShowWindow(SW_HIDE);
	}
	CSSWnd::OnTimer(nIDEvent);
}

void CWndInputCheck::SetFont(DYNAMIC_FONT	lf)
{
	m_lf = lf;
}

void CWndInputCheck::SetText(const CString &str)
{
	m_strText = str;
}

void CWndInputCheck::SetMainRect(int alainside, int alainoffst, const CRect &mainrc)
{
	m_nalainside = alainside;
	m_nalainoffset = alainoffst;
	m_rcMain = mainrc;
	CRect rc;
	GetWindowRect(&rc);
	OnSize(SIZE_RESTORED,rc.Width(),rc.Height());
}


//CWndInputCheckTip 窗口

CInputCheckTip* CInputCheckTip::m_instance = NULL;
std::map<HWND,CInputCheckTip*> CInputCheckTip::m_tipmap;

CInputCheckTip::CInputCheckTip(CWnd* pParent /*= NULL*/)
	: m_pWndInputCheck(NULL)
	, m_hWnd(NULL)
	, m_OldMsgProc(NULL)
	, m_bMoving(false)
{
	if (NULL == m_instance || m_tipmap.empty())
	{
		//注册窗口  
		WNDCLASS wc;  
		memset(&wc, 0, sizeof(WNDCLASS));  

		wc.style = 0;  
		wc.lpfnWndProc = ::DefWindowProc;  
		wc.hInstance = AfxGetInstanceHandle();  
		wc.hIcon = NULL;  
		wc.hCursor = NULL;  
		wc.hbrBackground = HBRUSH(GetStockObject(NULL_BRUSH));  
		wc.lpszMenuName = NULL;
		wc.lpszClassName = _T("CWndInputCheck");


		if (!AfxRegisterClass(&wc))  
		{  
			TRACE(_T("CWndInputCheck Class registration Failer\n"));
		}  
	}
	m_pWndInputCheck = new CWndInputCheck(pParent);
	m_pWndInputCheck->CreateEx(WS_EX_TOOLWINDOW,_T("CWndInputCheck"),NULL,WS_POPUP/*|WS_VISIBLE*/,CRect(0,0,0,0),pParent,0);
}

CInputCheckTip::~CInputCheckTip()
{
	m_pWndInputCheck->DestroyWindow();
	delete m_pWndInputCheck;
	int instcount = m_tipmap.size();
	if (NULL != m_instance)
	{
		++instcount;
	}
	if (instcount <= 1)
	{
		if(!UnregisterClass(_T("CWndInputCheck"),AfxGetInstanceHandle()))
		{
			TRACE(_T("CWndInputCheck Class unregistration Failer\n"));
		}
	}
}

CInputCheckTip * CInputCheckTip::GetTipInstance()
{
	if(NULL == m_instance)
	{
		m_instance = new CInputCheckTip;
	}
	return m_instance;
}

CInputCheckTip * CInputCheckTip::GetTipInstance(HWND hWnd)
{
	CInputCheckTip *pTip = NULL;
	std::map<HWND, CInputCheckTip *>::iterator it = m_tipmap.find(hWnd);
	if(it != m_tipmap.end())
	{
		pTip = it->second;
	}
	return pTip;
}

void CInputCheckTip::AddInputCheckTip(CWnd *pWnd)
{
	if (!pWnd || !(pWnd->GetSafeHwnd()))
	{
		return;
	}
	HWND hWnd = pWnd->GetSafeHwnd();
	std::map<HWND, CInputCheckTip *>::iterator it = m_tipmap.find(hWnd);
	if(it == m_tipmap.end())
	{
		CInputCheckTip *pTip = new CInputCheckTip(pWnd);
		bool binsert = m_tipmap.insert(std::make_pair(hWnd,pTip)).second;
		if(!binsert)
		{
			delete pTip;
		}
		WNDPROC OldMsgProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC, (LONG)MyMsgProcHwnd);
		m_tipmap[hWnd]->m_OldMsgProc = OldMsgProc;
//		m_tipmap.insert(std::make_pair(hWnd,new CInputCheckTip(CWnd::FromHandle(hWnd)))).first->second->m_OldMsgProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC, (LONG)MyMsgProcHwnd);
	}
}

void CInputCheckTip::UnInitInstance()
{
	if (NULL != m_instance)
	{
		delete m_instance;
		m_instance = NULL;
	}
	std::map<HWND, CInputCheckTip *>::iterator it = m_tipmap.begin();
	for (; it != m_tipmap.end(); ++it)
	{
		delete it ->second;
	}
	m_tipmap.clear();
}

LRESULT CInputCheckTip::MyMsgProc(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam)
{
	static BOOL bfirst = TRUE;
	static CRect rcP;
	if(message == WM_MOVING)
	{
		if (bfirst)
		{
			GetWindowRect(hwnd,&rcP);
		}
		bfirst = FALSE;
	}
	if(message == WM_MOVE)
	{
		//bfirst = TRUE;
		//int x = LOWORD(lParam);
		//int y = HIWORD(lParam);
		//CRect rc;
		//GetTipInstance()->m_pWndInputCheck->GetWindowRect(&rc);
		//rc += CPoint(LOWORD(lParam)-rcP.left,HIWORD(lParam)-rcP.top);
		//GetTipInstance()->m_pWndInputCheck->MoveWindow(&rc,FALSE);

		bfirst = TRUE;
		CRect rc, rcEndP;
		GetWindowRect(hwnd, &rcEndP);
		GetTipInstance()->m_pWndInputCheck->GetWindowRect(&rc);
		rc += CPoint(rcEndP.left-rcP.left,rcEndP.top-rcP.top);
		GetTipInstance()->m_pWndInputCheck->MoveWindow(&rc,FALSE);
	}
	if (message == WM_SHOWWINDOW)
	{
		if(GetTipInstance(hwnd)->m_pWndInputCheck->IsWindowVisible())
		{
			if (!(TRUE  == BOOL(wParam)))
			{
				GetTipInstance(hwnd)->m_pWndInputCheck->ShowWindow(SW_HIDE);
			}
		}
	}
	if (message == WM_CLOSE || message == WM_DESTROY)
	{
		GetTipInstance()->m_pWndInputCheck->ShowWindow(SW_HIDE);
	}
	return CallWindowProc(GetTipInstance()->m_OldMsgProc,hwnd,message,wParam,lParam);
}

LRESULT CInputCheckTip::MyMsgProcHwnd(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam)
{
	if(message == WM_MOVING)
	{
		if (!GetTipInstance(hwnd)->m_bMoving)
		{
			GetTipInstance(hwnd)->m_bMoving = true;
			GetWindowRect(hwnd,&(GetTipInstance(hwnd)->m_rcOld));
		}
	}
	if(message == WM_MOVE)
	{
		//GetTipInstance(hwnd)->m_bMoving = false;
		//int x = LOWORD(lParam);
		//int y = HIWORD(lParam);
		//CRect rc;
		//GetTipInstance(hwnd)->m_pWndInputCheck->GetWindowRect(&rc);
		//rc += CPoint(LOWORD(lParam)-GetTipInstance(hwnd)->m_rcOld.left,HIWORD(lParam)-GetTipInstance(hwnd)->m_rcOld.top);
		//GetTipInstance(hwnd)->m_pWndInputCheck->MoveWindow(&rc,FALSE);

		GetTipInstance(hwnd)->m_bMoving = false;
		CRect rc, rcEndP;
		GetWindowRect(hwnd, &rcEndP);
		GetTipInstance(hwnd)->m_pWndInputCheck->GetWindowRect(&rc);
		rc += CPoint(rcEndP.left-GetTipInstance(hwnd)->m_rcOld.left,rcEndP.top-GetTipInstance(hwnd)->m_rcOld.top);
		GetTipInstance(hwnd)->m_pWndInputCheck->MoveWindow(&rc,FALSE);
	}
	if (message == WM_SHOWWINDOW)
	{
		if(GetTipInstance(hwnd)->m_pWndInputCheck->IsWindowVisible())
		{
			if (!(TRUE  == BOOL(wParam)))
			{
				GetTipInstance(hwnd)->m_pWndInputCheck->ShowWindow(SW_HIDE);
			}
		}
	}
	if (message == WM_CLOSE || message == WM_NCDESTROY)
	{
		GetTipInstance(hwnd)->m_pWndInputCheck->ShowWindow(SW_HIDE);
		if(message == WM_NCDESTROY)
		{
			std::map<HWND, CInputCheckTip *>::iterator it = m_tipmap.find(hwnd);
			if (it != m_tipmap.end())
			{
				WNDPROC wndproc = it->second->m_OldMsgProc;
				delete it ->second;
				m_tipmap.erase(it);
				return CallWindowProc(wndproc,hwnd,message,wParam,lParam);
			}
		}
	}
	return CallWindowProc(GetTipInstance(hwnd)->m_OldMsgProc,hwnd,message,wParam,lParam);
}

const CString &CInputCheckTip::strWndInputCheck(int i)
{
	switch(i)
	{
	case 1:{_return(_T("请确保输入数值大于\"{1}\"。"),_T(""));break;}
	case 2:{_return(_T("请确保输入数值小于\"{2}\"。"),_T(""));break;}
	case 3:{_return(_T("请确保输入在\"{1}\" - \"{2}\"范围内。"),_T(""));break;}
	case 4:{_return(_T("请确保输入内容形如以下形式:\n\"{1}\""),_T(""));break;}
	default:break;
	}
	return m_strNULL;
}

void CInputCheckTip::PopTip(HWND hWnd, CPoint &point, int nTipType, const CString &sText1,const CString &sText2,const CString &sText3)
{
	if (!hWnd || !IsWindow(hWnd))
	{
		return ;
	}
	if (m_tipmap.find(hWnd) == m_tipmap.end())
	{
		if (m_hWnd && IsWindow(m_hWnd))
		{
			SetWindowLong (m_hWnd, GWL_WNDPROC, (LONG)m_OldMsgProc);
		}
		m_hWnd = hWnd;

		m_OldMsgProc=(WNDPROC)SetWindowLong (m_hWnd, GWL_WNDPROC, (LONG)MyMsgProc);
	}

	CString sztmp = nTipType==TIP_ERR_RANGE ? (sText2 == _T("") ? strWndInputCheck(1)
													: 
											   sText1 == _T("") ? strWndInputCheck(2)
																: strWndInputCheck(3))
											: 
					nTipType==TIP_ERR_LIKE  ? strWndInputCheck(4)
											: _T("{1}");
	sztmp.Replace(_T("{1}"),sText1);
	sztmp.Replace(_T("{2}"),sText2);
	sztmp.Replace(_T("{3}"),sText3);

	DYNAMIC_FONT	lf = SkinMgr::GetFont(fnt3);
	CDC* pDC = m_pWndInputCheck->GetDC();
	Graphics graph(pDC->GetSafeHdc());
	Gdiplus::Font font(pDC->GetSafeHdc(), lf);

	RectF rf;
	CRect rcTip;
	graph.MeasureString(sztmp,sztmp.GetLength(),&font,PointF(0,0),&rf);
	m_pWndInputCheck->ReleaseDC(pDC);

	rcTip.left   = (LONG)(0);
	rcTip.top    = (LONG)(0);
	rcTip.right  = (LONG)(rf.Width+16+16+10);
	rcTip.bottom = (LONG)(rf.Height+16);

	int x  = GetSystemMetrics(SM_XVIRTUALSCREEN );
	int y  = GetSystemMetrics(SM_YVIRTUALSCREEN );
	int cx = GetSystemMetrics(SM_CXVIRTUALSCREEN);
	int cy = GetSystemMetrics(SM_CYVIRTUALSCREEN);
	CRect DsktopRc(x,y,cx,cy);
	int alainside = -1;
	if (!(point.y - rcTip.Height() - 15 < DsktopRc.top))
	{
		alainside = 3;//bottom
	}
	if (alainside==-1 && !(point.y + rcTip.Height() + 15 > DsktopRc.bottom))
	{
		alainside = 1;
	}
	if (alainside==-1)
	{
		alainside = 3;
	}
	int alainoffset=20, offset = point.x-20-DsktopRc.left;
	if (offset<0)
	{
		if (offset>-10)
		{
			alainoffset += offset;
		}
		else
		{
			alainside = 0;//left;
		}
	}
	if (alainside != 0 && !(offset < 0))
	{
		offset = point.x-20+rcTip.Width()-DsktopRc.right;
		if (offset>0)
		{
			if (offset<rcTip.Width()-30)
			{
				alainoffset += offset;
			}
			else
			{
				alainside = 2;//right;
			}
		}
	}
	CRect rcTipReal = rcTip;

	switch(alainside)
	{
	case 0:
		{
			rcTip.left -= 15;
			rcTip += CPoint(point.x+15,point.y-alainoffset);
			rcTipReal += CPoint(15,0);
		}
		break;
	case 1:
		{
			rcTip.top -= 15;
			rcTip += CPoint(point.x-alainoffset,point.y+15);
			rcTipReal += CPoint(0,15);
		}
		break;
	case 2:
		{
			rcTip.right += 15;
			rcTip += CPoint(point.x-rcTip.Width(),point.y-alainoffset);
		}
		break;
	case 3:
		{
			rcTip.bottom += 15;
			rcTip += CPoint(point.x-alainoffset,point.y-rcTip.Height());
		}
		break;
	default:
		break;
	}
	m_pWndInputCheck->SetMainRect(alainside,alainoffset,rcTipReal);
	m_pWndInputCheck->SetFont(lf);
	m_pWndInputCheck->SetText(sztmp);
	m_pWndInputCheck->MoveWindow(&rcTip);
	m_pWndInputCheck->ShowWindow(SW_SHOWNOACTIVATE);
	m_pWndInputCheck->SetWindowPos(&CWnd::wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW);
	m_pWndInputCheck->SetWindowPos(&CWnd::wndNoTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW);
	m_pWndInputCheck->KillTimer(TIMER_HIDETIP);
	m_pWndInputCheck->SetTimer(TIMER_HIDETIP,3000,NULL);
}

void CInputCheckTip::PopTip(HWND hWnd, CRect  &rect , int nTipType, const CString &sText1,const CString &sText2,const CString &sText3)
{
	if (!hWnd)
	{
		return ;
	}
	if (m_tipmap.find(hWnd) == m_tipmap.end())
	{
		if (m_hWnd && IsWindow(m_hWnd))
		{
			SetWindowLong (m_hWnd, GWL_WNDPROC, (LONG)m_OldMsgProc);
		}
		m_hWnd = hWnd;

		m_OldMsgProc=(WNDPROC)SetWindowLong (m_hWnd, GWL_WNDPROC, (LONG)MyMsgProc);
	}

	CString sztmp = nTipType==TIP_ERR_RANGE ? (sText2 == _T("") ? strWndInputCheck(1)
													: 
											   sText1 == _T("") ? strWndInputCheck(2)
																: strWndInputCheck(3))
											: 
					nTipType==TIP_ERR_LIKE  ? strWndInputCheck(4)
											: _T("{1}");
	sztmp.Replace(_T("{1}"),sText1);
	sztmp.Replace(_T("{2}"),sText2);
	sztmp.Replace(_T("{3}"),sText3);

	DYNAMIC_FONT	lf = SkinMgr::GetFont(fnt3);
	CDC* pDC = m_pWndInputCheck->GetDC();
	Graphics graph(pDC->GetSafeHdc());
	Gdiplus::Font font(pDC->GetSafeHdc(), lf);

	RectF rf;
	CRect rcTip;
	graph.MeasureString(sztmp,sztmp.GetLength(),&font,PointF(0,0),&rf);
	m_pWndInputCheck->ReleaseDC(pDC);

	rcTip.left   = (LONG)(0);
	rcTip.top    = (LONG)(0);
	rcTip.right  = (LONG)(rf.Width+16+16+10);
	rcTip.bottom = (LONG)(rf.Height+16);

	//{
	int x  = GetSystemMetrics(SM_XVIRTUALSCREEN );
	int y  = GetSystemMetrics(SM_YVIRTUALSCREEN );
	int cx = GetSystemMetrics(SM_CXVIRTUALSCREEN);
	int cy = GetSystemMetrics(SM_CYVIRTUALSCREEN);
	CRect DsktopRc(x,y,cx,cy);

	CRect pointrc;//并不是一个实际的Rect
	pointrc.left  = max(rect.left,min(rect.left+5, cx));
	pointrc.right = min(rect.right,max(rect.right-5,x));
	pointrc.top   = max(rect.top,min(rect.top+5, cy));
	pointrc.bottom= min(rect.bottom,max(rect.bottom-5,y));

	int alainside = -1;
	if (!(pointrc.top - rcTip.Height() - 15 < DsktopRc.top))
	{
		alainside = 3;//bottom
	}
	if (alainside==-1 && !(pointrc.bottom + rcTip.Height() + 15 > DsktopRc.bottom))
	{
		alainside = 1;//top
	}
	if (alainside==-1)
	{
		alainside = 3;
	}
	int alainoffset=20, offset = pointrc.left-20-DsktopRc.left, rectoffset = 0;
	if (offset<0)
	{
		if (offset>-pointrc.Width())
		{
			rectoffset -= offset;
		}
		else if (offset>-pointrc.Width()-10)
		{
			rectoffset = pointrc.Width();
			alainoffset += (offset+pointrc.Width());
		}
		else
		{
			alainside = 0;//left;
		}
	}
	if (alainside != 0 && !(offset<0))
	{
		offset = pointrc.left-20+rcTip.Width()-DsktopRc.right;
		if (offset>0)
		{
			if (offset<rcTip.Width()-30)
			{
				alainoffset += offset;
			}
			else
			{
				alainside = 2;//right;
			}
		}
	}
	CRect rcTipReal = rcTip;
	//}
	switch(alainside)
	{
	case 0:
		{
			rcTip.left -= 15;
			rcTip += CPoint(pointrc.right+15,pointrc.top-alainoffset);
			rcTipReal += CPoint(15,0);
		}
		break;
	case 1:
		{
			rcTip.top -= 15;
			rcTip += CPoint(pointrc.left+rectoffset-alainoffset,pointrc.bottom+15);
			rcTipReal += CPoint(0,15);
		}
		break;
	case 2:
		{
			rcTip.right += 15;
			rcTip += CPoint(pointrc.left-rcTip.Width(),pointrc.top-alainoffset);
		}
		break;
	case 3:
		{
			rcTip.bottom += 15;
			rcTip += CPoint(pointrc.left+rectoffset-alainoffset,pointrc.top-rcTip.Height());
		}
		break;
	default:
		break;
	}
	m_pWndInputCheck->SetMainRect(alainside,alainoffset,rcTipReal);
	m_pWndInputCheck->SetFont(lf);
	m_pWndInputCheck->SetText(sztmp);
	m_pWndInputCheck->MoveWindow(&rcTip);
	m_pWndInputCheck->ShowWindow(SW_SHOWNOACTIVATE);
	m_pWndInputCheck->SetWindowPos(&CWnd::wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW);
	m_pWndInputCheck->SetWindowPos(&CWnd::wndNoTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW);
	m_pWndInputCheck->KillTimer(TIMER_HIDETIP);
	m_pWndInputCheck->SetTimer(TIMER_HIDETIP,3000,NULL);
}

void CInputCheckTip::HideTip()
{
	if (m_pWndInputCheck->IsWindowVisible())
	{
		m_pWndInputCheck->ShowWindow(SW_HIDE);
	}
}

使用: 

	//1.在输入控件等需要检查的控件附着的弹出式窗口的OnCreate中调用:
	CInputCheckTip::AddInputCheckTip(this);
	//2.在控件焦点切换或者其他时机,检查输入,如果不满足限制条件使用一下代码弹出提示:
	CInputCheckTip::GetTipInstance(GetSafeHwnd())->PopTip(GetSafeHwnd(), rc/*控件的桌面坐标矩形*/,TIP_ERR_CUSTOM,_T("输入有误!"));

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值