Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

HintTextBox

0.00/5 (No votes)
15 May 2007 1  
Shows inline hint for a textbox. Useful in cases where the UI is small and has to fit many input controls.

Screenshot - HintTextBox_Form.pngScreenshot - HintTextBox_Form_Password.png

Introduction

Very often, we (UI designers) are in situations where we have to capture a large amount of information from the user in a single screen. In such cases, it seems impossible to add enough labels and textboxes in a single form due to space considerations and the dimensions of the form. Nowadays, we see many forms over the internet which solve this problem. The idea being "why not add the label to the textbox itself?" I.e., can't the textbox itself act as the label (caption) and capture User Input at the same time?

This aritcle tries to solve these kind of problems with the use of a custom made control which I have used in many of my commercial applications. Moreover, it is a straight out-of-the-box control with a custom UI Smart Tag Designer, which is very handy.

Background

In one of my applications, I was left with just enough space on the form to accommodate two text boxes. What I thought was why not use the ways similar to Internet web forms and add a textbox which can act as both a textbox as well as a label.

I quickly Googled and found some similar controls which solved my problem. Well, it seemed so,. The control which I used functioned like this:

  1. Embed a Label control in a TextBox.
  2. Toggle the visibility of the Label when it get and loses focus.

This seemed to be a cool trick, but what pushed me to write my own control was, why in God's world should I use a Label when only a string should ideally do the job?

I somehow completed the application and delivered it, but the quest to develop such a control was always rolling in the back of my mind. So there I was, left with an inquisitive mind and a need to develop such a control which I could use across all my applications, and that too with a Smart Tag Designer so as to quickly do the job of preparing the UI.

Control Code

Well, the control code is much simpler than it seems to be, though a little lengthy. You can browse through the source code in the Zip files above.

Idea

  • Add a property of type string and use it to swap with the Text property of base TextBox on getting and losing focus.
  • Use some swap variables to hold the values of the Forecolor and Text properties.

SmartTag Designer

This was a bit tough to configure, but with some initial problems, I found out that the Smart Tags are dependent on Smart Tag UI Designers which are inherited from the System.Windows.Forms.Design.ControlDesigner class present in the System.Design.dll assembly.

Every inherited class should have a DesignerActionListCollection member variable which holds the reference to a class which holds the properties which should be displayed in the SmartTag.

The actual class which contains the properties to display is the one which is inherited from the DesignerActionList class.

Anyways, this is a bit too tricky... here you go with the code:

/////////////////////////////////////////////////////////////////
// Designer for the HintTextBox control with support for a smart 
// tag panel.
// Must add reference to System.Design.dll
/////////////////////////////////////////////////////////////////
[System.Security.Permissions.PermissionSet(
        System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
internal class ColorLabelDesigner : System.Windows.Forms.Design.ControlDesigner
{
    private DesignerActionListCollection actionLists;

    // Use pull model to populate smart tag menu.
    public override DesignerActionListCollection ActionLists
    {
        get
        {
            if (null == actionLists)
            {
                actionLists = new DesignerActionListCollection();
                actionLists.Add(new HintTextBoxDesignerActionList (this.Component));
            }
            return actionLists;
        }
    }
}

//the above class (ColorLabelDesigner )acts as a connector 
//connecting the Control and its Smart Tag Designer UI

internal class HintTextBoxDesignerActionList : DesignerActionList
{
    HintTextBox _BaseControl;
    private DesignerActionUIService designerActionUISvc = null;

    public HintTextBoxDesignerActionList(IComponent component)
        : base(component)
    {
        try
        {
            _BaseControl = (HintTextBox)component;
            this.designerActionUISvc = 
              GetService(typeof(DesignerActionUIService)) as DesignerActionUIService;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    // Helper method to retrieve control properties. Use of 
    // GetProperties enables undo and menu updates to work properly.
    private PropertyDescriptor GetPropertyByName(String propName)
    {
        PropertyDescriptor prop;
        prop = TypeDescriptor.GetProperties(_BaseControl)[propName];
        if (null == prop)
            throw new ArgumentException(
                 "Matching property not found!",
                  propName);
        else
            return prop;
    }

    public bool IsPassword
    {
        get { return _BaseControl.IsPassword; }
        set
        {
            GetPropertyByName("IsPassword").SetValue(_BaseControl, value);
            _BaseControl.Multiline = false;
            this.designerActionUISvc.Refresh(this.Component);
        }
    }

    public bool MultiLine
    {
        get { return _BaseControl.Multiline; }
        set
        {
            GetPropertyByName("Multiline").SetValue(_BaseControl, value);
            _BaseControl.IsPassword = false;
            this.designerActionUISvc.Refresh(this.Component);
        }
    }

    public string Hint
    {
        get { return _BaseControl.Hint; }
        set
        {
            GetPropertyByName("Hint").SetValue(_BaseControl, value);
            this.designerActionUISvc.Refresh(this.Component);
        }
    }

    public string Name
    {
        get { return _BaseControl.Name; }
        set
        {
            GetPropertyByName("Name").SetValue(_BaseControl, value);
            this.designerActionUISvc.Refresh(this.Component);
        }
    }

    public Color HintColor
    {
        get { return _BaseControl.HintColor; }
        set
        {
            GetPropertyByName("HintColor").SetValue(_BaseControl, value);
            this.designerActionUISvc.Refresh(this.Component);
        }
    }

    public Color TextColor
    {
        get { return _BaseControl.TextColor; }
        set
        {
            GetPropertyByName("TextColor").SetValue(_BaseControl, value);
            this.designerActionUISvc.Refresh(this.Component);
        }
    }

    public HorizontalAlignment HintAlignment
    {
        get { return _BaseControl.HintAlignment; }
        set
        {
            GetPropertyByName("HintAlignment").SetValue(_BaseControl, value);
            this.designerActionUISvc.Refresh(this.Component);
        }
    }

    public override DesignerActionItemCollection GetSortedActionItems()
    {
        DesignerActionItemCollection items = new DesignerActionItemCollection();

        //Define static section header entries.
        items.Add(new DesignerActionHeaderItem("Design"));
        items.Add(new DesignerActionHeaderItem("Behaviour"));
        items.Add(new DesignerActionHeaderItem("Appearance"));

        //Boolean property for locking color selections.

        items.Add(new DesignerActionPropertyItem("IsPassword",
                         "Password Field", "Behaviour",
                         "Is it a password field ?"));
       items.Add(new DesignerActionPropertyItem("MultiLine",
                         "MultiLine", "Behaviour",
                         "Multiline Text Field"));
            items.Add(new DesignerActionPropertyItem("HintColor",
                             "Hint Color", "Appearance",
                             "Sets the Hint Text color."));
            items.Add(new DesignerActionPropertyItem("TextColor",
                             "Text Color", "Appearance",
                             "Sets the Text Color."));
            items.Add(new DesignerActionPropertyItem("HintAlignment",
                             "HintAlignment", "Appearance",
                             "Sets the Hint Alignment."));
            //This next method item is also added to the context menu 
            // (as a designer verb).
            
        items.Add(new DesignerActionPropertyItem("Name",
                         "Control Name", "Design",
                         "Sets the Control Name."));
        items.Add(new DesignerActionPropertyItem("Hint",
                        "Hint", "Design",
                        "Sets the Hint text."));

        items.Add(new DesignerActionMethodItem(this,
                             "DefaultColors", "Set Default Colors",
                             "Appearance",
                             "Sets default Hint and Text colors.",
                              true));

        return items;
    }
    public void DefaultColors()
    {
        this._BaseControl.HintColor = Color.Gray;
        this._BaseControl.TextColor = Color.Black;
        this.designerActionUISvc.Refresh(this.Component);
    }

All you now have to do is add the designer type attribute on top of the control class which we have prepared:

[Designer(typeof(ColorLabelDesigner))]
public class HintTextBox
Result

Screenshot - HintTextBox_Designer_3.png

For those who are trying to modify the SmartTag UI, don't forget to add a reference to System.Design.dll found here.

Screenshot - HintTextBox_AddReference.png

Using the Control

To use the control, first drag HintTextBox.dll on the the toolbar (any toolbar) and you should be able to see a control named "HintTextBox".

There you are.. ready to go.. drag and drop it on any form and use it as you like...

Just remember to use the InternalText property to access user input text instead of using the traditional Text property.

Screenshot - HintTextBox_Form_Code1.png

History

  1. Added the HintAlignment property.
  2. Rectified the source code to make the ForeColor property work.
  3. N.B.: New property name: TextColor.

  4. Modified the Smart Tag to add extra properties and categorical support for them.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here