Windows编程入门(5)MFC程序最小托盘化

2024-03-27 12:32

本文主要是介绍Windows编程入门(5)MFC程序最小托盘化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 转载自http://blog.csdn.net/csf111/article/details/6980508

  为了使MFC程序(SDI,MDI,DLG)均能最小化到系统托盘,这里运用消息机制来实现系统托盘效果。

          那么什么是托盘呢?所谓的“托盘”,在Windows系统界面中,指的就是下面任务条右侧,有系统时间等等的标志的那一部分。在程序最小化或挂起时,但有不希望占据任务栏的时候,就可以把程序放到托盘区。

          怎么实现呢?这里需要运用到的Windows API函数:

BOOL Shell_NotifyIcon(DWORD dwMessage, PNOTIFYICONDATA lpdata
);
          函数了里面的参数对于实现不同的效果尤其重要,包括托盘图标、托盘菜单等等。那么我们来了解一下两个参数吧:

dwMessage可以取以下值:

NIM_ADD 向托盘中加入一个图标
NIM_MODIFY 修改托盘中的图标
NIM_DELETE 从托盘中删除一个图标

参数pnid是NOTIFYICONDATA结构的一个引用。该结构的原型如下:

[cpp] view plaincopyprint?
  1. typedef struct _NOTIFYICONDATA {   
  2.     DWORD cbSize; // 结构的大小,必须在程序中给出  
  3.     HWND hWnd;    // 程序中将要接收托盘消息的窗口句柄  
  4.     UINT uID;     // 应用程序中定义的托盘图标ID,此参数用作标识  
  5.     UINT uFlags;  //设置属性 标记下边3个参数是否有效  
  6.     UINT uCallbackMessage;// 自定义的消息ID值  
  7.     HICON hIcon;//显示在系统托盘上的Icon的句柄  
  8.     #if (_WIN32_IE < 0x0500)   
  9.         TCHAR szTip[64;// 用于图标显示的提示字符串  
  10.     #else   
  11.         TCHAR szTip[128];  
  12.     #endif   
  13.     #if (_WIN32_IE >= 0x0500)  
  14.         DWORD dwState;   
  15.         DWORD dwStateMask;   
  16.         TCHAR szInfo[256];   
  17.         union {  
  18.             UINT  uTimeout;   
  19.             UINT  uVersion;   
  20.         } DUMMYUNIONNAME;  
  21.         TCHAR szInfoTitle[64];   
  22.         DWORD dwInfoFlags;   
  23.     #endif   
  24.     #if (_WIN32_IE >= 0x600)   
  25.         GUID guidItem;  
  26.     #endif   
  27. } NOTIFYICONDATA, *PNOTIFYICONDATA;   
[cpp] view plain copy
 print?
  1. typedef struct _NOTIFYICONDATA {   
  2.     DWORD cbSize; // 结构的大小,必须在程序中给出  
  3.     HWND hWnd;    // 程序中将要接收托盘消息的窗口句柄  
  4.     UINT uID;     // 应用程序中定义的托盘图标ID,此参数用作标识  
  5.     UINT uFlags;  //设置属性 标记下边3个参数是否有效  
  6.     UINT uCallbackMessage;// 自定义的消息ID值  
  7.     HICON hIcon;//显示在系统托盘上的Icon的句柄  
  8.     #if (_WIN32_IE < 0x0500)  
  9.         TCHAR szTip[64;// 用于图标显示的提示字符串  
  10.     #else  
  11.         TCHAR szTip[128];  
  12.     #endif  
  13.     #if (_WIN32_IE >= 0x0500)  
  14.         DWORD dwState;   
  15.         DWORD dwStateMask;   
  16.         TCHAR szInfo[256];   
  17.         union {  
  18.             UINT  uTimeout;   
  19.             UINT  uVersion;   
  20.         } DUMMYUNIONNAME;  
  21.         TCHAR szInfoTitle[64];   
  22.         DWORD dwInfoFlags;   
  23.     #endif  
  24.     #if (_WIN32_IE >= 0x600)  
  25.         GUID guidItem;  
  26.     #endif  
  27. } NOTIFYICONDATA, *PNOTIFYICONDATA;   
           具体步骤如下:

1.在程序中增加一个私有的NOTIFYICONDAT对象

[cpp] view plaincopyprint?
  1. private:  
  2.         NOTIFYICONDATA m_tnid;  
[cpp] view plain copy
 print?
  1. private:  
  2.         NOTIFYICONDATA m_tnid;  
2.在初始化窗口时对NOTIFYICONDAT对象初始化 用Shell_NotifyIcon函数进行注册
[cpp] view plaincopyprint?
  1. m_notify.cbSize=sizeof NOTIFYICONDATA;  
  2. m_notify.hWnd=this->m_hWnd;    
  3. m_notify.uID=IDR_MAINFRAME;  
  4. m_notify.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));  
  5. strcpy(m_notify.szTip,"Michael_Chen is a good man");  
  6. m_notify.uCallbackMessage=WM_USER_NOTIFYICON;  
  7. m_notify.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP; //OK,下面就是托盘产生了.   
  8. Shell_NotifyIcon(NIM_ADD,&m_notify);  
