您的位置:首页 > 其它

MFC窗口程序启动时最小化到托盘、不在任务栏中显示、显示时在右小角

2017-09-29 14:32 666 查看


转自:http://www.cnblogs.com/watchdatalearn2012620/archive/2013/04/17/3025482.html


原文地址: http://hi.baidu.com/biboheart/item/5d17f8068c1c8a9c3c42e2dc


第一步:窗口最小化到托盘,显示图标。

       这一步在网上一搜,真的很多文章,基本上都可以用吧。有的是在OnSize中最化时画图标,隐藏窗口;有的是在初始化时画图标,在OnSysCommand中判断最大化和最小化时进行窗口显示隐藏。我选择了后者。一开始在后面的步骤遇到了麻烦,最后第二种方法完成了。谅没再去试第一种方法。在OnSysCommand中显示隐藏,效果挺好的。

       我的开发环境是VS2008,创建一个对话框应用程序,选中包含最小化框(因为要最小化到托盘)。因为我的程序只是设计成在屏幕右小角显示一个小窗口来开启、停止、配置服务的一些操作。所以不要最大化功能。

       1、XXXDlg.h中声明一个方法用作显示托盘图标。void _fnToTray();

             XXXDlg.cpp中实现如下

             //在桌面右下角显示托盘图标 

             void CXXXDlg::_fnToTray() 

             { 

                    NOTIFYICONDATA nid; 

                    nid.cbSize = sizeof( NOTIFYICONDATA ); 

                    nid.hWnd = m_hWnd; 

                    nid.uID = IDR_MAINFRAME; 

                    nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; 

                    nid.uCallbackMessage = WM_SYSTEMTRAY; 

                    nid.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 

                    wcscpy_s(nid.szTip, _T("服务管理器")); 

                    ::Shell_NotifyIcon(NIM_ADD,&nid ); 

             }

       2、修改CXXXDlg::OnSysCommand(UINT nID, LPARAM lParam)方法,橙色为增加的代码

             void CXXXDlg::OnSysCommand(UINT nID, LPARAM lParam) 

             { 

                    if ((nID & 0xFFF0) == IDM_ABOUTBOX) 

                    { 

                            CAboutDlg dlgAbout; 

                            dlgAbout.DoModal(); 

                    } 

else if(nID == SC_MAXIMIZE) //最大化 

                    { 

                            this->ShowWindow(SW_SHOW); 

                    } 

                    else if(nID == SC_MINIMIZE) //最小化,把他隐藏起来 

                    { 

                            this->ShowWindow(SW_HIDE); 

                    } 

                    else 

                    { 

                            CDialog::OnSysCommand(nID, lParam); 

                    } 

             }

      3、在资源中新建一个菜单资源,我这里为IDR_MENU1,在菜单中添加一个子菜单,设ID为ID_EXIT,文字为

          “退出”。

      4、在targetver.h文件中,最后添加一行#define  WM_SYSTEMTRAY WM_USER+1

      5、在XXXDlg.h文件中,添加方法声明:

            afx_msg LRESULT OnSystemTray(WPARAM wParam, LPARAM lParam);

      6、在XXXDlg.cpp文件中,BEGIN_MESSAGE_MAP(CXXXDlg,CDialog)和END_MESSAGE_MAP()之间增加

            ON_MESSAGE(WM_SYSTEMTRAY,OnSystemTray)

      7、在XXXDlg.cpp文件中,实现方法:

            LRESULT CXXXDlg::OnSystemTray(WPARAM wParam, LPARAM lParam) 

            { 

                   if ( wParam = IDR_MAINFRAME ) 

                   { 

                            switch( lParam ) 

                            { 

                            case WM_LBUTTONDOWN:            //左键点击托盘图标显示窗口 

                                     this->ShowWindow(SW_NORMAL); 

                                     break; 

                            case WM_RBUTTONDOWN:           //右键点击托盘图标显示菜单 

                                     CMenu menu; 

                                     menu.LoadMenu(IDR_MENU1); 

                                     POINT pt; 

                                     ::GetCursorPos(&pt); 

                                     menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTALIGN, pt.x, pt.y, this); 

                                     break; 

                            } 

                   } 

                   return 1; 

            }

8、声明右键菜单:在XXXDlg.h中声明afx_msg void OnExit();

       9、在XXXDlg.cpp中BEGIN_MESSAGE_MAP(CXXXDlg,CDialog)和END_MESSAGE_MAP()之间增加

             ON_COMMAND(ID_EXIT,OnExit)

       10、在XXXDlg.cpp中实现退出

               void CXXXDlg::OnExit() 

               { 

                        this->PostMessageW(WM_QUIT); 

               }

       11、在程序的OnDestroy()消息中移除图标



               void CXXXDlg::OnDestroy() 

               { 

                        CDialog::OnDestroy();

                        // TODO: 在此处添加消息处理程序代码 

                        NOTIFYICONDATA nid; 

                        nid.cbSize = sizeof( NOTIFYICONDATA ); 

                        nid.hWnd = m_hWnd; 

                        nid.uID = IDR_MAINFRAME; 

                        nid.uFlags = 0; 

                        ::Shell_NotifyIcon( NIM_DELETE,&nid ); 

               }

        12、一切准备好了。在CXXXDlg::OnInitDialog()中添加

                _fnToTray();

//-----------------------气泡窗体-----------------------------------

void CTimingDlg::ShowInfo() 



m_Htnd.cbSize = sizeof(NOTIFYICONDATA); 

m_Htnd.hWnd = GetSafeHwnd(); 

m_Htnd.uFlags = NIF_INFO; 

