一个完整托盘程序的实现

先让托盘"托"出来吧,关键在于一个NOTIFYICONDATA结构体,我的做法是建立一个SDI或Dialog程序,以SDI为例:

A,在frame.h中声明一个全局的NOTIFYICONDATA  ntf;

B,在OnCreate中,实例化ntf的各个数据成员:  -------------------------------------------唉,CSDN这个编辑器没做好:)ntf.cbSize=sizeof NOTIFYICONDATA;
 ntf.hWnd=this->m_hWnd;
 ntf.uID=IDR_MAINFRAME;
 ntf.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
 strcpy(ntf.szTip,"femalelover is a good man");
 ntf.uCallbackMessage=WM_MESSAGE;
 ntf.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP;                                         OK,下面就是托盘产生了.   Shell_NotifyIcon(NIM_ADD,&ntf);

C,在托盘程序中,人们一般喜欢去PreCreateWindow中给窗口加上WS_EX_TOOLWINDOW属性来使窗口在任务栏不可见. 我发现,这大可不必,因为这样一来会改变窗口的样子,变得很难看. 这就是困扰我的一个地方.我的解决办法是不管它 ^_^.   因为人性化的操作应该是程序运行时,窗口显示在桌面上, 这时,任务栏上会有程序图标,(如果要使窗口显示在桌面上而任务栏中没有图标,则好像只能使用WS_EX_TOOLWINDOW属性). 当最小化时,则显示托盘. 达到目的的做法相当简单:在OnSize中用这一句:   if (SIZE_MINIMIZED==nType) ShowWindow(SW_HIDE); 就OK了.

D,上面,托盘的样子是出来了. 接下来就是给托盘添加左右键处理, 在B步就,ntf.uCallbackMessage=WM_MESSAGE;
这里的WM_MESSAGE是一个自定义消息,当鼠标移动到托盘上时,系统会自动发送这个消息,俺要做的就是在自定义处理函数时判断是左键还是右键按下了,以及鼠标事件发生时干点什么. 唉,有的菜鸟朋友可能不知道怎么定义消息,这里也说一下(我自己也是菜鸟嘛,呵):--------------------------------------------------------------------------------------------------------  先定义: #define WM_MESSAGE   (WM_USER+101)                                                                                                     -----   然后去.H中添加为成员函数:     afx_msg LRESULT  OnMsage(WPARAM wparam,LPARAM lparam);                 --------再到.CPP中添加消息映射:      ON_MESSAGE(WM_MESSAGE,OnMsage)       花架子就是这样,接下来真正定义啦,说起来麻烦,直接贴一段自产的代码算了:                                               

LRESULT  CMainFrame::OnMsage(WPARAM wparam,LPARAM lparam)
{

 switch(lparam)
 {
 case WM_LBUTTONDOWN:
  {
   if(wparam==IDR_MAINFRAME)
   {
    POINT pt;
    GetCursorPos(&pt);
    AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOWNORMAL);
    SetForegroundWindow();
    break;
   }
  
  }
 case WM_RBUTTONUP:
  {
   POINT point;
   HMENU hMenu, hSubMenu;
   GetCursorPos(&point); //鼠标位置
   hMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MENU1)); // 加载菜单
   hSubMenu = GetSubMenu(hMenu, 0);//得到子菜单(因为弹出式菜单是子菜单)
   SetMenuDefaultItem(hSubMenu, -1, FALSE);//设置缺省菜单项,-1为无缺省项
   SetForegroundWindow(); // 激活窗口并置前
  
   //显示快捷菜单,并跟踪其选项,返回值为菜单选项的id,必须设置 TPM_RETURNCMD
   CMainFrame::m_bAutoMenuEnable=FALSE;     //这句就是用来使用菜单项有效的.
  
   int n = TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_LEFTALIGN|TPM_RETURNCMD, point.x, point.y, 0, m_hWnd, NULL);
  
   switch(n)            //上面返回的n值,当没有选中任何菜单项时,为0,否则,为被选中项的ID.
   {
   case IDM_EXIT:                                                 //只处理这一项啦,其他类似.
    SendMessage(WM_CLOSE,0,0);

   }
  }
 }
 return 0;
}

E,还应该在程序退出时删除图标,这就是我为什么要把前面的NOTIFYICONDATA设为全局的了.可在 ~Frame析构函数中使用这句:Shell_NotifyIcon(NIM_DELETE,&ntf);  则删除了图标.

就这样了,回过头来看,真是简单哪.可当初,因为ShowWindow(SW_SHOW)没有用SW_SHOWNORMAL,就让我晕了半天,左键点托盘,窗口不能浮上来.还以为哪里出了问题,粗心大意真是要不得呀. 呵呵.

你可能感兴趣的:(一个完整托盘程序的实现)