MFC实现窗口关闭为最小化托盘

新建一个 MinTray 的MFC工程(基于Dialog),
在 MinTrayDlg.h 头文件中,自定义消息 WM_SHOWTASK

////////////////// MinTrayDlg.h   ///////////////
#pragma once
#define WM_SHOWTASK (WM_USER +1) //自定义消息WM_SHOWTASK

//添加成员函数
class CMinTrayDlg : public CDialogEx
{
   //....
    afx_msg LRESULT OnShowTask(WPARAM wParam, LPARAM lParam);//wParam接收的是图标的ID,而lParam接收的是鼠标的行为
    //1、最小化的原理:首先要将窗口隐藏,然后在右下角绘制图标。
    //2、恢复的原理:将窗口显示,再将托盘中的图片删除。
    void ToTray();//最小化窗口到托盘
    void DeleteTray();////删除托盘图标函数   
}

在 MinTrayDlg.cpp 中

// MinTrayDlg.cpp : 实现文件

BEGIN_MESSAGE_MAP(CMinTrayDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_MESSAGE(WM_SHOWTASK, OnShowTask) //其中WM_SHOWTASK是消息名,OnShowTask是自己定义的消息响应函数

END_MESSAGE_MAP()



void CMinTrayDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else if (nID == SC_CLOSE)//右上角的关闭和标题栏的关闭WM_CLOSE
    {
        ToTray();//最小化到托盘
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}

LRESULT CMinTrayDlg::OnShowTask(WPARAM wParam, LPARAM lParam)
{//wParam接收的是图标的ID,而lParam接收的是鼠标的行为
    if (wParam != IDR_MAINFRAME)
        return 1;
    switch (lParam)
    {
    case WM_RBUTTONUP://右键起来时弹出快捷菜单,这里只有一个“关闭”
    {
        LPPOINT lpoint = new tagPOINT;
        ::GetCursorPos(lpoint);//得到鼠标位置
        CMenu menu;
        menu.CreatePopupMenu();//声明一个弹出式菜单
        menu.AppendMenu(MF_STRING, WM_DESTROY, L"关闭"); //增加菜单项“关闭”,点击则发送消息WM_DESTROY给主窗口(已隐藏),将程序结束。
        menu.TrackPopupMenu(TPM_LEFTALIGN, lpoint->x, lpoint->y, this); //确定弹出式菜单的位置
        HMENU hmenu = menu.Detach();
        menu.DestroyMenu(); //资源回收
        delete lpoint;
    } break;
    case WM_LBUTTONDBLCLK: //双击左键的处理
    {
        this->ShowWindow(SW_SHOW);//简单的显示主窗口完事儿
        DeleteTray();
    } break;
    default: break;
    }
    return 0;
}

//最小化窗口到托盘
void CMinTrayDlg::ToTray()
{
    NOTIFYICONDATA nid;
    nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
    nid.hWnd = this->m_hWnd;
    nid.uID = IDR_MAINFRAME;
    nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    nid.uCallbackMessage = WM_SHOWTASK;//自定义的消息名称
    nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
    wcscpy(nid.szTip, L"程序名称"); //信息提示条
    Shell_NotifyIcon(NIM_ADD, &nid); //在托盘区添加图标
    ShowWindow(SW_HIDE); //隐藏主窗口
}

//删除托盘图标函数
void CMinTrayDlg::DeleteTray()
{
    NOTIFYICONDATA nid;
    nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
    nid.hWnd = this->m_hWnd;
    nid.uID = IDR_MAINFRAME;
    nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    nid.uCallbackMessage = WM_SHOWTASK; //自定义的消息名称
    nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
    wcscpy(nid.szTip, L"程序名称"); //信息提示条为“计划任务提醒”
    Shell_NotifyIcon(NIM_DELETE, &nid); //在托盘区删除图标
}

 

另外:MFC中屏蔽 Esc 和 Enter 关闭窗口(由于Esc直接调用 OnCancel(),Enter 直接调用 OnOk())

方法一:

在头文件中

protected:
     virtual BOOL PreTranslateMessage(MSG* pMsg);  // PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的
public:
     virtual void OnOK();

在cpp文件中

BOOL CxxxDlg::PreTranslateMessage(MSG* pMsg)
{
    //屏蔽ESC关闭窗体/
    if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_ESCAPE ) return TRUE;
    //屏蔽回车关闭窗体,但会导致回车在窗体上失效.
    //if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN && pMsg->wParam) return TRUE;
    else
        return CDialog::PreTranslateMessage(pMsg);
}
void CxxxDlg::OnOK()
{
    //CDialogEx::OnOK();
}

方法二:

//////////////////  头文件  /////////

public:
    virtual void OnOK();
    virtual void OnCancel();
    afx_msg void OnClose(); //响应关闭事件!


/////////////// cpp文件  /////////////////
void CxxxDlg::OnOK()
{
    return;
}
void CxxxDlg::OnCancel()
{
    return;
}
void CxxxDlg::OnClose()
{
    // TODO:  在此添加消息处理程序代码和/或调用默认值
    
    CDialogEx::OnCancel();
    //CDialogEx::OnClose();
}

 

posted @ 2019-10-16 20:43  htj10  阅读(987)  评论(0编辑  收藏  举报
TOP