我想写一个程序具有任务栏图标的功能,并且在鼠标右键单击时能弹出菜单,但是不知为何菜单无法弹出,请大家帮忙看看。 
我的具体操作如下: 1.我用VC建立了一个对话框程序命名为TEST 
2.添加NOTIFYICONDATA类型的成员变量 tnd。 
然后调用Shell_NotifyIcon创建了一个任务栏图标程序。将如下代码写在OnInitDialog()中       NOTIFYICONDATA tnd; 
      tnd.cbSize=sizeof(NOTIFYICONDATA); 
      tnd.hWnd=this->m_hWnd; 
      tnd.uID=IDI_TEST; 
      tnd.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP; 
      tnd.uCallbackMessage=WM_POPMENU; 
      tnd.hIcon=LoadIcon(AfxGetInstanceHandle(), 
      MAKEINTRESOURCE(IDI_TEST)); 
      strcpy(tnd.szTip,"提示信息"); 
      Shell_NotifyIcon(NIM_ADD,&tnd); 
3.手动添加了WM_POPMENU消息,创建消息响应函数OnPopmenu,创建IDI_TEST菜单资源 
4.在OnPopmenu函数中添加如下代码: 
if(wParam!=tnd.uID || (lParam!=WM_RBUTTONUP && lParam!=WM_LBUTTONDBLCLK)) 

return 0; 

    CMenu menu; 
if(!menu.LoadMenu(tnd.uID)) 

return 0; 
} CMenu* pSubMenu=menu.GetSubMenu(0); 
    
if(!pSubMenu) 

return 0; 
} if(lParam==WM_RBUTTONUP) 

::SetMenuDefaultItem(pSubMenu->m_hMenu,0,TRUE); 
CPoint mouse; 
GetCursorPos(&mouse); 
::SetForegroundWindow(tnd.hWnd); 
::TrackPopupMenu(pSubMenu->m_hMenu,0,mouse.x,mouse.y,0,tnd.hWnd,NULL); 
}

