Сварачивание окна в SystemTray (шаблон WTL)
От: Splin Беларусь  
Дата: 05.02.03 17:13
Оценка: 9 (1)
Привет всем!

Сразу прошу прощения за столь избитый сабж.

Начну с использования:

1. Наследуем...
    class CMyWindow : public CSystemTrayWindow<CMyWindow> ...



2. Включаем в карту сообщений...
    BEGIN_MSG_MAP(CMyWindow)
        CHAIN_MSG_MAP(CSystemTrayWindow<CMyWindow>)
    ...


3. Создаем иконку где нибудь при создании окна...
    // create notify icon and sets context menu
    CreateNotifyIcon();
    SetNotifyIconContextMenu(IDM_POPUP);


Вот собственно и все, т.к. расписывать как работает шаблон мне лень...
Ах да... чуть не забыл — сам шаблон:

template <class T>
class CSystemTrayWindow
{
public:
    CSystemTrayWindow()
    {
        m_uID = 0;
        m_hIcon = NULL;
        m_szTip[0] = '\0';
        m_uMessage = WM_NULL;
        
        m_bAdded = FALSE;
        
        m_uIDMenu = 0;
    }

    virtual ~CSystemTrayWindow()
    {
        DestroyNotifyIcon();

        if(m_hIcon)
        {
            ::DestroyIcon(m_hIcon);
            m_hIcon = NULL;
        }
    }

public:
    BOOL CreateNotifyIcon(UINT uID = 1, UINT nMessage = WM_NULL)
    {
        m_uID = uID;
        
        if (nMessage != WM_NULL)
            m_uMessage = nMessage;
        else
            m_uMessage = GetDefaultNotifyIconMsg();

        return UpdateNotifyIcon();
    }

