系统托盘的问题

今天要求做个东东,有让程序最小化到系统托盘的部分,写下如下代码,先建立消息映射
ON_MESSAGE(WM_ICONNOTIFY,OnMinToShellNotifyIcon)
然后写下消息函数
LRESULT    OnMinToShellNotifyIcon(WPARAM wParam, LPARAM lParam)    // 产生托盘图标消息
{
    UINT uMsg = (UINT)lParam;
    CMenu menu;   
    SetMenu(&menu);
    UINT uCmd;
    switch (uMsg)
    {
        case WM_LBUTTONDOWN:           
            DeleteShellNotifyIcon(0);    //    清除托盘图标
            SetForegroundWindow();        //    让程序前置到窗口
            ShowWindow(SW_SHOWNORMAL);
            break;
        case WM_RBUTTONUP:
            //-----------弹出菜单---------------------------------
            menu.CreatePopupMenu();
            menu.AppendMenu(MF_STRING, 1100+1, _T("还原")); //1100是自己定义的,表示菜单上的项目ID,
//最好用define定义成特定的字串,如#define MY_MENU_ITEM 1100;并且要按照MS的要求定义大小。
            menu.AppendMenu(MF_STRING, 1100+2, _T("退出"));
            POINT point;
            GetCursorPos(&point);
            uCmd = menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, this, NULL);
            switch(uCmd)    //    处理菜单消息
            {
            case 1100 + 1 :
                //AfxMessageBox("ok");
                DeleteShellNotifyIcon(0);    //    清除托盘图标
                ShowWindow(SW_SHOWNORMAL); 
                SetForegroundWindow();        //    让程序前置到窗口
                break;
            case 1100 + 2 :
                PostMessage(WM_CLOSE, 0, 0); // 退出程序
                break;
            default:
                break;
            }
        default:
              break;
    }
    return 0;
}
运行,试一下鼠标消息,正常执行,可是当鼠标在其他地方点击时(并不点击弹出菜单的还原或退出),发现菜单并不消失,除非再点击一下原来程序的界面.奇怪了,并且有时点击后菜单出来,但又马上消失,好像要加点什么代码才能让其正常,看看MSDN上有什么说明,找了找有个函数 BOOL CMenu:: DestroyMenu( );添加到default:下(心里感觉可能不行),果真如此。费了半天劲,这可不好搞。消失的问题不好解决,上microsoft看看,都是英文,硬着头皮看下去,找到Q135788:Menus for Notification Icons Do Not Work Correctly,原来“When you display a context menu for a notification icon (see Shell_NotifyIcon), clicking anywhere besides the menu or the window that created the menu (if it is visible) doesn't cause the menu to disappear. When this behavior is corrected, the second time this menu is displayed, it displays and then immediately disappears. ”接下来说明了解决办法,就是说在调用TrackPopupMenu前必须把当前程序作成顶层窗口,用SetForegroundWindow();同时防止点击右键时菜单出现又马上消失的问题,必须送一个空消息PostMessage(WM_NULL, 0, 0);好办得很。把上面代码改一下:
LRESULT    OnTaskbar(WPARAM wParam, LPARAM lParam)    // 产生托盘图标消息
{
    UINT uMsg = (UINT)lParam;
    CMenu menu;   
    SetMenu(&menu);
    UINT uCmd;
    switch (uMsg)
    {
        case WM_LBUTTONDOWN:           
            DeleteShellNotifyIcon(0);    //    清除托盘图标
            SetForegroundWindow();        //    让程序前置到窗口
            ShowWindow(SW_SHOWNORMAL);
            break;
        case WM_RBUTTONUP:
            //-----------弹出菜单---------------------------------
            menu.CreatePopupMenu();
            menu.AppendMenu(MF_STRING, 1100+1, _T("还原")); //1100是自己定义的,表示菜单上的项目ID,
//最好用define定义成特定的字串,如#define MY_MENU_ITEM 1100;并且要按照MS的要求定义大小。
            menu.AppendMenu(MF_STRING, 1100+2, _T("退出"));
            POINT point;
            GetCursorPos(&point);
            SetForegroundWindow(); //这里是新添加的
            uCmd = menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, this, NULL);
            PostMessage(WM_NULL, 0, 0); //这里是新添加的
            switch(uCmd)    //    处理菜单消息
            {
            case 1100 + 1 :
                //AfxMessageBox("ok");
                DeleteShellNotifyIcon(0);    //    清除托盘图标
                ShowWindow(SW_SHOWNORMAL); 
                SetForegroundWindow();        //    让程序前置到窗口
                break;
            case 1100 + 2 :
                PostMessage(WM_CLOSE, 0, 0); // 退出程序
                break;
            default:
                break;
            }
        default:
              break;
    }
    return 0;
}
看来,这个问题莫名其妙,就两个函数解决了问题,不知道其中到底有什么毛病,还是没有说明具体问题!网络是个好东东,microsoft更是个好东东!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值