I'm pretty sure all of you, who are using Windows Vista, have come along this new control:

It's called "Command Link" and it is used across many of the new wizards and dialogs included for Windows Vista. I was wondering how to include such controls in an own Windows Forms application (as for WPF I could just simply template a button).

While researching, I found out, that this command-link-button is a simple Win32 button restyled with a new button style (BS_COMMANDLINK). As Windows Forms buttons also wrap classic Win32 buttons, it is possible to restyle one of these for a command link button.

All you have to do is set the FlatStyle of the button to System and apply the BS_COMMANDLINK style to the Style property of the CreateParams of the button.

    public class CommandLink:Button
    {
        const int BS_COMMANDLINK = 0x0000000E;

        public CommandLink()
        {
            this.FlatStyle = FlatStyle.System;
        }


        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cParams = base.CreateParams;
                cParams.Style |= BS_COMMANDLINK;
                return cParams;
            }
        }
    }

This will produce a basic command link, as shown above, including a text, but now description. To set a description text, you've got to send a special button WindowMessage BCM_SETNOTE:

  SendMessage(new HandleRef(this, this.Handle),
    BCM_SETNOTE,
    IntPtr.Zero, "Note text");

Getting the content of the note text requires to messages BCM_GETNOTELENGTH, returning the length of the note, and BCM_GETNOTE, querying n+1 characters of the note text.

  int length = SendMessage(new HandleRef(this, this.Handle),
    BCM_GETNOTELENGTH,
    IntPtr.Zero, IntPtr.Zero) + 1;

  StringBuilder sb = new StringBuilder(length);

  SendMessage(new HandleRef(this, this.Handle),
    BCM_GETNOTE,
    ref length, sb);

  return sb.ToString();

Finally you can also switch the default icon of the command link to a shield, to indicate an administrative operation.

To establish this, you can also use a message, BCM_SETSHIELD (but you have to remember the current value of it, as there is no BCM_GETSHIELD,..)

  SendMessage(new HandleRef(this, this.Handle), BCM_SETSHIELD, 
    IntPtr.Zero, true);

I created properties to wrap these two messages, and packed it all up into a custom WinForms control! With this, all you need to do is drop a CommandLink into your form and set the properties to create forms like this:

Feel free to download the CommandLink control source included as attachment!