    BOOL CreateNotifyIcon(UINT uIDIcon, UINT uIDTip, UINT uID = 1, UINT nMessage = WM_NULL)
    {
        HINSTANCE hResource = _Module.GetResourceInstance();
        HICON hIcon;
        TCHAR szTip[64];
        
        if (0 == ::LoadString(hResource, uIDTip, szTip, _countof(lpszTip)))
            return FALSE;
        
        hIcon = (HICON)::LoadImage(hResource, MAKEINTRESOURCE(uIDIcon), 
            IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
        if(!hIcon)
            return FALSE;
        
        m_uID = uID;
        
        if (nMessage != WM_NULL)
            m_uMessage = nMessage;
        else
            m_uMessage = GetDefaultNotifyIconMsg();
        

        SaveNotifyIconTip(szTip);
        
        if (hIcon)
        {
            if (m_hIcon)
            {
                ::DestroyIcon(m_hIcon);
                m_hIcon = NULL;
            }
            m_hIcon = hIcon;
        }
        
        return AddNotifyIcon();
    }

    BOOL UpdateNotifyIcon()
    {
        T* pT = static_cast<T*>(this);
        ATLASSERT(::IsWindow(pT->m_hWnd));

        if(!IsWindow(pT->m_hWnd))
            return FALSE;

        // get window icon
        HICON hIcon = (HICON)pT->SendMessage(WM_GETICON, ICON_SMALL, 0);
        if(!hIcon)
            hIcon    = (HICON)pT->SendMessage(WM_GETICON, ICON_BIG, 0);

        if (hIcon == NULL)
            return FALSE;

        // get window text
        TCHAR szTip[64];
        szTip[0] = _T('\0');
        int nTitle = pT->GetWindowText(szTip, _countof(szTip));
        if (nTitle > _countof(szTip))
        {
            szTip[_countof(szTip)-1] = _T('.');
            szTip[_countof(szTip)-2] = _T('.');
            szTip[_countof(szTip)-3] = _T('.');
            szTip[_countof(szTip)] = _T('\0');
        }

        SaveNotifyIconTip(szTip);
        
        if (hIcon)
        {
            if (m_hIcon)
            {
                ::DestroyIcon(m_hIcon);
                m_hIcon = NULL;
            }
            m_hIcon = hIcon;
        }

        if (IsAddedNotifyIcon())
            return ModifyNotifyIcon();
        else
            return AddNotifyIcon();
    }

    BOOL DestroyNotifyIcon()
    {
        if (IsAddedNotifyIcon())
            return DeleteNotifyIcon();
        else
            return TRUE;
    }

    void SetNotifyIconContextMenu(UINT uIDMenu)
    {
        m_uIDMenu = uIDMenu;
    }
    
    BOOL SetNotifyIconTip(LPCTSTR lpszTip)
    {
        SaveNotifyIconTip(lpszTip);
        return ModifyNotifyIcon();
    }
    
    BOOL ModifyNotifyIcon(HINSTANCE hInstRes, UINT uIDIcon, UINT uIDTip)
    {
        TCHAR lpszTip[64];
        
        if (0 == ::LoadString(hInstRes, uIDTip, lpszTip, _countof(lpszTip)))
            return FALSE;
        else
            return ModifyNotifyIcon(hInstRes, uIDIcon, lpszTip);
    }
    
    BOOL ModifyNotifyIcon(HINSTANCE hInstRes, UINT uIDIcon, LPCTSTR lpszTip = NULL)
    {
        HICON hIcon;
        
        hIcon = (HICON)::LoadImage(hInstRes, MAKEINTRESOURCE(uIDIcon), 
            IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);

        if(!hIcon)
            return FALSE;

        if (lpszTip)
            SaveNotifyIconTip(lpszTip);
        
        if (hIcon)
        {
            if (m_hIcon)
            {
                ::DestroyIcon(m_hIcon);
                m_hIcon = NULL;
            }
            m_hIcon = hIcon;
        }

        return ModifyNotifyIcon();
    }

    BOOL IsAddedNotifyIcon()
    {
        return m_bAdded;
    }
    
    static UINT GetDefaultNotifyIconMsg(void)
    {
        static const UINT sc_uDefaultMsg = ::RegisterWindowMessage(_T("CHideWindow_DefaultNotifyIconMsg"));
        return sc_uDefaultMsg;
    }

    static UINT GetTaskbarCreatedMsg(void)
    {
        static const UINT sc_uTaskbarCreatedMsg = ::RegisterWindowMessage(_T("TaskbarCreated"));
        return sc_uTaskbarCreatedMsg;
    }

    BEGIN_MSG_MAP(CSowCommonHideWindow)
        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
        MESSAGE_HANDLER(WM_SIZE, OnSize)
        MESSAGE_HANDLER(GetTaskbarCreatedMsg(), OnTaskbarCreated)
        MESSAGE_HANDLER(m_uMessage, OnNotifyIcon)
    END_MSG_MAP()

    BOOL HideWindow()
    {
        T* pT = static_cast<T*>(this);
        ATLASSERT(::IsWindow(pT->m_hWnd));

        if(!IsWindow(pT->m_hWnd))
            return FALSE;
    
        return pT->ShowWindow(SW_HIDE);
    }
    
    BOOL RestoreWindow()
    {
        T* pT = static_cast<T*>(this);
        ATLASSERT(::IsWindow(pT->m_hWnd));

        if(!IsWindow(pT->m_hWnd))
            return FALSE;

        // if iconic, restore the main window
        if (pT->IsIconic())
            return pT->ShowWindow(SW_RESTORE);
        // if not visible, show main window
        else if (!pT->IsWindowVisible())
            return pT->ShowWindow(SW_SHOW);
        else
            return ForegroundWindow();
    }

    BOOL ForegroundWindow()
    {
        T* pT = static_cast<T*>(this);
        ATLASSERT(::IsWindow(pT->m_hWnd));

        if(!IsWindow(pT->m_hWnd))
            return FALSE;

        // if so, does it have any popups?
        HWND hWndChild = pT->GetLastActivePopup();
        // bring the main window or its popup to the foreground
        return ::SetForegroundWindow(hWndChild);
    }

protected:

    LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
    {
        // destroy notify icon
        DestroyNotifyIcon();
        bHandled = FALSE;
        return 0;
    }

    LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
    {
        if (wParam == SIZE_MINIMIZED && IsAddedNotifyIcon())
        {
            HideWindow();
            return 1;
        }
        bHandled = FALSE;
        return 0;
    }

    LRESULT OnTaskbarCreated(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
    {
        if (IsAddedNotifyIcon())
            RestoreNotifyIcon();
        bHandled = FALSE;
        return 0;
    }

    LRESULT OnNotifyIcon(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        if (!IsAddedNotifyIcon())
            return 0;
        
        if (m_uID != wParam)
            return 0;

        POINT point;
        ::GetCursorPos(&point);
        
        switch(lParam)
        {
        case WM_MOUSEMOVE:
            break;
        case WM_LBUTTONDBLCLK:
            break;
        case WM_LBUTTONDOWN:
            RestoreWindow();
            ForegroundWindow();
            break;
        case WM_LBUTTONUP:
            break;
        case WM_RBUTTONDOWN:
            break;
        case WM_RBUTTONUP:
            OnNotifyIconContextMenu(point);
            break;
        case WM_RBUTTONDBLCLK:
            break;
        default:
            break;
        }

        bHandled = FALSE;
        return 0;
    }
    
    virtual void OnNotifyIconContextMenu(const POINT& point)
    {
        T* pT = static_cast<T*>(this);
        ATLASSERT(::IsWindow(pT->m_hWnd));

        if(!IsWindow(pT->m_hWnd))
            return;

        HMENU hPopupMenu;
        HMENU hSubMenu;
        HINSTANCE hResource = _Module.GetResourceInstance();
        
        if(m_uIDMenu == 0)
            return;
        
        hPopupMenu = ::LoadMenu(hResource, MAKEINTRESOURCE(m_uIDMenu));
        
        if(hPopupMenu)
        {
            if (hSubMenu = ::GetSubMenu(hPopupMenu, 0))
            {
                if (!pT->SendMessage(WM_INITMENUPOPUP, (WPARAM)hSubMenu, 0))
                {
                    ForegroundWindow();
                    ::TrackPopupMenuEx(hSubMenu, TPM_LEFTALIGN, point.x, point.y, pT->m_hWnd, NULL);
                    pT->PostMessage(WM_NULL, 0, 0);
                }
            }
            ::DestroyMenu(hPopupMenu);
        }
    }

private:

    void SaveNotifyIconTip(LPCTSTR lpszTip)
    {
        if (lpszTip)
            lstrcpyn(m_szTip, lpszTip, _countof(m_szTip));
        else
            m_szTip[0] = '\0';
    }
    
    BOOL AddNotifyIcon()
    {
        T* pT = static_cast<T*>(this);
        ATLASSERT(::IsWindow(pT->m_hWnd));

        if(!IsWindow(pT->m_hWnd))
            return FALSE;
        
        NOTIFYICONDATA nid;
        ZeroMemory(&nid, sizeof(NOTIFYICONDATA));
        nid.cbSize                 = sizeof(NOTIFYICONDATA);
        nid.hWnd                 = pT->m_hWnd;
        nid.uID                 = m_uID;
        nid.uFlags                 = NIF_MESSAGE | (m_hIcon ? NIF_ICON : 0);
        nid.uCallbackMessage    = m_uMessage;
        nid.hIcon                 = m_hIcon;
        
        if(lstrlen(m_szTip))
        {
            lstrcpyn(nid.szTip, m_szTip, _countof(nid.szTip));
            nid.uFlags |= NIF_TIP;
        }
        
        return (m_bAdded = ::Shell_NotifyIcon(NIM_ADD, &nid));
    }

    BOOL ModifyNotifyIcon()
    {
        T* pT = static_cast<T*>(this);
        ATLASSERT(::IsWindow(pT->m_hWnd));

        if(!IsWindow(pT->m_hWnd))
            return FALSE;
        
        NOTIFYICONDATA nid;
        ZeroMemory(&nid, sizeof(NOTIFYICONDATA));
        nid.cbSize                 = sizeof(NOTIFYICONDATA);
        nid.hWnd                 = pT->m_hWnd;
        nid.uID                 = m_uID;
        nid.uFlags                 = NIF_MESSAGE | (m_hIcon ? NIF_ICON : 0);
        nid.uCallbackMessage    = m_uMessage;
        nid.hIcon                 = m_hIcon;
        
        if(lstrlen(m_szTip))
        {
            lstrcpyn(nid.szTip, m_szTip, _countof(nid.szTip));
            nid.uFlags |= NIF_TIP;
        }
        
        return ::Shell_NotifyIcon(NIM_MODIFY, &nid);
    }
    
    BOOL DeleteNotifyIcon(void)
    {
        T* pT = static_cast<T*>(this);
        ATLASSERT(::IsWindow(pT->m_hWnd));

        if(!IsWindow(pT->m_hWnd))
            return FALSE;
        
        NOTIFYICONDATA nid;
        ZeroMemory(&nid, sizeof(NOTIFYICONDATA));
        nid.cbSize = sizeof(NOTIFYICONDATA);
        nid.hWnd   = pT->m_hWnd;
        nid.uID    = m_uID;
        
        return !(m_bAdded = !::Shell_NotifyIcon(NIM_DELETE, &nid));
    }
    
    BOOL RestoreNotifyIcon(void)
    {
        if(!m_hIcon)
            return FALSE;
        return AddNotifyIcon();
    }

    UINT        m_uID;            // the id
    UINT        m_uMessage;        // the message id

    HICON        m_hIcon;        // the handle of a current icon
    TCHAR        m_szTip[128];    // the tip string
    
    UINT        m_uIDMenu;        // the id of a popup menu
    BOOL        m_bAdded;

};
... << RSDN@Home 1.0 beta 5 >>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.