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


    原文地址: 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;
    }

    #vc 学习专用

  • 相关阅读:
    Pyspider实例之抓取数据并保存到MySQL的数据库
    pyspider中内容选择器常用方法汇总
    pyspider用PyQuery解析页面数据
    CasperJs 入门介绍
    移动应用抓包调试利器Charles
    GO语言文件的创建与打开实例分析
    Golang之实现一个负载均衡算法(随机,轮询)
    重新认识一个强大的 Gson
    关于Java的File.separator
    centos重启redis后,数据丢失
  • 原文地址:https://www.cnblogs.com/watchdatalearn2012620/p/3025482.html
Copyright © 2020-2023  润新知