MFC自定义半透明信息提示框

1.MessageBox类实现

// 头文件
#pragma once


// CMessageBox dialog

class CMessageBox : public CDialogEx
{
    DECLARE_DYNAMIC(CMessageBox)

public:
    CMessageBox(CWnd* pParent = NULL);   // standard constructor
    virtual ~CMessageBox();

// Dialog Data
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_MSG_BOX };
#endif

    enum MessageType {
        Pass,
        Fail,
        Normal,
        Custom
    };

    void ShowMessage(const CString& strMsg, MessageType type = MessageType::Normal, bool bDoModal = false);
    void CMessageBox::SetMessageInfo(const CString& msg,
        COLORREF backgroudColor = RGB(255, 255, 255),
        COLORREF fontColor = RGB(0, 0, 0),
        DWORD fontSize = 700,
        const CString& fontFormat = _T("宋体"));

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnPaint();
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    virtual void OnOK();

private:
    CString        m_strMsg;
    COLORREF    m_bkColor;
    COLORREF    m_fontColor;
    DWORD        m_fontSize;
    CString        m_fontFormat;
public:
    virtual BOOL OnInitDialog();
};


// 实现.cpp
// MessageBox.cpp : implementation file
//

#include "stdafx.h"
#include "CMessageBox.h"
#include "MessageBox.h"
#include "afxdialogex.h"


// CMessageBox dialog

IMPLEMENT_DYNAMIC(CMessageBox, CDialogEx)

CMessageBox::CMessageBox(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_MSG_BOX, pParent)
    , m_strMsg(_T(""))
    , m_bkColor(RGB(255, 255, 255))
    , m_fontColor(RGB(0, 0, 0))
    , m_fontFormat(_T("宋体"))
    , m_fontSize(700)
{

}

CMessageBox::~CMessageBox()
{
}


void CMessageBox::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CMessageBox, CDialogEx)
    ON_WM_PAINT()
    ON_WM_LBUTTONDOWN()
//    ON_WM_CLOSE()
END_MESSAGE_MAP()


// CMessageBox message handlers

// Repaint Event
void CMessageBox::OnPaint()
{
    // device context for painting
    CPaintDC dc(this); 

    // TODO: Add your message handler code here
    // Do not call CDialogEx::OnPaint() for painting messages
    CRect rect;
    GetClientRect(&rect);        // 获取客户区尺寸

    // 背景画刷
    CBrush brush(m_bkColor);
    // 前景字体
    CFont font;
    font.CreatePointFont(m_fontSize, m_fontFormat);
    // 将画刷和字体选入设备描述表
    dc.SelectObject(&font);
    dc.SelectObject(&brush);
    // 设置背景透明
    dc.SetBkMode(TRANSPARENT); 
    // 设置文本颜色
    dc.SetTextColor(m_fontColor);

    // 填充背景
    dc.FillRect(rect, &brush);
    // 绘制文字信息(水平垂直居中,单行显示)
    dc.DrawText(m_strMsg, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}

// Left button clicked
void CMessageBox::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    this->OnCancel();

    CDialogEx::OnLButtonDown(nFlags, point);
}


void CMessageBox::OnOK()
{
    // TODO: Add your specialized code here and/or call the base class
    return;
}


void CMessageBox::SetMessageInfo(const CString& msg, COLORREF backgroudColor /*= RGB(0, 0, 255)*/, COLORREF fontColor /*= RGB(0, 0, 0)*/, DWORD fontSize /*= 700*/, const CString& fontFormat /*= _T("宋体")*/)
{
    if (!msg.IsEmpty()) {
        m_strMsg = msg;
    }
    if (backgroudColor >= 0x00000000 && backgroudColor <= 0x00FFFFFF) {
        m_bkColor = backgroudColor;
    }
    if (fontColor >= 0x00000000 && fontColor <= 0x00FFFFFF) {
        m_fontColor = fontColor;
    }
    if (fontSize >= 0) {
        m_fontSize = fontSize;
    }
    if (!fontFormat.IsEmpty()) {
        m_fontFormat = fontFormat;
    }
}


// 模态和非模态模式显示信息,非模态显示必须保证在窗口关闭之前窗口对象的生命周期(窗口对象析构时会释放窗口资源)
void CMessageBox::ShowMessage(const CString& strMsg, MessageType type /*= MessageType::Normal*/, bool bDoModal/*= false*/)
{
    switch (type)
    {
    case CMessageBox::Pass:
        SetMessageInfo(strMsg, RGB(0, 255, 0));
        break;
    case CMessageBox::Fail:
        SetMessageInfo(strMsg, RGB(255, 0, 0));
        break;
    case CMessageBox::Normal:
        SetMessageInfo(strMsg);
        break;
    default:
        break;
    }

    // 模态和非模态模式
    if (bDoModal) {
        DoModal();
    }
    else {
        static int i = 0;
        // 第一次显示时创建窗口,不能创建
        if (i == 0) {
            this->Create(IDD_MSG_BOX, NULL); 
        }        
        this->ShowWindow(SW_SHOW); // 按照窗口预先设定的尺寸显示
        i++;
    }
}