解决方案 »

  1.   

    在TrackPopupMenu上面设置断点,看看能否执行到。
      

  2.   

     楼主加的消息不能你那样响应
    #define WM_POPMENU WM_USER+1
    利用向导加一个XXXX::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
      switch(message)

     case WM_POPMENU : 
        if(lParam==WM_LBUTTONDBLCLK){ ...}
        else if(lParam==WM_RBUTTONDOWN){...}
         else if(){}
        ...
       break;}
    return CDialog::WindowProc(message, wParam, lParam);
    }
      

  3.   

    LRESULT CMainFrame::OnPopmenu(WPARAM wParam, LPARAM lParam)
    {
        //在系统托盘上点击右键。
        if (LOWORD(lParam) == WM_RBUTTONUP)
        {
            POINT pt;
            GetCursorPos(&pt);
            //在系统托盘中的弹出菜单。
            GetMenu()->GetSubMenu(0)->TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON, pt.x, pt.y, this);
        }
        return 0;
    }
      

  4.   

    你得在主窗体的窗口过程中添加代码:LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
    {
    switch(message)
    {
    case WM_POPMENU : //如果是用户定义的消息 
    if(lParam == WM_LBUTTONDOWN)
    {
    ShowWnd();//显示窗口
    } else if(lParam == WM_RBUTTONDOWN) //鼠标右键单击弹出选单 
    {
    CMenu menu;
    menu.LoadMenu(IDR_TRAY_MENU); //载入事先定义的选单
                    CMenu *pMenu = menu.GetSubMenu(0);
    if(pMenu != NULL)
    {
    CPoint pos;
    GetCursorPos(&pos);
    SetForegroundWindow();
    pMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, pos.x, pos.y, this);
    } PostMessage(WM_NULL, 0, 0); //这样可能除去当失去焦点时,菜单不取消的问题
    }
    return 0;
    break;

    case WM_SYSCOMMAND: //如果是系统消息
    if(wParam == SC_MINIMIZE) //接收到最小化消息时主窗口隐藏
    {
    ShowWnd(false);//隐藏窗口
    return 0;
    }
    break; }
    return CFrameWnd::WindowProc(message, wParam, lParam);
    }
      

  5.   

    改成相应 RBUTTONDOWN的事件 看看...
      

  6.   

    大家说的问题我都注意到了。不过我期待的菜单还是没有弹出来。
    我这里有个疑问。就是NOTIFYICONDATA 这个结构体该定义在那个函数比较好?我发现放在OnInitDialog 和 OnPaint中都有效。
      

  7.   

    基于对话框的话,你把NOTIFYICONDATA放到OnInitDialog中好点。
      

  8.   

    恩,把图标响应消息里面的
    lParam判定改为WM_LBUTTONDBLCLK和WM_RBUTTONDOWN,双击左键或者单击右键,试试看。
      

  9.   

    问楼上:
    CMainFrame哪里来?
      

  10.   

    那只是他的程序中 添加到 MainFrame下了
    你在自己的对话框下 重载虚函数 WindowProc
    我复制我的给你看 我的就是对话框下做的
    LRESULT CMainDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
    { // TODO: Add your specialized code here and/or call the base class switch(message){

    case MYWM_NOTIFYICON:       
    //如果是用户定义的消息
    if(lParam==WM_LBUTTONDBLCLK)
    {  //鼠标双击时主窗口出现
    AfxGetApp()->m_pMainWnd->
    ShowWindow(SW_SHOW);
    }
    else if(lParam==WM_RBUTTONDOWN)

    //鼠标右键单击弹出菜单
       CMenu menu;
    menu.LoadMenu(IDM_RICHMENU); 
    //载入事先定义的菜单
    CMenu* pMenu=menu.GetSubMenu(0);
    CPoint pos;
    GetCursorPos(&pos);
    pMenu->TrackPopupMenu
    (TPM_LEFTALIGN|TPM_RIGHTBUTTON,
    pos.x,pos.y,AfxGetMainWnd());
    }
    break;
    case WM_SYSCOMMAND:     
    //如果是系统消息
    if(wParam==SC_CLOSE){  //接收到关闭消息时主窗口隐藏
    AfxGetApp()->m_pMainWnd->
    ShowWindow(SW_HIDE);
    return 0;
    }
    break;
    }

    return CDialog::WindowProc(message, wParam, lParam);
    }
      

  11.   

    很好很强大,我就没重写了,直接NOTIFYICONDATA.uCallbackMessage = WM_MYTASKICON
    ON_MESSAGE(WM_TASKICON,OnTaskIcon)
    其他的响应放到OnTaskIcon()里面。嘿嘿,偶素懒人哈。
      

  12.   

    感谢讨论。我明白你的意思,不过我所要实现的是当鼠标在托盘图标上按下鼠标获得菜单的效果。我看过MSDN关于NOTIFYICONDATA结构体的介绍。
    大家注意看这个参数的解释
    uCallbackMessage 
    Application-defined message identifier. The system uses this identifier to send notifications to the window identified in hWnd. These notifications are sent when a mouse event occurs in the bounding rectangle of the icon, or when the icon is selected or activated with the keyboard. The wParam parameter of the message contains the identifier of the taskbar icon in which the event occurred. The lParam parameter holds the mouse or keyboard message associated with the event. For example, when the pointer moves over a taskbar icon, lParam is set to WM_MOUSEMOVE. See the Taskbar guide chapter for further discussion.MSDN的意思是lParam参数会捕获到关联的鼠标键盘消息wParam会获取到ICON的ID号。所以我我将自定义的消息WM_POPMENU付给uCallackMessage参数,并作了消息映射。响应函数是OnPopmenu(WPARAM wParam,LPARAM lParam)
    将俩个参数传了进去。接下来的代码如帖子。可是不知哪里除了BUG,菜单就是无法显示~~~
      

  13.   

    诶1.
    上面说了,OnInitDialog()中设置NOTIFYICONDATA:
    其中
    TaskIcon.cbSize = sizeof(TaskIcon);
    TaskIcon.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    TaskIcon.hWnd = this->GetSafeHwnd();
    TaskIcon.uFlags = 0x7; //NIF_MESSAGE|NIF_ICON|NIF_TIP;
    lstrcpy(TaskIcon.szTip,_T("、、、、"));
    TaskIcon.uCallbackMessage = WM_TASKICON;//设置出发图标响应消息
    Shell_NotifyIcon(NIM_ADD,&TaskIcon);//这里设置图标咯2.
    BEGIN_MESSAGE_MAP(CTest1Dlg, CDialog)
    //{{AFX_MSG_MAP(CTest1Dlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
    ON_MESSAGE(WM_TASKICON,OnTaskIcon)//这里设置对图标响应消息的函数
    END_MESSAGE_MAP()3.写响应函数吧
    void CTest1Dlg::OnTaskIcon(WPARAM wParam,LPARAM lParam)
    {
    POINT point;
    GetCursorPos(&point);
    CMenu *pContextMenu ; if(lParam == WM_LBUTTONDBLCLK)
    ShowWindow(SW_SHOWNORMAL);
    else if(lParam == WM_RBUTTONDOWN)
    {
    CMenu menu;
    menu.LoadMenu(IDR_QUIT);//这里放你自己希望弹出的菜单资源哈
    pContextMenu = menu.GetSubMenu(0);
    pContextMenu->TrackPopupMenu(TPM_LEFTBUTTON,point.x,point.y,this);


    } return;
    }
    that's all.