Еще несколько маленьких доработок:

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_bVisible;
        bool     m_bShowAtCursor;

        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_HANDLER(WM_SETCURSOR, OnMouseMessage) // Если хочется что бы над подказкой был такой-же курсор как и над хозяином
            MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
        END_MSG_MAP()


        Tooltip()
        : baseClass()
        , m_bVisible(false)
        , m_hWndOwner(0)
        {
            memset(&m_ToolInfo, 0, sizeof(m_ToolInfo));
        }

        ~Tooltip()
        { 
            DestroyWindow();
        }

        bool Create( HWND hWndParent, HWND hWndOwner = NULL )
        {
            DestroyWindow();

            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
            m_ToolInfo.cbSize = sizeof(m_ToolInfo);
            m_ToolInfo.uFlags = TTF_TRACK | TTF_TRANSPARENT | TTF_SUBCLASS;
            m_ToolInfo.hwnd = hWndParent;

             m_hWndOwner = hWndOwner;

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

            SubclassWindow( hWnd );

            return true;
        }


        void DestroyWindow()
        {
            if( m_hWnd )baseClass::DestroyWindow();

            delete [] m_ToolInfo.lpszText;
            memset(&m_ToolInfo, 0, sizeof(m_ToolInfo));
        }


        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_bVisible; };

        const TCHAR* GetText()
        {
            ::SendMessage( m_hWnd, TTM_GETTEXT, 0, (LPARAM)&m_ToolInfo );
            return m_ToolInfo.lpszText;
        }

        void SetText( const TCHAR* text )
        {
            delete [] m_ToolInfo.lpszText;

            if( text )
            {
                m_ToolInfo.lpszText = new TCHAR[ _tcslen(text)+1 ];
                _tcscpy( m_ToolInfo.lpszText, text );
            }
            else m_ToolInfo.lpszText = NULL;

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

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

        void Show( int x, int y )
        {
            Move( x, y );
            Show();
        }

        void Show( const RECT* r )
        {
            m_bVisible = 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)&m_ToolInfo );
        }

        void Show( BOOL bShow = TRUE )
        {
            m_bVisible = (bShow == TRUE);
            ::SendMessage( m_hWnd, TTM_TRACKACTIVATE, bShow, (LPARAM)&m_ToolInfo );
        }

        void ShowAtCursor()
        {
            POINT pt; ::GetCursorPos( &pt );
            Show( pt.x, pt.y+20 );
        }

        void ShowAfter( UINT delay, bool bAtCursor = false )
        {
            if( IsWindow() )
            {
                m_bShowAtCursor = bAtCursor;

                KillTimer( TIMER_MSG_DELAY_SHOW );
                SetTimer( TIMER_MSG_DELAY_SHOW, delay );
            }
        }

        void ShowAtCursorAfter( UINT delay )
        {
            ShowAfter( delay, true );
        }

        void HideAfter( UINT delay )
        {
            if( IsWindow() )
            {
                KillTimer( TIMER_MSG_DELAY_HIDE );
                SetTimer( TIMER_MSG_DELAY_HIDE, delay );
            }
        }

        void CancelShowAfter()
        {
            KillTimer( TIMER_MSG_DELAY_SHOW );
        }

        void CancelHideAfter()
        {
            KillTimer( TIMER_MSG_DELAY_HIDE );
        }

        operator HWND() { return m_hWnd; }


        // Message handlers

        LRESULT OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
        {
            if( TIMER_MSG_DELAY_SHOW == wParam )
            {
                m_bShowAtCursor?ShowAtCursor():Show();
                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 )
        {
            LRESULT ret = 0;

            // forward message to owner window 
            if( m_hWndOwner )
            {
                POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                ClientToScreen( &pt ); ::ScreenToClient( m_hWndOwner, &pt );
                ret = ::SendMessage( m_hWndOwner, uMsg, wParam, MAKELONG( pt.x, pt.y ) );
            }

            //bHandled = TRUE;
            bHandled = FALSE;
            return ret;
        }
    };
}
... << RSDN@Home 1.1.4 @@subversion >>
Автор: WinterMute    Оценить