现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

MFC渐入渐出框实现方式二

2012-08-21 06:22 工业·编程 ⁄ 共 6829字 ⁄ 字号 暂无评论

    类似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!"));

给我留言

留言无头像?