c++中托盘图标的生成

通俗点,先举个例子,我们在挂着QQ的时候通常在右下角菜单上会看到一个QQ的图标,双击这个图标,qq就会弹出显示在桌面上,如下如所示:

c++中托盘图标的生成

看,QQ,还有我现在测试的windows小程序都有了图标,这个图标我们称之为托盘图标

下面说下在c++中如何实现;

环境:vs2010+win xp

----------------------风格线---------------------

前阵子做过android对接blog的一个小应用,在android中就有NotificationManager类管理android托盘

c++中托盘图标的生成

所在在c++中一样有专门管理托盘的结构体

下面先看看结构体的定义(摘自msdn library):

NOTIFYICONDATA


typedef struct _NOTIFYICONDATA { 
    DWORD cbSize; 
    HWND hWnd; 
    UINT uID; 
    UINT uFlags; 
    UINT uCallbackMessage; 
    HICON hIcon; 
    char szTip[64]; 
} NOTIFYICONDATA, *PNOTIFYICONDATA; 


Contains information that the system needs to process taskbar status area messages. 

cbSize 
Size of this structure, in bytes. 
hWnd 
Handle to the window that will receive notification messages associated with an icon in the taskbar status area. 
uID 
Application-defined identifier of the taskbar icon. 
uFlags 
Array of flags that indicate which of the other members contain valid data. This member can be a combination of the following: NIF_ICON  The hIcon member is valid.  
NIF_MESSAGE  The uCallbackMessage member is valid. 
NIF_TIP  The szTip member is valid. 

uCallbackMessage 
Application-defined message identifier. The system uses this identifier for notification messages that it sends to the window identified in hWnd. These notifications are sent when a mouse event occurs in the bounding rectangle of the icon. 
hIcon 
Handle to the icon to add, modify, or delete. 
szTip 
Tooltip text to display for the icon.

具体参数的意义,请自信阅读,说明都很详细。

下面还需要了解一个函数:Shell_NotifyIcon

全局函数Shell_NotifyIcon() 用于在托盘上增加、删除或修改图标。其原型为

Shell_NotifyIcon


WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(
    DWORD dwMessage, 
    PNOTIFYICONDATA pnid
);    

Sends a message to the system to add, modify, or delete an icon from the taskbar status area. 

Returns nonzero if successful, or zero otherwise. 
dwMessage 
Message value to send. This parameter can be one of these values: NIM_ADD  Adds an icon to the status area. 
NIM_DELETE  Deletes an icon from the status area. 
NIM_MODIFY  Modifies an icon in the status area.  

pnid 
Address of a NOTIFYICONDATA structure. The content of the structure depends on the value of dwMessage.

好了,了解一个结构体,一个全局方法后即可编写自己的托盘,并且diy各种小功能了:

下面说说一个简单的实例:

1) 在所要处理的Frame或Dialog中添加保护成员变量

protected:  
    NOTIFYICONDATA m_tnid;

2) 为对应的Frame 或Dialog 添加 WM_CREATE 消息函数,在对应实现函数中添加托盘生成代码

在对应的类声明文件中定义消息 ,并在OnCreate 函数中Return 之前添加代码

//对应的类声明文件中定义消息   
#define MYWM_NOTIFYICON WM_USER+1   

//OnCreate 函数中return 之前添加托盘生成代码   
m_tnid.cbSize=sizeof(NOTIFYICONDATA);   
m_tnid.hWnd=this->m_hWnd;   
m_tnid.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;   
m_tnid.uCallbackMessage=MYWM_NOTIFYICON;      
//用户定义的回调消息    
CString szToolTip;   
szToolTip=_T("托盘图标实例"); //鼠标在托盘上移动时显示文本   
_tcscpy(m_tnid.szTip, szToolTip);   
m_tnid.uID=IDR_MAINFRAME;   
HICON hIcon;   
hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);   
m_tnid.hIcon=hIcon;   
::Shell_NotifyIcon(NIM_ADD,&m_tnid);   
if(hIcon)::DestroyIcon(hIcon);

3) 编写消息处理函数

----为了处理图标回调消息,如鼠标左键双击、鼠标右键单击消息,我们重载WindowProc()函数。此外,我们还希望在主框架窗口最小化时图标不在任务栏空白区出现,在此函数中同时作相应处理。

别忘了编辑属于你自己的菜单,这里暂且使用 IDR_RIGHT_MENU 标志

LRESULT ***Frame/*or Dialog*/::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)      
{   
 switch(message){   
  case MYWM_NOTIFYICON:      
   //如果是用户定义的消息    
   if(lParam==WM_LBUTTONDBLCLK)   
   {   
    //鼠标双击时主窗口出现    
    AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOW);   
   }   
   else if(lParam==WM_RBUTTONDOWN){      
    //鼠标右键单击弹出菜单    
    CMenu menu;   
    menu.LoadMenu(IDR_RIGHT_MENU);      
    //载入事先定义的菜单    
    CMenu* pMenu=menu.GetSubMenu(0);   
    CPoint pos;   
    GetCursorPos(&pos);   
    pMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,pos.x,pos.y,AfxGetMainWnd());   
   }   
   break;   
  case WM_SYSCOMMAND:      
   //如果是系统消息    
        switch(wParam){  
          case SC_MINIMIZE:  
              //接收到最小化消息时主窗口隐藏    
              ShowWindow(SW_HIDE);   
              return 0;  
              break;  
          case SC_CLOSE :  
              ::Shell_NotifyIcon(NIM_DELETE,&m_nid); //关闭时删除系统托盘图标   
              break;  
        }   
   break;   
 }   
 return CFrameWnd/*or CDialog*/::WindowProc(message, wParam, lParam);  //其实就是调用父类的消息处理函数   
}

至此,托盘图标程序的常规功能我们均已实现。我们还可以通过Shell_NotifyIcon()函数的调用实现不同状态下图标的改变

反思:

关于隐藏任务栏功能查找资料,处理思路如下:

第一、创建对话框时必须将它作为某个不可见框架窗口的子窗口;

第二、这个不可见窗口的扩展式样必须设置 WS_EX_TOOLWINDOW;

第三、保证对话框的扩展式样没有设置 WS_EX_APPWINDOW;



因此,实现上比较灵活

1) 在创建 Dialog 类的时候,设置父窗口

一般我们这样写代码

CTest3Dlg dlg;

m_pMainWnd = &dlg;

dlg.DoModal();

现在为了隐藏,我们需要这么写

//STEP 1 获取 CWnd * pParent = ...... ,要求该 pParent 是不可见的,当然为了简单起见,可以令 pParent =CWnd::FindWindow("ProgMan",NULL)



CTest3Dlg dlg(pParent);

m_pMainWnd = &dlg;

dlg.DoModal();



2) 在Dialog 的OnInitDialog 函数里面添加如下代码

ModifyStyleEx(WS_EX_APPWINDOW,0);

当然,也可以注释掉对应对话框资源文件中 WS_EX_APPWINDOW 扩展式样的定义 EXSTYLE WS_EX_APPWINDOW





通过以上步骤,即可实现对dialog 窗口的任务栏隐藏

窗口扩展设置里隐藏任务栏

ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW);

要显示时就交换

ModifyStyleEx(WS_EX_TOOLWINDOW, WS_EX_APPWINDOW);

--------------------------分割线----------------------

参考自:http://blog.csdn.net/xian0617/article/details/5873248

http://www.open-open.com/lib/view/open1342167759343.html

原文链接: https://www.cnblogs.com/tohilary/archive/2012/08/05/2623967.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/57954

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 上午8:29
下一篇 2023年2月9日 上午8:29

相关推荐