[cpp] view plain copy
 print?
  1. m_notify.cbSize=sizeof NOTIFYICONDATA;  
  2. m_notify.hWnd=this->m_hWnd;    
  3. m_notify.uID=IDR_MAINFRAME;  
  4. m_notify.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));  
  5. strcpy(m_notify.szTip,"Michael_Chen is a good man");  
  6. m_notify.uCallbackMessage=WM_USER_NOTIFYICON;  
  7. m_notify.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP; //OK,下面就是托盘产生了.   
  8. Shell_NotifyIcon(NIM_ADD,&m_notify);  
3.增加自定义的消息处理函数或者重载WindowProc函数,在消息处理函数或WindowProc函数中对自定义的消息进行处理

1)运用自定义消息

i,WM_USER_NOTIFYICON是自定义的消息 在头文件中进行声明;

[cpp] view plaincopyprint?
  1. #define WM_USER_NOTIFYICON WM_USER+1  
[cpp] view plain copy
 print?
  1. #define WM_USER_NOTIFYICON WM_USER+1  
ii,在.h文件中声明消息函数原型
[cpp] view plaincopyprint?
  1. afx_msg LRESULT OnNotifyMsg(WPARAM wparam,LPARAM lparam);  
[cpp] view plain copy
 print?
  1. afx_msg LRESULT OnNotifyMsg(WPARAM wparam,LPARAM lparam);  
iii,在.cpp文件中进行消息映射
[cpp] view plaincopyprint?
  1. BEGIN_MESSAGE_MAP(CNotifyiconDlg, CDialog)  
  2.     //{{AFX_MSG_MAP(CNotifyiconDlg)   
  3.                  ...  
  4.     ON_MESSAGE(WM_USER_NOTIFYICON,OnNotifyMsg)  
  5.     //}}AFX_MSG_MAP   
  6. END_MESSAGE_MAP()  
[cpp] view plain copy
 print?
  1. BEGIN_MESSAGE_MAP(CNotifyiconDlg, CDialog)  
  2.     //{{AFX_MSG_MAP(CNotifyiconDlg)  
  3.                  ...  
  4.     ON_MESSAGE(WM_USER_NOTIFYICON,OnNotifyMsg)  
  5.     //}}AFX_MSG_MAP  
  6. END_MESSAGE_MAP()  
iiii,在.cpp文件中添加自定义的消息响应代码,左键双击弹出应用程序主窗口,右键单击弹出菜单。
[cpp] view plaincopyprint?
  1. LRESULT  CNotifyiconDlg::OnNotifyMsg(WPARAM wparam,LPARAM lparam)  
  2. //wParam接收的是图标的ID,而lParam接收的是鼠标的行为      
  3. {  
  4.     if(wparam!=IDR_MAINFRAME)     
  5.         return    1;     
  6.     switch(lparam)     
  7.     {     
  8.     case  WM_RBUTTONUP://右键起来时弹出快捷菜单,这里只有一个“关闭”     
  9.         {       
  10.             LPPOINT    lpoint=new    tagPOINT;     
  11.             ::GetCursorPos(lpoint);//得到鼠标位置     
  12.             CMenu    menu;     
  13.             menu.CreatePopupMenu();//声明一个弹出式菜单     
  14.             //增加菜单项“关闭”,点击则发送消息WM_DESTROY给主窗口(已     
  15.             //隐藏),将程序结束。      
  16.             menu.AppendMenu(MF_STRING,WM_DESTROY,"关闭");       
  17.             //确定弹出式菜单的位置      
  18.             menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x,lpoint->y,this);     
  19.             //资源回收      
  20.             HMENU    hmenu=menu.Detach();     
  21.             menu.DestroyMenu();     
  22.             delete    lpoint;     
  23.         }     
  24.         break;     
  25.     case    WM_LBUTTONDBLCLK://双击左键的处理     
  26.         {     
  27.             this->ShowWindow(SW_SHOW);//简单的显示主窗口完事儿     
  28.         }     
  29.         break;     
  30.     }      
  31.     return 0;  
  32. }  
[cpp] view plain copy
 print?
  1. LRESULT  CNotifyiconDlg::OnNotifyMsg(WPARAM wparam,LPARAM lparam)  
  2. //wParam接收的是图标的ID,而lParam接收的是鼠标的行为     
  3. {  
  4.     if(wparam!=IDR_MAINFRAME)     
  5.         return    1;     
  6.     switch(lparam)     
  7.     {     
  8.     case  WM_RBUTTONUP://右键起来时弹出快捷菜单,这里只有一个“关闭”     
  9.         {       
  10.             LPPOINT    lpoint=new    tagPOINT;     
  11.             ::GetCursorPos(lpoint);//得到鼠标位置     
  12.             CMenu    menu;     
  13.             menu.CreatePopupMenu();//声明一个弹出式菜单     
  14.             //增加菜单项“关闭”,点击则发送消息WM_DESTROY给主窗口(已     
  15.             //隐藏),将程序结束。     
  16.             menu.AppendMenu(MF_STRING,WM_DESTROY,"关闭");       
  17.             //确定弹出式菜单的位置     
  18.             menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x,lpoint->y,this);     
  19.             //资源回收     
  20.             HMENU    hmenu=menu.Detach();     
  21.             menu.DestroyMenu();     
  22.             delete    lpoint;     
  23.         }     
  24.         break;     
  25.     case    WM_LBUTTONDBLCLK://双击左键的处理     
  26.         {     
  27.             this->ShowWindow(SW_SHOW);//简单的显示主窗口完事儿     
  28.         }     
  29.         break;     
  30.     }      
  31.     return 0;  
  32. }  

2)重载WindowProc函数

i,重载WindowProc函数(方法略)

ii,在WindowProc中增加的消息相应代码

[cpp] view plaincopyprint?
  1. //WindowProc中增加的代码   
  2. LRESULT CNotifyiconDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)   
  3. {  
  4.     // TODO: Add your specialized code here and/or call the base class  
  5.     switch(message) //判断消息类型  
  6.     {   
  7.     case WM_USER_NOTIFYICON:   
  8.         //如果是用户定义的消息    
  9.         if(lParam==WM_LBUTTONDBLCLK)  
  10.               
  11.         {   
  12.             //鼠标双击时主窗口出现    
  13.             if(AfxGetApp()->m_pMainWnd->IsWindowVisible()) //判断窗口当前状态  
  14.             {  
  15.                 AfxGetApp()->m_pMainWnd->ShowWindow(SW_HIDE); //隐藏窗口  
  16.             }  
  17.             else  
  18.             {  
  19.                 AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOW); //显示窗口  
  20.             }  
  21.               
  22.         }   
  23.         else if(lParam==WM_RBUTTONDOWN)  
  24.         { //鼠标右键单击弹出选单    
  25.             CMenu menu;   
  26.             menu.LoadMenu(IDR_MENU1); //载入事先定义的选单   
  27.             CMenu *pMenu=menu.GetSubMenu(0);   
  28.             CPoint pos;   
  29.             GetCursorPos(&pos);   
  30.             pMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,pos.x,pos.y,AfxGetMainWnd());   
  31.         }   
  32.         break;   
  33.     case WM_SYSCOMMAND:   
  34.         //如果是系统消息    
  35.         if(wParam==SC_MINIMIZE)  
  36.         {   
  37.             //接收到最小化消息时主窗口隐藏    
  38.             AfxGetApp()->m_pMainWnd->ShowWindow(SW_HIDE);   
  39.             return 0;   
  40.         }   
  41.         if(wParam==SC_CLOSE)  
  42.         {  
  43.             ::Shell_NotifyIcon(NIM_DELETE,&m_notify); //关闭时删除系统托盘图标  
  44.         }  
  45.         break;  
  46.     }  
  47.     return CDialog::WindowProc(message, wParam, lParam);  
  48. }  
[cpp] view plain copy
 print?
  1. //WindowProc中增加的代码  
  2. LRESULT CNotifyiconDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)   
  3. {  
  4.     // TODO: Add your specialized code here and/or call the base class  
  5.     switch(message) //判断消息类型  
  6.     {   
  7.     case WM_USER_NOTIFYICON:   
  8.         //如果是用户定义的消息   
  9.         if(lParam==WM_LBUTTONDBLCLK)  
  10.               
  11.         {   
  12.             //鼠标双击时主窗口出现   
  13.             if(AfxGetApp()->m_pMainWnd->IsWindowVisible()) //判断窗口当前状态  
  14.             {  
  15.                 AfxGetApp()->m_pMainWnd->ShowWindow(SW_HIDE); //隐藏窗口  
  16.             }  
  17.             else  
  18.             {  
  19.                 AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOW); //显示窗口  
  20.             }  
  21.               
  22.         }   
  23.         else if(lParam==WM_RBUTTONDOWN)  
  24.         { //鼠标右键单击弹出选单   
  25.             CMenu menu;   
  26.             menu.LoadMenu(IDR_MENU1); //载入事先定义的选单   
  27.             CMenu *pMenu=menu.GetSubMenu(0);   
  28.             CPoint pos;   
  29.             GetCursorPos(&pos);   
  30.             pMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,pos.x,pos.y,AfxGetMainWnd());   
  31.         }   
  32.         break;   
  33.     case WM_SYSCOMMAND:   
  34.         //如果是系统消息   
  35.         if(wParam==SC_MINIMIZE)  
  36.         {   
  37.             //接收到最小化消息时主窗口隐藏   
  38.             AfxGetApp()->m_pMainWnd->ShowWindow(SW_HIDE);   
  39.             return 0;   
  40.         }   
  41.         if(wParam==SC_CLOSE)  
  42.         {  
  43.             ::Shell_NotifyIcon(NIM_DELETE,&m_notify); //关闭时删除系统托盘图标  
  44.         }  
  45.         break;  
  46.     }  
  47.     return CDialog::WindowProc(message, wParam, lParam);  
  48. }  


        经过以上的步骤,就编写出了一个简单的可以最小化到托盘的程序。该程序在一启动时,在托盘创立应用程序的图标,最小化程序时隐藏主窗口,双击托盘区的图标时,显示主窗口,右键点击托盘区窗口时,弹出菜单。


这篇关于Windows编程入门(5)MFC程序最小托盘化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/852107

相关文章

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

Windows设置nginx启动端口的方法

《Windows设置nginx启动端口的方法》在服务器配置与开发过程中,nginx作为一款高效的HTTP和反向代理服务器,被广泛应用,而在Windows系统中,合理设置nginx的启动端口,是确保其正... 目录一、为什么要设置 nginx 启动端口二、设置步骤三、常见问题及解决一、为什么要设置 nginx

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

在 Windows 上安装 DeepSeek 的完整指南(最新推荐)

《在Windows上安装DeepSeek的完整指南(最新推荐)》在Windows上安装DeepSeek的完整指南,包括下载和安装Ollama、下载DeepSeekRXNUMX模型、运行Deep... 目录在www.chinasem.cn Windows 上安装 DeepSeek 的完整指南步骤 1:下载并安装

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

Windows自动化Python pyautogui RPA操作实现

《Windows自动化PythonpyautoguiRPA操作实现》本文详细介绍了使用Python的pyautogui库进行Windows自动化操作的实现方法,文中通过示例代码介绍的非常详细,对大... 目录依赖包睡眠:鼠标事件:杀死进程:获取所有窗口的名称:显示窗口:根据图片找元素:输入文字:打开应用:依

javafx 如何将项目打包为 Windows 的可执行文件exe

《javafx如何将项目打包为Windows的可执行文件exe》文章介绍了三种将JavaFX项目打包为.exe文件的方法:方法1使用jpackage(适用于JDK14及以上版本),方法2使用La... 目录方法 1:使用 jpackage(适用于 JDK 14 及更高版本)方法 2:使用 Launch4j(

windows端python版本管理工具pyenv-win安装使用

《windows端python版本管理工具pyenv-win安装使用》:本文主要介绍如何通过git方式下载和配置pyenv-win,包括下载、克隆仓库、配置环境变量等步骤,同时还详细介绍了如何使用... 目录pyenv-win 下载配置环境变量使用 pyenv-win 管理 python 版本一、安装 和

Python使用pysmb库访问Windows共享文件夹的详细教程

《Python使用pysmb库访问Windows共享文件夹的详细教程》本教程旨在帮助您使用pysmb库,通过SMB(ServerMessageBlock)协议,轻松连接到Windows共享文件夹,并列... 目录前置条件步骤一:导入必要的模块步骤二:配置连接参数步骤三:实例化SMB连接对象并尝试连接步骤四: