private Size GetToolTipWindowSize(string contentSpacing) { Win32.TOOLINFO ti = new Win32.TOOLINFO(); ti.cbSize = Marshal.SizeOf(ti); ti.uFlags = Win32.TTF_TRACK; ti.lpszText = contentSpacing; if (0 == Win32.SendMessage(Handle, Win32.TTM_ADDTOOL, 0, ref ti)) { throw new Exception(); } // enable multi-line text-layout Win32.SendMessage(Handle, Win32.TTM_SETMAXTIPWIDTH, 0, SystemInformation.MaxWindowTrackSize.Width); Win32.SendMessage(Handle, Win32.TTM_TRACKACTIVATE, 1, ref ti); Win32.RECT rect = new Win32.RECT(); Win32.GetWindowRect(Handle, ref rect); Win32.SendMessage(Handle, Win32.TTM_TRACKACTIVATE, 0, ref ti); Win32.SendMessage(Handle, Win32.TTM_DELTOOL, 0, ref ti); return(new Size(rect.right - rect.left, rect.bottom - rect.top)); }
private Win32.TOOLINFO CreateTool(string contentSpacing, IWin32Window window, StemPosition stemPosition) { Win32.TOOLINFO ti = new Win32.TOOLINFO(); ti.cbSize = Marshal.SizeOf(ti); ti.uFlags = Win32.TTF_IDISHWND | Win32.TTF_TRACK | Win32.TTF_TRANSPARENT; ti.uId = window.Handle; ti.hwnd = window.Handle; ti.lpszText = contentSpacing; if (StemPosition.BottomCentre == stemPosition || StemPosition.TopCentre == stemPosition) { ti.uFlags |= Win32.TTF_CENTERTIP; } if (0 == Win32.SendMessage(Handle, Win32.TTM_ADDTOOL, 0, ref ti)) { throw new Exception(); } // enable multi-line text-layout Win32.SendMessage(Handle, Win32.TTM_SETMAXTIPWIDTH, 0, SystemInformation.MaxWindowTrackSize.Width); return(ti); }
public ToolTipWindow(Control content, IWin32Window window, int x, int y, StemPosition stemPosition, bool useAnimation, bool useFading) { Window = window; CreateParams createParams = new CreateParams(); createParams.ClassName = Win32.TOOLTIPS_CLASS; createParams.Style = Win32.TTS_ALWAYSTIP | Win32.TTS_BALLOON; if (!useAnimation) { createParams.Style |= Win32.TTS_NOANIMATE; } if (!useFading) { createParams.Style |= Win32.TTS_NOFADE; } CreateHandle(createParams); // first, work out the actual stem-position: the supplied value is a hint, but may have to be changed if there isn't enough space to accomodate it string contentSpacing = GetSizingText(content); // this is where the caller would like us to be Rectangle toolTipBounds = CalculateToolTipLocation(contentSpacing, Window, x, y, stemPosition); Screen currentScreen = Screen.FromHandle(Window.Handle); Rectangle screenBounds = currentScreen.WorkingArea; stemPosition = AdjustStemPosition(stemPosition, ref toolTipBounds, ref screenBounds); // and this is where we'll actually end up toolTipBounds = CalculateToolTipLocation(contentSpacing, Window, x, y, stemPosition); toolTipBounds.X = Math.Max(0, toolTipBounds.X); toolTipBounds.Y = Math.Max(0, toolTipBounds.Y); // build the tooltip window _toolInfo = CreateTool(contentSpacing, Window, stemPosition); // initial position to force the stem into the correct orientation int initialX = screenBounds.X; int initialY = screenBounds.Y; if (StemPosition.TopLeft == stemPosition || StemPosition.BottomLeft == stemPosition) { initialX += StemInset; } else if (StemPosition.TopCentre == stemPosition || StemPosition.BottomCentre == stemPosition) { initialX += screenBounds.Width / 2; } else { initialX += screenBounds.Width - StemInset; } if (StemPosition.BottomLeft == stemPosition || StemPosition.BottomCentre == stemPosition || StemPosition.BottomRight == stemPosition) { initialY += screenBounds.Height; } Win32.SendMessage(Handle, Win32.TTM_TRACKPOSITION, 0, (initialY << 16) | initialX); // and finally display it Win32.SendMessage(Handle, Win32.TTM_TRACKACTIVATE, 1, ref _toolInfo); DoLayout(Window, content, stemPosition, ref toolTipBounds); _contentPanel.MouseDown += delegate(object sender, MouseEventArgs e) { if (null != MouseDown && _mouseOverToolTip) { _mouseOverToolTip = true; MouseDown(this, e); } }; _contentPanel.MouseEnter += delegate(object sender, EventArgs e) { if (null != MouseEnter && !_mouseOverToolTip) { _mouseOverToolTip = true; MouseEnter(this, e); } }; _contentPanel.MouseLeave += delegate(object sender, EventArgs e) { // only send the event if the mouse has actually left the balloon and not simply moved from _contentPanel to the caller-supplied content if (null != MouseLeave && _mouseOverToolTip && null == _contentPanel.GetChildAtPoint(_contentPanel.PointToClient(Control.MousePosition))) { _mouseOverToolTip = false; MouseLeave(this, e); } }; }