m_Htnd.uID=IDR_MAINFRAME; 

m_Htnd.dwInfoFlags=1; 

m_Htnd.uTimeout = 3000; 

wcscpy(m_Htnd.szInfoTitle,_T("气泡标题")); 

wcscpy(m_Htnd.szInfo,_T("气泡内容")); 

Shell_NotifyIcon(NIM_MODIFY,&m_Htnd); 

}

//-----------------------------------------------------------------

第二步:在屏幕右下角显示窗口

       这步代码很少,实现起来简单。

       1、在CXXXDlg.h中声明一个方法void _fnShowRBOfWindow();

       2、实现在CXXXDlg.cpp中

//在桌面右下角显示 

void CCCRFIDServiceManagerDlg::_fnShowRBOfWindow() 



 // 获得桌面大小 

 CRect rectWorkArea; 

 SystemParametersInfo(SPI_GETWORKAREA,0,&rectWorkArea,SPIF_SENDCHANGE); 

 // 获得对话框大小 

 CRect rectDlg; 

 GetWindowRect(&rectDlg); 

 int nW = rectDlg.Width(); 

 int nH = rectDlg.Height(); 

 // 将窗口设置到右下角 

 SetWindowPos(NULL,rectWorkArea.right-nW,rectWorkArea.bottom-nH,nW,nH,SWP_NOSIZE); 

}

        3、在CXXXDlg::OnInitDialog()中添加

_fnShowRBOfWindow();

这样就实现了程序窗口显示在桌面右下角

第三步:实现程序启动时无窗口、任务栏不显示。只有在托盘显示了一个图标。

       这一步如果只是在CXXXDlg.cpp的某处调用ShowWindow(SW_HIDE),不容易实现,实现了也不能得到好的效果,有的会闪一下。最后试下以下方法,运行起来效果挺好。

       1、在CXXXApp.h中添加一个变量:CWnd m_wndOwner;

       2、在CXXXApp.cpp::InitInstance()中修改添加(橙色为修改内容):

BOOL CCCRFIDServiceManagerApp::InitInstance() 



 // 如果一个运行在 Windows XP 上的应用程序清单指定要 

 // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式, 

 //则需要 InitCommonControlsEx()。否则,将无法创建窗口。 

 INITCOMMONCONTROLSEX InitCtrls; 

 InitCtrls.dwSize = sizeof(InitCtrls); 

 // 将它设置为包括所有要在应用程序中使用的 

 // 公共控件类。 

 InitCtrls.dwICC = ICC_WIN95_CLASSES; 

 InitCommonControlsEx(&InitCtrls);

CWinApp::InitInstance();

AfxEnableControlContainer();

// 标准初始化 

 // 如果未使用这些功能并希望减小 

 // 最终可执行文件的大小,则应移除下列 

 // 不需要的特定初始化例程 

 // 更改用于存储设置的注册表项 

 // TODO: 应适当修改该字符串, 

 // 例如修改为公司或组织名 

 SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

if ( m_wndOwner.m_hWnd == NULL ) 

 { 

  LPCTSTR pstrOwnerClass = AfxRegisterWndClass(0);

  if ( !m_wndOwner.CreateEx(0, pstrOwnerClass, _T(""),  //创建一个隐藏的弹出样式的窗口 

         WS_POPUP, CW_USEDEFAULT, 

         CW_USEDEFAULT, 

         CW_USEDEFAULT, 

         CW_USEDEFAULT, 

         NULL, 0) ) 

  return FALSE; 

 }

CXXXDlg dlg(&m_wndOwner); 

 m_pMainWnd = &dlg; 

 INT_PTR nResponse = dlg.DoModal(); 

 if (nResponse == IDOK) 

 { 

  // TODO: 在此放置处理何时用 

  //  “确定”来关闭对话框的代码 

 } 

 else if (nResponse == IDCANCEL) 

 { 

  // TODO: 在此放置处理何时用 

  //  “取消”来关闭对话框的代码 

 } 

 if (m_wndOwner.m_hWnd != NULL) 

 { 

  m_wndOwner.DestroyWindow(); 

 }

// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序, 

 //  而不是启动应用程序的消息泵。 

 return FALSE; 

}

       3、编辑CXXX.rc()查看代码编辑。找到EXSTYLE WS_EX_APPWINDOW删除。

       4、在CXXXDlg.cpp::OnInitDialog()中添加(在CXXXDlg.h中添加变量WINDOWPLACEMENT m_wp)

m_wp.length = sizeof(WINDOWPLACEMENT); 

 GetWindowPlacement(&m_wp);  //恢复时用 

 WINDOWPLACEMENT wp; 

 wp.length = sizeof(WINDOWPLACEMENT); 

 wp.flags = WPF_RESTORETOMAXIMIZED; 

 wp.showCmd = SW_HIDE; 

 SetWindowPlacement(&wp);

在第一步中的OnSystemTray(WPARAM wParam, LPARAM lParam)修改如下:

LRESULT CCCRFIDServiceManagerDlg::OnSystemTray(WPARAM wParam, LPARAM lParam) 



    if ( wParam = IDR_MAINFRAME ) 

    { 

        switch( lParam ) 

        { 

        case WM_LBUTTONDOWN: 

            this->ShowWindow(SW_NORMAL); 

SetWindowPlacement(&m_wp); 

            break; 

        case WM_RBUTTONDOWN: 

            CMenu menu; 

            menu.LoadMenu(IDR_MENU_RBUTTON); 

            POINT pt; 

            ::GetCursorPos(&pt); 

            menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTALIGN, pt.x, pt.y, this); 

            break; 

        } 

    } 

    return 1; 

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: