A very interesting problem was proposed to me by Microsoft Partner, Dmitry Grigansky. The goal was to create a host designer and have an editable label control placed on it, having this article as a starting base:

http://msdn.microsoft.com/en-us/magazine/cc163634.aspx

With help from Dmitry, who relentlessly investigated the matter, here are the main steps for creating this project.

First of all, we create a VS 2010 Win forms project and make sure we set the project for .NET 4 , not .NET 4 Client profile.

Add a reference to System.Design and then create a form named ParentForm. This will be the form on which our Designer will be place.

Next, we create a form named DesignForm, which will be the actual area for the controls to be placed.

On the ParentForm we add this code:

public ParentForm()
{
InitializeComponent();
System.ComponentModel.Design.DesignSurface
ds = new System.ComponentModel.Design.DesignSurface();
ds.BeginLoad(typeof(DesignForm));
Control c = ds.View as Control;
c.Parent = this;
c.Dock = DockStyle.Fill;
}

 

Now, the DesignForm is a child of ParentForm.

We will now proceed to the creation of class EditableLabelDesigner derived from ControlDesigner

 

class EditableLabelDesigner : ControlDesigner 
{
private const int WM_LBUTTONDBLCLK = 0x0203;

public override void Initialize(IComponent
component)
{
base.Initialize(component);
}
 

     

 protected override void WndProc(ref
System.Windows.Forms.Message m)
{
if (m.Msg == WM_LBUTTONDBLCLK)
{
((EditableLabel)Control).ShowInplaceEditor();
}
base.WndProc(ref m);
}
}

 

The WndProc method will catch the WM_LBUTTONDBLCLK event and show the editable area on the label.

 

Next, create the custom control EditableLabel:

Add new user control EditableLabel

 

[Designer(typeof(EditableLabelDesigner))] 

public partial class EditableLabel : Label
{
public EditableLabel()
{
InitializeComponent();
}

private TextBox inplaceEditor;
private bool isRedrawn = false;
public TextBox InplaceEditor
{
get { return inplaceEditor; }
}

public bool IsRedrawn
{
get { return isRedrawn; }
set
{
if (value == true)
{
if (inplaceEditor != null)
{
Text = inplaceEditor.Text;
inplaceEditor.Visible = false;
}
}
isRedrawn = value;
}
}



protected override void OnPaint(PaintEventArgs e)
{
if (!isRedrawn)
{
IsRedrawn = true;
}
base.OnPaint(e);
}

public void ShowInplaceEditor()
{
isRedrawn = false;
if (inplaceEditor == null)
{
this.inplaceEditor = new TextBox();
inplaceEditor.Parent = this.Parent.Parent;
inplaceEditor.Multiline = true;
}


inplaceEditor.HideSelection = false;
inplaceEditor.AcceptsTab = true;
inplaceEditor.Text = this.Text;
inplaceEditor.Visible = true;
inplaceEditor.Location = new Point(this.Parent.Location.X
+ this.Location.X + 10, this.Parent.Location.Y + this.Location.Y
+ 32);
inplaceEditor.Size = new Size(this.ClientRectangle.Width
- 4, this.ClientRectangle.Height - 4);
inplaceEditor.Font = this.Font;
inplaceEditor.SelectAll();
inplaceEditor.BringToFront();
inplaceEditor.Focus();
}
}

In the ShowInplaceEditor, the TextBox is added to the DesignForm’s parent, so it will be editable. 

Finally, in the ParentForm constructor, we add the EditableLabel on the DesignFom:

 IDesignerHost idh = (IDesignerHost)ds.GetService(typeof(IDesignerHost));
IToolboxUser itu = (IToolboxUser)idh.GetDesigner(idh.RootComponent);
itu.ToolPicked(new ToolboxItem(typeof(EditableLabel)));

 

Make sure to put the ParentForm as the staring form of your project, and you’re done.

You can find the sample project here.