类似360消息弹出框,实现方式一见http://blog.csdn.net/segen_jaa/article/details/7848598。
本文采用另外的API实现渐入渐出效果。
主要API:SetLayeredWindowAttributes。
实现功能:
采用管理器控制消息框每次只显示一个。
消息框独立显示在右下角,不随主窗口放大缩小变化。
鼠标进入消息框区域,渐入渐出效果停止。
1、消息框实现
创建对话框类CMsgTipDlg,设置对话框属性。
Tool Window:true。设置对话框为消息框,任务栏上将没有图标。
Topmost:true。设置对话框置顶。
MsgTipDlg.h。
#pragma once // CMsgTipDlg dialog class CMsgTipMng; class CMsgTipDlg : public CDialog { DECLARE_DYNAMIC(CMsgTipDlg) public: CMsgTipDlg(CMsgTipMng* pTipMng, const CString& strTipInfo, CWnd* pParent = NULL); // standard constructor virtual ~CMsgTipDlg(); // Dialog Data enum { IDD = IDD_MCMSG_DLG }; void ShowMsgWindow(); int GetTipID() const { return m_nTipID; } protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual BOOL OnInitDialog(); virtual void OnCancel(); virtual void PostNcDestroy(); virtual BOOL PreTranslateMessage(MSG* pMsg); afx_msg void OnTimer(UINT_PTR nIDEvent); afx_msg void OnBnClickedOk(); afx_msg void OnBnClickedCancel(); afx_msg void OnMouseMove(UINT nFlags, CPoint point); DECLARE_MESSAGE_MAP() private: void InitDlgPosition(); private: CMsgTipMng* m_pTipMng; CString m_strTipInfo; int m_nTipID; BYTE m_bAlpha;//淡入淡出透明效果 };
MsgTipDlg.cpp。
// MCMsgTipDlg.cpp : implementation file // #include "stdafx.h" #include "mcmsgtip_demo.h" #include "MsgTipDlg.h" #include "MsgTipMng.h" const UINT_PTR BLAND_IN = 1; const UINT_PTR DLG_DELAY = 2; const UINT_PTR BLAND_OUT = 3; const UINT IN_ELAPSE = 50; const UINT DELAY_ELAPSE = 5000; const UINT OUT_ELAPSE = 50; //淡入淡出跨度 const BYTE BLAND_SPAN = 15; //淡入淡出最小值 const BYTE BLAND_MIN = 0; //淡入淡出最大值 const BYTE BLAND_MAX = 255; //淡入淡出颜色值设置 const COLORREF BLAND_COLOR = 0; // CMsgTipDlg dialog IMPLEMENT_DYNAMIC(CMsgTipDlg, CDialog) CMsgTipDlg::CMsgTipDlg(CMsgTipMng* pTipMng, const CString& strTipInfo, CWnd* pParent) : CDialog(CMsgTipDlg::IDD, pParent) , m_pTipMng(pTipMng) , m_strTipInfo(strTipInfo) , m_nTipID(0) , m_bAlpha(0) { static int s_nTipID = 0; ++s_nTipID; m_nTipID = s_nTipID; } CMsgTipDlg::~CMsgTipDlg() { } void CMsgTipDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CMsgTipDlg, CDialog) ON_WM_TIMER() ON_WM_MOUSEMOVE() ON_BN_CLICKED(IDOK, &CMsgTipDlg::OnBnClickedOk) ON_BN_CLICKED(IDCANCEL, &CMsgTipDlg::OnBnClickedCancel) END_MESSAGE_MAP() // CMsgTipDlg message handlers void CMsgTipDlg::ShowMsgWindow() { HWND hActiveHwnd = ::GetActiveWindow(); Create(IDD, GetDesktopWindow()); ShowWindow(SW_HIDE); ShowWindow(SW_SHOWNOACTIVATE); if (hActiveHwnd != NULL) { ::SetActiveWindow(hActiveHwnd); } } BOOL CMsgTipDlg::OnInitDialog() { CDialog::OnInitDialog(); // TODO: Add extra initialization here SetDlgItemText(IDC_TIP_INFO, m_strTipInfo); InitDlgPosition(); //设置窗口可淡入淡出 ModifyStyleEx(NULL, WS_EX_LAYERED); //消息渐入渐出效果 SetTimer(BLAND_IN, IN_ELAPSE, NULL); return TRUE; } void CMsgTipDlg::InitDlgPosition() { CRect rectInit; GetWindowRect(&rectInit); RECT rect; SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); int cy = rect.bottom-rect.top; int cx = rect.right-rect.left; int nx = rect.right - rectInit.Width(); int ny = cy - rectInit.Height(); rectInit.MoveToXY(nx, ny); MoveWindow(rectInit); } void CMsgTipDlg::OnTimer(UINT_PTR nIDEvent) { RECT rect; SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0); int cy = rect.bottom-rect.top; int cx = rect.right-rect.left; CRect rectTip; GetWindowRect(&rectTip); switch (nIDEvent) { case BLAND_IN: { if (m_bAlpha > (BLAND_MAX - BLAND_SPAN)) { m_bAlpha = BLAND_MAX; } else { m_bAlpha += BLAND_SPAN; } SetLayeredWindowAttributes(BLAND_COLOR, m_bAlpha, LWA_ALPHA); if (BLAND_MAX == m_bAlpha) { KillTimer(BLAND_IN); SetTimer(DLG_DELAY, DELAY_ELAPSE, NULL); } break; } case DLG_DELAY: { KillTimer(DLG_DELAY); SetTimer(BLAND_OUT, OUT_ELAPSE, NULL); break; } case BLAND_OUT: { if (m_bAlpha < BLAND_SPAN) { m_bAlpha = BLAND_MIN; } else { m_bAlpha -= BLAND_SPAN; } SetLayeredWindowAttributes(BLAND_COLOR, m_bAlpha, LWA_ALPHA); if (BLAND_MIN == m_bAlpha) { KillTimer(BLAND_OUT); PostMessage(WM_CLOSE); } break; } } CDialog::OnTimer(nIDEvent); } void CMsgTipDlg::OnCancel() { DestroyWindow(); } void CMsgTipDlg::PostNcDestroy() { CDialog::PostNcDestroy(); //窗口销毁时,删除该对象 m_pTipMng->RemoveTipWindow(m_nTipID); } void CMsgTipDlg::OnBnClickedOk() { OnCancel(); //::MessageBox(AfxGetMainWnd()->GetSafeHwnd(), _T("提示框的反馈-是"), _T("提示"), MB_OK); } void CMsgTipDlg::OnBnClickedCancel() { OnCancel(); } BOOL CMsgTipDlg::PreTranslateMessage(MSG* pMsg) { //对话框屏蔽Enter和ESC键 if (WM_KEYDOWN == pMsg->message) { if ( (VK_RETURN == pMsg->wParam) || (VK_ESCAPE == pMsg->wParam)) { return TRUE; } } return CDialog::PreTranslateMessage(pMsg); } void CMsgTipDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CRect rect; GetClientRect(&rect); //显示对话框 if (m_bAlpha < BLAND_MAX) { KillTimer(BLAND_IN); KillTimer(DLG_DELAY); KillTimer(BLAND_OUT); m_bAlpha = BLAND_MAX; SetLayeredWindowAttributes(BLAND_COLOR, m_bAlpha, LWA_ALPHA); //继续等待 SetTimer(DLG_DELAY, DELAY_ELAPSE, NULL); } CDialog::OnMouseMove(nFlags, point); }
2、消息框管理器
消息框管理器功能:控制每次只弹出一个消息框。
MsgTipMng.h。
/* @brief 消息提示管理器 @date 2012-08-10 */ #pragma once #include "MsgTipDlg.h" #include <vector> #include <algorithm> using namespace std; class CMsgTipMng { public: CMsgTipMng(void); ~CMsgTipMng(void); void AddTipWindow(const CString& strTipInfo); void RemoveTipWindow(int nTipID); private: void ShowTipWindow(); private: vector<CMsgTipDlg*> m_vTipVct; bool m_bInShow;//是否有消息框弹出 };
MsgTipMng.cpp。
#include "StdAfx.h" #include "mcmsgtip_demo.h" #include "MsgTipMng.h" class vcttip_finder { public: vcttip_finder(int nTipID) : m_nTipID(nTipID) { } bool operator()(const CMsgTipDlg* pTipDlg) { if (NULL == pTipDlg) { return false; } int nInTipID = pTipDlg->GetTipID(); return (m_nTipID == nInTipID); } private: int m_nTipID; }; CMsgTipMng::CMsgTipMng(void) : m_bInShow(false) { } CMsgTipMng::~CMsgTipMng(void) { } void CMsgTipMng::AddTipWindow(const CString& strTipInfo) { m_vTipVct.push_back(new CMsgTipDlg(this, strTipInfo)); ShowTipWindow(); } void CMsgTipMng::RemoveTipWindow(int nTipID) { vector<CMsgTipDlg*>::iterator vIter = find_if(m_vTipVct.begin(), m_vTipVct.end(), vcttip_finder(nTipID)); if (vIter == m_vTipVct.end()) { return; } m_vTipVct.erase(vIter); m_bInShow = false; ShowTipWindow(); } void CMsgTipMng::ShowTipWindow() { if (m_vTipVct.empty()) { return; } if (m_bInShow) { return; } m_bInShow = true; m_vTipVct[0]->ShowMsgWindow(); }
3、消息框显示
m_pTipMng为成员变量,类型CMsgTipMng*。
显示对话框:
m_pTipMng->AddTipWindow(_T("Hello World!"));