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