WTL: Подсказка в любом месте экрана
От: WinterMute Россия http://yarrr.ru
Дата: 18.08.04 14:15
Оценка:
В своё время меня не устроил стандартный CTooltipCtrl -- мне была нужена подсказка которая бы появлялась и пропадала когда ей скажут. Кроме того, нужно было, что бы подсказка была прозрачна для всех сообщений мыши (я делал т.н. inplace tooltip). Этот простой класс делает всё вышеперечисленное.

Короткое описание:

Маленькое замечание: при создании нужно указать окно хозяин, и это не тоже самое что окно владелец(m_hWndOwner). В качестве хозяина удобнее всего установить ::GetDesktopWindow(), в противном случае возникают малопонятные глюки с позиционированием.

namespace UI2
{
    class Tooltip
        : public CWindowImpl<Tooltip, ATL::CWindow>
    {
    public:
        typedef CWindowImpl<Tooltip, ATL::CWindow> baseClass;
        typedef Tooltip thisClass;

        HWND     m_hWndOwner;

    private:
        TOOLINFO m_ToolInfo;
        bool     m_bActive;

        enum { TIMER_MSG_DELAY_SHOW = 100, TIMER_MSG_DELAY_HIDE = 101, };

        static LPCTSTR GetWndClassName(){ return _T("Zaebis_Tooltip"); }

    public:
        DECLARE_WND_SUPERCLASS(GetWndClassName(), baseClass::GetWndClassName())

        BEGIN_MSG_MAP(thisClass)
            MESSAGE_HANDLER(WM_TIMER, OnTimer)
            MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
        END_MSG_MAP()


        Tooltip()
        : baseClass()
        , m_bActive(false)  // подсказка видна
        , m_hWndOwner(0)    // окно, которому будут передаваться мышиные сообщения
        {
        }

        virtual ~Tooltip()
        { }

        bool Create( HWND hWndParent, HWND hWndOwner = NULL )
        {
            HWND hWnd = ::CreateWindowEx(WS_EX_TOPMOST,
                TOOLTIPS_CLASS,
                NULL,
                TTS_NOPREFIX | TTS_ALWAYSTIP,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                hWndParent,
                NULL,
                NULL,
                NULL);

            ATLASSERT(hWnd);

            // initialize toolinfo struct
            memset(&m_ToolInfo, 0, sizeof(m_ToolInfo));
            m_ToolInfo.cbSize = sizeof(m_ToolInfo);
            m_ToolInfo.uFlags = TTF_TRACK | TTF_TRANSPARENT | TTF_SUBCLASS;
            m_ToolInfo.hwnd = hWndParent;

            ::SendMessage(hWnd, TTM_SETMAXTIPWIDTH, 0, SHRT_MAX);
            ::SendMessage(hWnd, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &m_ToolInfo);

            m_hWndOwner = hWndOwner;

            SubclassWindow( hWnd );

            return true;
        }

        void SetBackColor( COLORREF c ){ ::SendMessage(m_hWnd, TTM_SETTIPBKCOLOR, c, 0); }
        void SetTextColor( COLORREF c ){ ::SendMessage(m_hWnd, TTM_SETTIPTEXTCOLOR, c, 0); }
        void SetMargins( const RECT* rectMargins ){ ::SendMessage(m_hWnd, TTM_SETMARGIN, 0, (LPARAM)rectMargins); }
        void SetMaxWidth( int maxWidth ){ ::SendMessage(m_hWnd, TTM_SETMAXTIPWIDTH, 0, (LPARAM)maxWidth); }

        bool IsVisible(){ return m_bActive; };

        CString GetText()
        {
            ::SendMessage( m_hWnd, TTM_GETTEXT, 0, m_ToolInfo );
            return CString( m_ToolInfo.lpszText );
        }

        void SetText( const TCHAR* str )
        {
            delete m_ToolInfo.lpszText;
            if( str )
            {
                m_ToolInfo.lpszText = new TCHAR[ _tcslen(str)+1 ];
                _tcscpy( m_ToolInfo.lpszText, str );
            }
            else m_ToolInfo.lpszText = NULL;

            ::SendMessage( m_hWnd, TTM_UPDATETIPTEXT, 0, (LPARAM)(LPTOOLINFO) &m_ToolInfo );
        }

        void Show( int x, int y )
        {
            m_bActive = true;

            ::SendMessage( m_hWnd, TTM_TRACKPOSITION, 0, (LPARAM)(DWORD) MAKELONG( x, y ) );
            ::SendMessage( m_hWnd, TTM_TRACKACTIVATE, TRUE, (LPARAM)(LPTOOLINFO) &m_ToolInfo );
        }

        void Show( const RECT* r )
        {
            m_bActive = true;

            m_ToolInfo.rect = *r;

            ::SendMessage( m_hWnd, TTM_TRACKPOSITION, 0, (LPARAM)(DWORD) MAKELONG( r->left, r->top ) );
            ::SendMessage( m_hWnd, TTM_SETMAXTIPWIDTH, 0, (LPARAM)(r->right - r->left) );
            ::SendMessage( m_hWnd, TTM_TRACKACTIVATE, TRUE, (LPARAM)(LPTOOLINFO)&m_ToolInfo );
        }

        void Show( BOOL bShow = TRUE )
        {
            KillTimer( TIMER_MSG_DELAY_SHOW );
            KillTimer( TIMER_MSG_DELAY_HIDE );

            m_bActive = (bShow == TRUE);

            ::SendMessage( m_hWnd, TTM_TRACKACTIVATE, bShow, (LPARAM)(LPTOOLINFO) &m_ToolInfo );
        }

        void Move( int x, int y )
        {
            ::SendMessage( m_hWnd, TTM_TRACKPOSITION, 0, (LPARAM)(DWORD) MAKELONG( x, y ) );
        }

        void DelayShowAtCursor( UINT timeToShow )
        {
            KillTimer( TIMER_MSG_DELAY_SHOW );
            SetTimer( TIMER_MSG_DELAY_SHOW, timeToShow );
        }

        operator HWND() { return m_hWnd; }


        // Message handlers

        LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
        {
            if( TIMER_MSG_DELAY_SHOW == wParam )
            {
                POINT pt; ::GetCursorPos( &pt );
                Show( pt.x, pt.y+20 );
                KillTimer( wParam );
            }
            else if( TIMER_MSG_DELAY_HIDE == wParam )
            {
                Show(FALSE);
                KillTimer( wParam );
            }

            bHandled = FALSE;
            return 0;
        }

        LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
        {
            // forward message to owner window 
            if( m_hWndOwner )
            {
                POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                ClientToScreen( &pt ); ::ScreenToClient( m_hWndOwner, &pt );
                lParam = PtToLPARAM(pt);

                ::SendMessage( m_hWndOwner, uMsg, wParam, lParam );
            }

            bHandled = TRUE;
            return 0;
        }
    };

    // ----------------------------------------------------
    
    inline LPARAM PtToLPARAM( POINT pt )
    {
        LPARAM lParam = 0;
        WORD*  pLParam = (WORD*)&lParam;
    
        pLParam[0] = (short)pt.x;
        pLParam[1] = (short)pt.y;
    
        return lParam;
    }
}
Думай, что хочешь, делай, что хочешь, живи, как хочешь -- всё тебе припомню!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.