BOOL CMessageBox::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // TODO:  Add extra initialization here
    //设置窗口大小,样式
    int cx = GetSystemMetrics(SM_CXSCREEN);
    int cy = GetSystemMetrics(SM_CYSCREEN);
    int iXpos = 0;
    int iYpos = cy / 2 - cy / 6;
    // 置顶窗口
    SetWindowPos(&CWnd::wndTopMost, iXpos, iYpos, cx, cy / 3, SWP_NOOWNERZORDER); // SWP_NOZORDER | SWP_NOOWNERZORDER
    // 设置窗口分层属性
    ::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE) | WS_EX_LAYERED); 
    // 设置分层窗口的不透明度, 透明度由alpha参数指定
    SetLayeredWindowAttributes(0, 150, LWA_ALPHA);

    return TRUE;  // return TRUE unless you set the focus to a control
                  // EXCEPTION: OCX Property Pages should return FALSE
}

 

2.使用

// CMessageBoxDlg.cpp : implementation file
//

#include "stdafx.h"
#include "CMessageBox.h"
#include "CMessageBoxDlg.h"
#include "afxdialogex.h"
#include "MessageBox.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CAboutDlg dialog used for App About

class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();

// Dialog Data
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_ABOUTBOX };
#endif

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CCMessageBoxDlg dialog



CCMessageBoxDlg::CCMessageBoxDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_CMESSAGEBOX_DIALOG, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CCMessageBoxDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CCMessageBoxDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BTN_PASS, &CCMessageBoxDlg::OnBnClickedBtnPass)
    ON_BN_CLICKED(IDC_BTN_FAIL, &CCMessageBoxDlg::OnBnClickedBtnFail)
    ON_WM_CLOSE()
    ON_BN_CLICKED(IDC_BTN_NORMAL, &CCMessageBoxDlg::OnBnClickedBtnNormal)
    ON_BN_CLICKED(IDC_BTN_CUSTOM, &CCMessageBoxDlg::OnBnClickedBtnCustom)
END_MESSAGE_MAP()


// CCMessageBoxDlg message handlers

BOOL CCMessageBoxDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // Add "About..." menu item to system menu.

    // IDM_ABOUTBOX must be in the system command range.
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);            // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon

    // TODO: Add extra initialization here
    if (m_msgBox == nullptr)
        m_msgBox = new CMessageBox(this);

    return TRUE;  // return TRUE  unless you set the focus to a control
}

void CCMessageBoxDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CCMessageBoxDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CCMessageBoxDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}



void CCMessageBoxDlg::OnBnClickedBtnPass()
{
    // TODO: Add your control notification handler code here
    if (m_msgBox) {
        m_msgBox->ShowMessage(_T("测试OK"), CMessageBox::MessageType::Pass);
    }
    TRACE("\n--------------------------------------------------------------");
}


void CCMessageBoxDlg::OnBnClickedBtnFail()
{
    // TODO: Add your control notification handler code here
    if (m_msgBox) {
        m_msgBox->ShowMessage(_T("测试Fail"), CMessageBox::MessageType::Fail);
    }
    TRACE("\n--------------------------------------------------------------");
}


void CCMessageBoxDlg::OnOK()
{
    // TODO: Add your specialized code here and/or call the base class
    return;
}


void CCMessageBoxDlg::OnCancel()
{
    // TODO: Add your specialized code here and/or call the base class
    return;
}


void CCMessageBoxDlg::OnClose()
{
    // TODO: Add your message handler code here and/or call default
    if (m_msgBox != nullptr) {
        m_msgBox->DestroyWindow();
        delete m_msgBox;
    }

    CDialogEx::OnCancel();
    //CDialogEx::OnClose();
}


void CCMessageBoxDlg::OnBnClickedBtnNormal()
{
    // 模态调用
    CMessageBox box;
    box.ShowMessage(_T("正常..."), CMessageBox::MessageType::Normal, true);
}


void CCMessageBoxDlg::OnBnClickedBtnCustom()
{
    // TODO: Add your control notification handler code here
    // 模态调用
    CMessageBox box;
    box.SetMessageInfo(_T("测试中..."), RGB(255, 255, 0));
    box.ShowMessage(_T(""), CMessageBox::MessageType::Custom, true);
}

 

3.效果图

 

posted @ 2020-08-11 23:18  碎银三二两  阅读(441)  评论(0编辑  收藏  举报