类似360消息弹出框,见实现方式一。本文采用另外的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!"));