///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using JetBrains.Interop.WinApi;
using JetBrains.Omea.Base;
using JetBrains.UI.Interop;
namespace JetBrains.JetListViewLibrary
{
///
/// Custom wrapper for the system ToolTips control.
///
internal class ItemToolTip: NativeWindow, IDisposable
{
private const string TOOLTIP_CLASS = "tooltips_class32";
private JetListView _ownerControl;
private PinnedStringPool _toolTipPool;
private Rectangle _lastItemShowRect;
private JetListViewNode _lastToolTipNode;
private JetListViewColumn _lastToolTipColumn;
private bool _lastNeedPlace = true;
public ItemToolTip( JetListView ownerControl )
{
_ownerControl = ownerControl;
_toolTipPool = new PinnedStringPool( 5 );
}
public void Dispose()
{
DestroyHandle();
_toolTipPool.Dispose();
}
internal void CreateHandle()
{
CreateParams cp = new CreateParams();
cp.Parent = _ownerControl.Handle;
cp.ClassName = TOOLTIP_CLASS;
unchecked
{
cp.Style = (int) Win32Declarations.WS_POPUP | Win32Declarations.TTS_NOFADE | Win32Declarations.TTS_NOPREFIX;
}
cp.ExStyle = 0;
cp.Caption = null;
CreateHandle( cp );
Win32Declarations.SetWindowPos( this.Handle, (IntPtr) Win32Declarations.HWND_TOPMOST, 0, 0, 0, 0, 19 );
TOOLINFOCB ti = new TOOLINFOCB();
ti.cbSize = Marshal.SizeOf( typeof(TOOLINFO) );
ti.flags = Win32Declarations.TTF_IDISHWND | Win32Declarations.TTF_SUBCLASS | Win32Declarations.TTF_TRANSPARENT;
ti.hwnd = _ownerControl.Handle;
ti.uId = _ownerControl.Handle;
ti.textCallback = Win32Declarations.LPSTR_TEXTCALLBACK;
if ( Win32Declarations.SendMessage( Handle, Win32Declarations.TTM_ADDTOOLW, 0, ref ti ) == 0 )
{
throw new Exception( "Failed to add tool" );
}
Win32Declarations.SendMessage( Handle, Win32Declarations.TTM_ACTIVATE, (IntPtr) 1, IntPtr.Zero );
}
internal void HandleWMNotify( ref Message m )
{
uint pos = Win32Declarations.GetMessagePos();
Point pt = new Point( Win32Declarations.LOWORD( pos ), Win32Declarations.HIWORD( pos ) );
pt = _ownerControl.PointToClient( pt );
NMHDR nmhdr = (NMHDR) m.GetLParam( typeof(NMHDR) );
if ( nmhdr.code == Win32Declarations.TTN_NEEDTEXTW )
{
NMTTDISPINFOW dispInfo = (NMTTDISPINFOW) m.GetLParam( typeof(NMTTDISPINFOW ) );
_lastToolTipNode = _ownerControl.GetNodeAt( pt );
_lastToolTipColumn = _ownerControl.GetColumnAt( pt );
string tooltip = null;
if ( _lastToolTipColumn != null && _lastToolTipNode != null )
{
Rectangle rc = _ownerControl.GetItemBounds( _lastToolTipNode, _lastToolTipColumn );
_lastNeedPlace = true;
tooltip = _lastToolTipColumn.GetToolTip( _lastToolTipNode, rc, ref _lastNeedPlace );
_lastItemShowRect = rc;
}
if ( tooltip == null || tooltip.Length == 0 )
{
dispInfo.szText = "";
dispInfo.lpszText = IntPtr.Zero;
}
else
{
dispInfo.lpszText = _toolTipPool.PinString( tooltip );
}
Marshal.StructureToPtr( dispInfo, m.LParam, false );
}
else if ( nmhdr.code == Win32Declarations.TTN_SHOW && _lastNeedPlace )
{
Rectangle scItemShowRect = _ownerControl.RectangleToScreen( _lastItemShowRect );
RECT rc = Win32Declarations.RectangleToRECT( scItemShowRect );
Win32Declarations.SendMessage( Handle, (LVM) Win32Declarations.TTM_ADJUSTRECT,
1, ref rc );
Win32Declarations.SetWindowPos( Handle, IntPtr.Zero, rc.left, rc.top, 0, 0,
Win32Declarations.SWP_NOSIZE | Win32Declarations.SWP_NOZORDER | Win32Declarations.SWP_NOACTIVATE );
m.Result = (IntPtr) 1;
}
}
internal void UpdateToolTip( Point pt )
{
JetListViewNode node = _ownerControl.GetNodeAt( pt );
JetListViewColumn col = _ownerControl.GetColumnAt( pt );
if ( node != _lastToolTipNode || col != _lastToolTipColumn )
{
Hide();
Win32Declarations.SendMessage( Handle, Win32Declarations.TTM_UPDATE, IntPtr.Zero, IntPtr.Zero );
}
}
public void Hide()
{
Win32Declarations.ShowWindow( Handle, Win32Declarations.SW_HIDE );
}
}
}