TL;DR

  • CoolTip source code and read-me at github.
  • CoolTip component at nuget.

The Idea

My general idea was to place tip window under the hovered control, but not just near the cursor. Also I wanted to draw tip in a little bit another way. So, to do this I need:

  • override tip appearance location (window position);
  • override tip boundaries (window size);
  • override tip drawing.

I don’t want to say that this idea was only my, I saw it some application and I like it 😊

The Journey

From development point of view, to make custom behavior for tool tips in WinForms we have 3 ways:

  • use standard class and try to override it’s behavior with component-provided events and properties;
  • reuse original source code to add needed functionality;
  • implement own component with needed behavior.

And I tried all of them and the result looks very exciting 😃

We cannot inherit and try to completely override class behavior with language-given possibilities because there’s no virtual functions exist to override.

ToolTip Events

ToolTip component propose to us instruments to customize it’s behavior, including:

  • it’s size, but not position (which is really hard to understand to me why?);
  • it’s content, i.e. custom drawing.

ToolTip.Popup event gives us event arguments with the following useful properties:

  • AssociatedWindow - possibly the tip window itself. But no, this is the window of the control which the tip belongs to, i.e. HWND of the AssociatedControl.
  • AssociatedControl - the control which the tip belongs to.
  • ToolTipSize - the size of tip window. But from this size component gets only Width property, and ignoring everything else.
  • Cancel if we want to cancel tip appearance.

You can check the source for ToolTip.Popup call.

ToolTip.Draw provide very similar arguments, but also some functions to draw (predefined) contents. It’s call yon can check here in the sources.

ToolTip Class

It’s a mess. It totally relies on the Windows functionality of systems hints. However, I even reached some success in this way. It would be okay, but I faced with direct usage of ToolTip class in other controls, and not in a way of OS usage: ToolStrip, Label, DataGridView, etc.

And, if you want to make it workable you need to copy a lot of .Net internals, especially native imports and marshaling.

Own Implementation

Generally I decide to make it extendable, i.e. add possibility to add support for any other complex controls, and custom too.

Two main API’s for this purpose:

  • IVisitor gives possibility to decompose complex controls into parts or items: ListViewListViewItem;
  • then IManager gives you control for item bounds and tool tip text.

While component have no connection to the form that it is placed on, we need to setup proper form into the BaseForm property. Form controls bypass algorithm I copied from original ToolTip component and narrow it to only needed functionality.

Detailed how-to you can find on github.