Еще несколько маленьких доработок:
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 >>