CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  基础类

怎样实现非对话框应用程序最小化成为托盘图标,请先告诉我,有没有这个可能?

楼主rockett(用户中文昵称)2001-12-05 16:44:52 在 VC/MFC / 基础类 提问

 
  如果可以的话,应该怎样做,给一些思路也好。  
  问题点数:50、回复次数:6Top

1 楼TigerHu(愁煞人)回复于 2001-12-05 16:47:18 得分 0

可以!  
  http://www.csdn.net/expert/topic/323/323557.shtmTop

2 楼rockett(用户中文昵称)回复于 2001-12-05 16:48:52 得分 0

为什么很多资料在讲解托盘的例子时,都是要建立一个非文档类的应用程序?  
   
  难道基于文档类的就不能做成托盘的形式吗?金山詞霸算不算基于文档类的程序?  
   
  请指教。Top

3 楼rockett(用户中文昵称)回复于 2001-12-05 17:00:26 得分 0

如何知道应用程序最小化了?Top

4 楼TigerHu(愁煞人)回复于 2001-12-05 17:04:18 得分 50

void   CMainFrame::OnSize(UINT   nType,   int   cx,   int   cy)    
  {  
  CFrameWnd::OnSize(nType,   cx,   cy);  
   
  //   TODO:   Add   your   message   handler   code   here  
   
           
  if(nType   ==   SIZE_MINIMIZED)     //   程序最小化  
  {  
  //   this->ShowWindow(SW_HIDE);  
  }  
  }  
   
  Top

5 楼pinel()回复于 2001-12-05 17:07:27 得分 0

