A hint about .NET WinForms controls ToolTips

By: John Kaster

Abstract: Delphi developers are familiar with the "hint" property of VCL controls. This article explains how .NET Extender Providers can be used to include ToolTips for .NET WinForms controls.

What's in a name?

The "hint" property of a Delphi control is called a "ToolTip" for controls in the Microsoft .NET framework. The ToolTip is the text that appears (usually in a yellow box with black text) when you hover over a given control with your mouse. For example, this image shows the tooltip "Please put your C# source code here".
WinForms ToolTip

In my article introducing BabelCode, I list the steps to build a WinForms client that calls the BabelCode web service. While writing that article (and the client), I noticed for the first time that the WinForms controls did not have a ToolTip property available in the designer. I thought that was strange, particularly since the ASP.NET components have a ToolTip property, but I decided to get the article announcing BabelCode published instead of finding out where the ToolTip property had gone.

I finished the article, published it, and promptly forgot about the missing ToolTips.

Extender providers

Today, I started learning more about .NET's "Extender Providers" because I wanted to implement one, and some text from the article on MSDN Implementing an Extender Provider caught my eye:

For example, Windows Forms has a ToolTip component that offers an extender property to other controls.

"Well, duh!" I said to myself. (Unfortunately, I say that to myself a lot.) I couldn't find tooltips for the WinForms controls because you need to drop this WinForms ToolTip component on the design surface, which is an Extender Provider that makes ToolTips available for the visual controls on the form.

Once I did that, the ToolTip property became available for the controls. In the image below, you can see ToolTip1 inside the component tray (the non-visual component container), and the new property available in the object inspector. For those of you more familiar with .NET, you might call the "object inspector" a "property grid" instead.
ToolTip Extender

Then, I selected the CSharpCode RichText box, and the DelphiCode RichText box, and set their tooltips. Here's the excerpts of the relevant code showing the end result. Note the lines that contain references to the ToolTip1 component.


unit WinFormBabelClient;

interface
...
type
  TWinForm = class(System.Windows.Forms.Form)
  {$REGION 'Designer Managed Code'}
  strict private
...
    CSharpCode: System.Windows.Forms.RichTextBox;
    DelphiCode: System.Windows.Forms.RichTextBox;
    ToolTip1: System.Windows.Forms.ToolTip;
...
implementation
...
procedure TWinForm.InitializeComponent;
begin
  Self.components := System.ComponentModel.Container.Create;
...
  Self.ToolTip1 := System.Windows.Forms.ToolTip.Create(Self.components);

  // 
  // CSharpCode
  // 
  Self.CSharpCode.Dock := System.Windows.Forms.DockStyle.Top;
  Self.CSharpCode.Font := System.Drawing.Font.Create('Courier New', 
    10, System.Drawing.FontStyle.Regular, 
    System.Drawing.GraphicsUnit.Point, (Byte(0)));
  Self.CSharpCode.Location := System.Drawing.Point.Create(0, 0);
  Self.CSharpCode.Name := 'CSharpCode';
  Self.CSharpCode.Size := System.Drawing.Size.Create(328, 168);
  Self.CSharpCode.TabIndex := 3;
  Self.CSharpCode.Text := '';
  Self.ToolTip1.SetToolTip(Self.CSharpCode, 
    'Please put your C# source code here');
  Self.CSharpCode.WordWrap := False;
  // 
  // DelphiCode
  // 
  Self.DelphiCode.Dock := System.Windows.Forms.DockStyle.Fill;
  Self.DelphiCode.Font := System.Drawing.Font.Create('Courier New', 
    10, System.Drawing.FontStyle.Regular, 
    System.Drawing.GraphicsUnit.Point, (Byte(0)));
  Self.DelphiCode.Location := System.Drawing.Point.Create(0, 194);
  Self.DelphiCode.Name := 'DelphiCode';
  Self.DelphiCode.Size := System.Drawing.Size.Create(328, 168);
  Self.DelphiCode.TabIndex := 4;
  Self.DelphiCode.Text := 'Translated Delphi code appears here';
  Self.ToolTip1.SetToolTip(Self.DelphiCode, 
    'The BabelCode translation of the C# code to Delphi goes here');
  Self.DelphiCode.WordWrap := False;
...

As you can see from the code above, the component being extended by the ToolTip provider is passed in as a parameter for the extender. This is how multiple components can be extended by using the same ToolTip provider. It's a powerful and elegant implementation.

Extender Providers are not visual controls, although they support extending visual controls. They allow you to introduce properties to existing controls. The MSDN article on writing a WinForms Extender Provider Sample provides much more detail on what they can do.

ECO Extenders

I originally became interested in Extender Providers seeing the ECO extender provider components. They enhance the existing Windows Forms controls in a variety of ways, including making .NET Button controls ECO model-aware so you can perform actions on the model without writing any code, and supporting drag and drop from one DataGrid to another to populate associations among persistent objects classes. You can see the ECO extenders on the Delphi 8 Architect component palette:
ECO Extenders

Conclusion

I hope you find this information about Extender Providers helpful, and the idea itself of interest. It's a great way to extend existing .NET controls to accomplish highly customized solutions, while retaining RAD productivity. It might not provide everything that Aspect Oriented Programming (AOP) is intended to do, but it does have the same flavor. This introduction to AOP summarizes it thus:

Aspect-Oriented Programming (AOP) complements OO programming by allowing the developer to dynamically modify the static OO model to create a system that can grow to meet new requirements.

This sounds like a good description for Extender Providers, doesn't it?

If you create any cool extender providers, be sure to let me know, or get paid for an article about it for BDN.



Server Response from: ETNASC03