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