VC知识库     www.vckbase.com      
   
  --------------------------------------------------------------------------------  
     
  VC++6.0中实现将应用程序的图标加入到Windows的系统托盘中      
  西安二炮工程学院   俞俊军   张   毅      
   
  --------------------------------------------------------------------------------  
     
  摘要    
      本文对如何将应用程序的图标加入到Windows的系统托盘中做了较为详细的介绍,  
      然后给出了一个C++类以方便的实现该功能,并在VC++6.0中给出了一个应用程序  
      实例来体现其具体实现过程。同时该应用程序实例还讲解了如何在托盘中实现动  
      画图标以及在程序中关闭计算机的技术。    
   
      关键词:系统托盘   动画图标    
   
      Windows98桌面的系统托盘位于任务栏的右侧,即Windows98桌面的右下方。它常  
      用来显示一些系统的状态。如:系统时间,音量控制以及其它的一些图标(依个  
      人机器安装的软件而不定),如下图为笔者的Windows98系统托盘。(图略)    
   
      常常能见到一些优秀的软件在运行后会将其应用程序图标加入到系统托盘中,如  
      金山词霸。如果能将自己编写的应用程序的图标也加入到系统托盘中,将会使你  
      的程序显得很有专业水准。    
   
      其实这并不困难,与系统托盘通信的函数只有一个:    
   
    Shell_NotifyIcon   (UINT   message,   NOTIFYICONDATA   &m_nid);    
   
      首先看一下该函数的两个参数。    
      第一个参数message可以取以下值:    
   
  NIM_ADD           向托盘中加入一个图标;    
  NIM_MODIFY       修改托盘中的图标  
  NIM_DELETE       从托盘中删除一个图标  
   
      第二个参数m_nid是NOTIFYICONDATA结构的一个引用。该结构的原型如下:    
  typedef   struct   _NOTIFYICONDATA    
    {    
    DWORD   cbSize;//   结构的大小,必须在程序中给出    
    HWND   hWnd;  
    //是你程序中将要接收托盘消息的窗口句柄    
    UINT   uID;    
    //   应用程序中定义的托盘图标ID,此参数用作标识    
    UINT   uFlags;  
  //设置属性,低三位有意义,0--7,如下:    
  //第一位//#define   NIF_MESSAGE   0x1    
  //   uCallbackMessage参数有效    
   
  //第二位//#define   NIF_ICON     0x2   //   hIcon参数有效    
  //第三位//#define   NIF_TIP     0x4   //   szTip参数有效    
                       
    UINT   uCallbackMessage;      
  //   自定义的消息ID值,一定不要与以有的消息ID相重。      
    HICON   hIcon;    
  //显示在系统托盘上的Icon的句柄,可以为系统的   IDI_WINLOGO等  
    CHAR   szTip[64];   //   用于图标显示的提示字符串  
  }   NOTIFYICONDATA;  
   
      为了接收到来自托盘的通知消息你可以将uCallbackMessage设定为你所定义的消息  
      ID值,同时设定NIF_MESSAGE标志。这样当用户在你的托盘图标上移动或按下鼠标  
      时,Windows将发出消息:该消息的   messageID是你在uCallbackMessage中定义的  
      值;wParam是你定义的uID值;而lParam是鼠标事件(如WM_LBUTTONDOWN),这样你  
      的应用程序就能响应该事件了。    
      因此,为了将自己的应用程序加入到系统托盘中,首先得建立一处理托盘通知消息  
      的窗口对象,然后将窗口对象与你自己的托盘通知消息联系起来并建立相应的托盘  
      通知消息映射机制,以便你的窗口对象能处理相应的事件。    
   
      可以看到结构体NOTIFYICONDATA中,其成员变量hWnd,uID,uFlags均用于在窗口对  
      象与你自己的托盘通知消息之间建立联系,而成员变量uCallbackMessage则必须是  
      对应于你的窗口对象的托盘通知消息ID值。    
   
      于是要完成的工作有:    
   
      (1)建立一处理托盘通知消息的窗口对象;    
      (2)建立一结构体NOTIFYICONDATA变量,并给变量的相应域赋值以在托盘通知消  
                息与窗口对象之间建立联系;    
      (3)建立相应的托盘通知消息映射机制;    
      (4)调用Shell_NotifyIcon函数以在系统托盘中加入、修改或删除图标;    
      (5)当然别忘了在你的窗口对象中编写相应的事件响应函数。    
   
      因此,可以编写一C++类来实现以上功能以简化编程同时提高代码的可重用性。以  
      下为该类代码:    
   
  class   CTrayIcon   :   public   CCmdTarget   {  
  protected:  
      DECLARE_DYNAMIC(CTrayIcon)  
      NOTIFYICONDATA   m_nid;          
    //   Shell_NotifyIcon   函数中的结构参数  
   
  public:  
      CTrayIcon(UINT   uID);  
      ~CTrayIcon();  
   
      //   通过调用该成员函数来接收托盘通知消息  
      void   SetNotificationWnd(CWnd*   pNotifyWnd,  
      UINT   uCbMsg);  
   
      //   SetIcon   函数用来在系统托盘中加入、改变及删除图标。  
      //要删除图标这样调用:SetIcon(0)  
      BOOL   SetIcon(UINT   uID);    
      BOOL   SetIcon(HICON   hicon,   LPCSTR   lpTip);  
      BOOL   SetIcon(LPCTSTR   lpResName,   LPCSTR   lpTip)  
      {    
            return   SetIcon(lpResName   ?    
            AfxGetApp()->LoadIcon(lpResName):NULL,lpTip);  
      }  
       
      BOOL   SetStandardIcon(LPCTSTR   lpszIconName,LPCSTR   lpTip)  
      {  
            return   SetIcon(::LoadIcon(NULL,lpszIconName),lpTip);  
      }  
   
      virtual   LRESULT   OnTrayNotification(WPARAM   uID,   LPARAM   lEvent);  
  };  
   
  CTrayIcon::CTrayIcon(UINT   uID)  
  {  
      //初始化NOTIFYICONDATA结构变量  
      memset(&m_nid,   0   ,   sizeof(m_nid));  
      m_nid.cbSize   =   sizeof(m_nid);  
      m_nid.uID   =   uID;    
      AfxLoadString(uID,   m_nid.szTip,   sizeof  
      (m_nid.szTip));  
  }  
   
  CTrayIcon::~CTrayIcon()  
  {  
      SetIcon(0);   //   从系统托盘中删除图标  
  }  
   
  //   设定通知窗口,该窗口必须已被创建  
  void   CTrayIcon::SetNotificationWnd(CWnd*   pNotifyWnd,   UINT   uCbMsg)  
  {  
          ASSERT(pNotifyWnd==NULL   ||   ::IsWindow(pNotifyWnd->GetSafeHwnd()));  
   
          m_nid.hWnd   =   pNotifyWnd->GetSafeHwnd();  
   
  ASSERT(uCbMsg==0   ||   uCbMsg>=WM_USER);  
  m_nid.uCallbackMessage   =   uCbMsg;  
  }  
   
  BOOL   CTrayIcon::SetIcon(UINT   uID)  
  {    
      HICON   hicon=NULL;  
      if   (uID)   {  
        AfxLoadString(uID,   m_nid.szTip,   sizeof(m_nid.szTip));  
        hicon   =   AfxGetApp()->LoadIcon(uID);  
      }  
      return   SetIcon(hicon,   NULL);  
  }  
   
  //////////////////  
  //  
  BOOL   CTrayIcon::SetIcon(HICON   hicon,   LPCSTR   lpTip)    
  {  
      UINT   msg;  
      m_nid.uFlags   =   0;  
   
      //   设定图标  
      if   (hicon)   {  
        //   判断是要在系统托盘中增加还是要删除图标  
        msg   =   m_nid.hIcon   ?   NIM_MODIFY   :   NIM_ADD;  
        m_nid.hIcon   =   hicon;  
        m_nid.uFlags   |=   NIF_ICON;  
      }   else   {   //   删除图标  
        if   (m_nid.hIcon==NULL)  
            return   TRUE;       //已被删除  
        msg   =   NIM_DELETE;  
      }  
      if   (lpTip)  
        strncpy(m_nid.szTip,   lpTip,   sizeof(m_nid.szTip));  
      if   (m_nid.szTip[0])  
        m_nid.uFlags   |=   NIF_TIP;  
   
      if   (m_nid.uCallbackMessage   &&   m_nid.hWnd)  
        m_nid.uFlags   |=   NIF_MESSAGE;  
   
      BOOL   bRet   =   Shell_NotifyIcon(msg,   &m_nid);  
      if   (msg==NIM_DELETE   ||   !bRet)  
        m_nid.hIcon   =   NULL;    
      return   bRet;  
  }  
   
  //   缺省事件处理程序,该程序处理鼠标右击及双击事件。  
  LRESULT   CTrayIcon::OnTrayNotification(WPARAM   wID,  
    LPARAM   lEvent)  
  {  
      if   (wID!=m_nid.uID   ||  
        (lEvent!=WM_RBUTTONUP   &&   lEvent!=WM_LBUTTONDBLCLK))  
        return   0;  
   
      //   使用与托盘图标拥有同样ID号的菜单作为右键弹出菜单    
      //   并将菜单上的第一项作为缺省命令使用,  
      //   缺省命令在WM_LBUTTONDBLCLK事件发生时被击发  
      //    
      CMenu   menu;  
      if   (!menu.LoadMenu(m_nid.uID))  
        return   0;  
      CMenu*   pSubMenu   =   menu.GetSubMenu(0);  
      if   (!pSubMenu)    
        return   0;  
   
      if   (lEvent==WM_RBUTTONUP)   {  
   
        //使菜单第一项为缺省项   (表现为粗体)  
        ::SetMenuDefaultItem(pSubMenu->m_hMenu,   0,   TRUE);  
   
        //   在鼠标的当前位置弹出菜单。  
        CPoint   mouse;  
        GetCursorPos(&mouse);  
        ::SetForegroundWindow(m_nid.hWnd);    
        ::TrackPopupMenu(pSubMenu->m_hMenu,  
  0,  
  mouse.x,  
  mouse.y,  
  0,  
  m_nid.hWnd,  
  NULL);  
   
      }   else   //   双击事件:   执行菜单第一项  
        ::SendMessage(m_nid.hWnd,   WM_COMMAND,   pSubMenu->  
        GetMenuItemID(0),   0);  
   
      return   1;   //   表示事件已被处理  
  }  
   
      以下以在VC++6.0中具体实现的程序为例。该程序将拥有以下功能:程序被执行  
      后,首先显示一对话框表示程序开始执行,然后该对话框消失。接着程序图标  
      被加入到系统托盘中,可以看到,该图标将是一动画图标。当鼠标在该系统托  
      盘上右击时,将弹出一菜单。如图所示(略)。其第一项为缺省项命令,单击  
      将显示应用程序。为简化编程,该应用程序只是显示一应用程序主窗口。而单击  
      菜单第二项将关闭机器,单击菜单第三项将结束本程序。当并且当用户双击时,  
      CTrayIcon将执行菜单上的第一项:显示服务程序,这将击活(显示)TrayDemo  
      (正常情况下,它是隐藏的)。而要终止TrayDemo,你得选择结束本程序。当你  
      执行File   Exit或关掉TrayDemo主窗口时,TrayDemo并没有真正的关掉,它只不过  
      隐藏起来了而已。TrayDemo   重载了Cmainframe::OnClose函数以执行该项功能。    
      首先在VC++6.0中生成用应用程序向导生成一单文档工程TrayDemo,然后在工程中  
      加入以上的CTrayIcon类。    
   
      要使用CTrayIcon类,你首先得实例化一个CTrayIcon类对象,TrayDemo在视图中  
      完成此项工作。以下是对应代码:    
   
    class   CTrayDemoView   :   public   CView   {  
  protected:   CTrayIcon   m_trayIcon;    
                      //   my   tray   icon  
                        .  
                        .  
                        .  
  };  
   
      当你实例化一个CTrayIcon类对象之后,你必须分配给其一个ID号。该ID号是此图  
      标在其生命周期内使用的唯一一个ID号,即使在以后你改变了实际显示的图标。此  
      ID号是当鼠标事件发生时你获得的ID。它可以不必是图标的资源ID;在TrayDemo  
      中,其值是IDR_TRAYICON,由CTrayDemoView构造函数所初始化。    
    CTrayDemoView::CTrayDemoView()   :  
    m_trayIcon(IDR_TRAYICON){  
                        .  
                        .  
                        .  
  }  
   
  要增加图标,可调用SetIcon重载函数之一  
    m_trayIcon.SetIcon(IDI_MYICON);   //参数为资源ID  
    m_trayIcon.SetIcon("myicon");   //参数为资源名  
    m_trayIcon.SetIcon(hicon);   //参数为HICON句柄    
    m_trayIcon.SetStandardIcon(IDI_WINLOGO);  
    //加入系统图标  
   
      除了SetIcon(UINT   uID)函数需要一个同样拥有uID号的字符串资源作为提示字符串  
      以外,所有这些函数都有一个可选的指向提示字符串的LPCSTR参数。例如,在  
      TRAYTEST中有以下行:    
  //   (In   TrayDemoView.cpp)  
  m_trayIcon.SetIcon(IDI_RED);  
   
      该语句在增加图标的同时同样设定了提示字符串,因为TrayDemo有一个同样ID的字  
      符串:如果你想改变图标,只需再次调用其中的一个SetIcon函数,只不过需要不  
      同的ID或HICON。CTrayIcon类知道响应NIM_MODIFY消息而不是NIM_ADD消息。同样  
      的函数甚至可以去掉图标:    
    m_trayIcon.SetIcon(0);//removeicon  
   
      CtrayIcon类会将其解释为NIM_DELETE事件。这么多的代码和标志只用一个简单的  
      重载函数就予以完成,这是C++的伟大之处。    
      如果要显示动画图标,只需设置一定时器,然后在定时器的响应事件中调用  
      SetIcon成员函数就可以了。如:    
   
  int   CTrayDemoView::OnCreate(LPCREATESTRUCT   lpCreateStruct)    
  {  
  m_timerID   =   this->SetTimer(99,200,NULL);  
  …  
  }  
   
  void   CTrayDemoView::OnTimer(UINT   nIDEvent)    
  {  
  uChangeIcon++;  
  if(uChangeIcon-IDI_RED>2)  
  uChangeIcon=IDI_RED;  
  m_trayIcon.SetIcon(uChangeIcon);  
  CView::OnTimer(nIDEvent);  
  }  
   
      在示例程序中,有3个图标,其ID为IDI_RED,IDI_YELLO,IDI_GREEN,且其ID值是相  
      连的,因而UINT型变量uChangeIcon用来依次轮换三个图标。这样程序执行以后,你  
      将会看到红、黄、绿三个交通指示灯依次闪烁。    
      那么怎样处理托盘通知呢?    
   
      要处理托盘通知,需要在你设定图标之前调用CTrayIcon::SetNotificationWnd函  
      数,当然你必须已经创建了窗口。最适当的地方是在OnCreate函数中,在TrayDemo  
      中也是这样做的。用ClassWizard在CtrayDemoView类中加入WM_CREATE消息响应函  
      数OnCreate(),并加入以下代码:    
   
    //   Private   message   used   for   tray   notifications  
  #define   WM_MY_TRAY_NOTIFICATION   WM_USER+0  
  int   CTrayDemoView::OnCreate(LPCREATESTRUCT   lpCreateStruct)  
                          .  
                          .  
                          .  
    m_trayIcon.SetNotificationWnd(this,WM_MY_TRAY_NOTIFICATION);  
    m_trayIcon.SetIcon(IDI_RED);    
    return   0;  
  }  
   
      然后进行消息注册(REGISTER),一旦注册以后,你就可以用正常的消息映射方式  
      处理托盘通知。    
  BEGIN_MESSAGE_MAP(CMainFrame,   CFrameWnd)    
  ON_MESSAGE(WM_MY_TRAY_NOTIFICATION,OnTrayNotification)  
    //   (or   ON_REGISTERED_MESSAGE)  
  END_MESSAGE_MAP()  
   
  当然不要忘了在TrayDemoView.h中加入以下语句:  
  afx_msg   LRESULT   OnTrayNotification(WPARAM   wp,   LPARAM   lp);  
   
      当你的处理程序得到在托盘图标上的鼠标事件的控制以后,WPARAM参数是你在创建  
      CTrayIcon类时定义的ID;LPARAM是鼠标事件(如,WM_LBUTTONDOWN)。当捕获到  
      通知后你可以做任何你想做的事情;记得最后要调用  
      CTrayIcon::OnTrayNotification函数以完成一些缺省的处理。该虚函数完成前面  
      所提到的一些缸省的UI行为。特别的,它处理WM_LBUTTONDBLCLK和WM-RBUTTONUP事  
      件。CTrayIcon类寻找与图标拥有同样ID的菜单(如,IDR_TRAYICON)。如果拥有  
      该ID的菜单存在,CTrayIcon类将在用户右击图标的时候显示此菜单;而当用户双  
      击时,CTrayIcon将执行菜单上的第一个命令。    
   
  LRESULT   CTrayDemoView::OnTrayNotification(WPARAM   wp,   LPARAM   lp)  
  {                      
        return   m_trayIcon.OnTrayNotification(wp,   lp);  
  }  
   
      只有两件事需要进一步解释。在显示菜单之前,CTrayIcon类使得第一项为缸省项,  
      因此它看起来是大写的。但怎样使得一个菜单项大写呢?使用函数    
      GSetMenuDefaultItem。    
    //   Make   first   menu   item   the   default   (bold   font)  
  ::SetMenuDefaultItem(pSubMenu->m_hMenu,   0,   TRUE);  
   
      这里的0便指定了第一个菜单项,TRUE表示通过位置而不是ID来确定菜单项。    
      对CTrayIcon::OnTrayNotification,我们关心的第二项是为了显示相关菜单,它干  
      了些什么?    
   
    ::SetForegroundWindow(m_nid.hWnd);    
    ::TrackPopupMenu(pSubMenu->m_hMenu,   ...);  
   
      为了使TrackPopupMenu函数在托盘环境中工作正常,你必须首先在拥有该弹出菜单  
      的窗口中调用SetForegroundWindow函数。否则,当用户按下Esc键或在菜单以外单  
      击鼠标时该菜单将不会消失。正如你看到的那样,CTrayIcon类使得托盘图标的编  
      程很简单。为了使托盘菜单生效,在TrayDemo中所做的只是实现一个通知程序,在  
      该程序中调用了CTrayIcon::OnTrayNotification,对了别忘了还要提供一个与  
      CTrayIcon类拥有同样ID的菜单。TrayDemo程序中是在菜单编辑器内加入一ID为  
      IDR_TRAYICON的如下菜单:    
      然后,用ClassWizard在视图类中分别为三个菜单命令加入如下的响应函数:    
   
  void   CTrayDemoView::OnDisplayProgram()    
  {  
  CWnd*   pWnd;  
  pWnd=AfxGetApp()->m_pMainWnd;  
  pWnd->ShowWindow(SW_NORMAL);    
      pWnd->SetForegroundWindow();  
  }  
   
  void   CTrayDemoView::OnCloseProgram()    
  {  
  m_bShutdown   =   TRUE;       //   really   exit  
  CWnd*   pWnd;  
  pWnd=AfxGetApp()->m_pMainWnd;  
      pWnd->SendMessage(WM_CLOSE);    
  }  
   
  void   CTrayDemoView::OnShutoff()    
  {  
  ExitWindowsEx(EWX_SHUTDOWN,0);  
  }  
   
      其中,在OnShutoff函数中,ExitWindowsEx(EWX_SHUTDOWN,0)用来关闭计算机。限  
      于篇幅,这里不作详细介绍,读者可以查看MSDN来获得更详细的资料。    
      最后,还要重载Cmainframe::OnClose函数如下:    
   
  void   CMainFrame::OnClose()    
  {  
  CTrayDemoView   *pView   =    
      (CTrayDemoView   *)GetActiveView();  
  if   (pView->m_bShutdown)  
        CFrameWnd::OnClose();  
      else  
        ShowWindow(SW_HIDE);  
  }  
   
      提醒一点,为使框架程序识别视图类,还要在MainFrm.cpp中加入如下两句:    
  #include   "TrayDemoDoc.h"  
  #include   "TrayDemoView.h"  
   
      如果有兴趣,还可以对将本程序继续扩充,使之可以监视系统的状态:当鼠标和键  
      盘在超过一设定的时间后,仍没有动作,则程序将自动执行关机命令。    
      以上程序在Windows98,VC++6.0中调试通过。  
   
     
     
     
     
     
  Top

6 楼freeclick(自由点击)回复于 2001-12-05 17:12:35 得分 0

当然可以,加托盘和程序是否有界面完全没有关系,就是一个什么也没有的后台程序也可以放托盘的。关于放置托盘想必你已经有了例子。GOOD   LUCKTop

相关问题

  • 应用程序最小化
  • 使对话框最小化渐变到托盘区。
  • 怎样把一个对话框应用程序放到托盘中去。
  • 如何将应用程序最小化至系统托盘(任务栏最右边)?
  • 求教,删除文件的问题以及将应用程序最小化到托盘的问题
  • 如何让基于对话框的应用程序一开始不可见,然后如何再显示?我是做托盘
  • 对话框最小化的问题
  • 如何编程最小化应用程序?
  • 如何实现是桌面所有应用程序最小化?
  • 如何才能使应用程序不会被最小化?

关键词

  • c++
  • vc++
  • 函数
  • 应用程序
  • 系统
  • 消息
  • 鼠标
  • 托盘
  • 图标
  • ctrayicon

得分解答快速导航

  • 帖主:rockett
  • TigerHu

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo