How to dynamically add a control without hard coding the control type in Visual C++ .NET 2003 or in Visual C++ 2005 (815779)



The information in this article applies to:

  • Microsoft Visual C++ 2005 Express Edition
  • Microsoft Visual C++ .NET (2003)

For a Microsoft Visual Basic .NET version of this article, see 311321.
For a Microsoft Visual C# .NET version of this article, see 815780.
This article refers to the following Microsoft .NET Framework Class Library namespaces:
  • System::Windows::Forms
  • System::ComponentModel
  • System::Collections
  • System::Reflection

IN THIS TASK

SUMMARY

This step-by-step article describes how to dynamically add a control to a form in Microsoft Visual C++ .NET 2003 or in Microsoft Visual C++ 2005 and how to respond to the events of the control.

This article describes how to use the Assembly method of the Form type object to retrieve the assembly information. This article also describes how to create the controls dynamically by using the CreateInstance method of the System::Reflection::Assembly class, and how to change the control properties dynamically.

This article also describes how to add event handlers to the controls, and how to respond to the user actions by using these event handlers.

Back to the top

Step-by-step example

This section describes how to create a Windows Forms Application project that demonstrates how to dynamically add a control to a form in Visual C++ .NET or in Visual C++ 2005, how to dynamically add event handlers for the controls that are created, and how to respond to the events of the control.
  1. Start Microsoft Visual Studio .NET 2003 or Microsoft Visual Studio 2005.
  2. On the File menu, point to New, and then click Project.
  3. Click Visual C++ Projects under Project Types, and then click Windows Forms Application (.NET) under Templates.

    Note In Visual Studio 2005, Visual C++ Projects is changed to Visual C++, and Windows Forms Application (.NET) is changed to Windows Forms Application.
  4. In the Name box, type CreateControls, and then click OK. By default, the Form1 form is created and opens in Design view.
  5. Add two Button controls and one ComboBox control to the Form1 form. You add controls dynamically to the top of Form1.
  6. For each control, change the Name and the Text properties as follows
    ControlName PropertyText Property
    button1btnAddControlAdd Control
    button2btnRemoveControlRemove Control
    comboBox1cboControlTypeSelect Control Type
  7. Right-click Form1, and then click View Code.
  8. Add the following code at the top of the Form1.h file after the using directives.
    using namespace System::Reflection;
  9. Paste the following code in the Form1 class after the control variable declarations.
    // Define the Controls and Control Object 
    private: System::Windows::Forms::TreeView *DynTreeview;
    private: System::Windows::Forms::TextBox *DynTextBox;
    private: System::Windows::Forms::ListBox *DynListBox;
    private: System::Windows::Forms::Control *ControlObject;
  10. Switch to Design view, and then double-click Form1 to position the insertion point at the first line of the Form1_Load event.
  11. Paste the following code in the Form1_Load event.
    // Add event handlers to the buttons and control names to the combo
    btnAddControl->Click += new System::EventHandler(this,btnAddControl_Click);
    btnRemoveControl->Click += new System::EventHandler(this,btnRemoveControl_Click);
    cboControlType->Items->Add(S"TreeView");
    cboControlType->Items->Add(S"ListBox");
    cboControlType->Items->Add(S"TextBox");
  12. Paste the following code before the Form1_Load event.
    private: void AddControl(String	*ControlName, String* ControlType)
    {
    	//get the assebly of the form and create a control instance
    	Type *typ = __typeof(Form);
    
    	Assembly* asmb = typ->Assembly;
    	ControlObject =	__try_cast<System::Windows::Forms::Control*>
    			(asmb->CreateInstance(ControlType));
    
    	//set control properties and add it to controls collection
    	ControlObject->Name = ControlName;
    	ControlObject->Location = System::Drawing::Point(20, 20);
    	Controls->Add(ControlObject);
    
    	//compare control type selected, change the properties, add event handlers accordingly
    	if (ControlType->EndsWith(S"TreeView"))
    	{
    		DynTreeview = __try_cast<System::Windows::Forms::TreeView *> (ControlObject);
    		DynTreeview->Width = 200;
    		DynTreeview->Height = 120;
    		DynTreeview->Nodes->Add(new TreeNode(S"Root"));
    		DynTreeview->Nodes->Add(S"FirstChild");
    		DynTreeview->Nodes->Add(S"SecondChild");
    		DynTreeview->ExpandAll();
    		DynTreeview->AfterSelect += new System::Windows::Forms::TreeViewEventHandler(this,DynTree_AfterSelect);
    	}
    	else if	(ControlType->EndsWith(S"ListBox"))
    	{
    		DynListBox = __try_cast<System::Windows::Forms::ListBox*>(ControlObject);
    		DynListBox->Width = 200;
    		DynListBox->Height = 120;
    		DynListBox->Items->Add(S"Apples");
    		DynListBox->Items->Add(S"Banana");
    		DynListBox->Items->Add(S"Oranges");
    		DynListBox->SelectedIndexChanged += new	System::EventHandler(this,DynCtrl_Event);
    	}
    	else if	(ControlType->EndsWith(S"TextBox"))
    	{
    		DynTextBox = __try_cast<System::Windows::Forms::TextBox	*>(ControlObject);
    		DynTextBox->Width = 200;
    		DynTextBox->Text = S"Dynamically Added Textbox.";
    		DynTextBox->DoubleClick	+= new System::EventHandler(this,DynCtrl_Event);
    	}
    }
    private: void btnAddControl_Click(Object* sender, System::EventArgs* e)
    {
    	String* CtrlType;
    
    	if (!(ControlObject == NULL))
    	{
    		btnRemoveControl->PerformClick();
    	}
    
    	if (cboControlType->SelectedIndex < 0)
    	{
    		MessageBox::Show(S"Select a Control Type to add.");
    		return;
    	}
    
    	CtrlType = String::Concat(S"System.Windows.Forms.",cboControlType->SelectedItem->ToString());
    	this->AddControl(S"myControl", CtrlType);
    }
    
    private: void DynCtrl_Event(Object* sender, System::EventArgs* e)
    {
    	if (sender->GetType()->ToString()->EndsWith(S"ListBox"))
    	{
    		MessageBox::Show(String::Concat(S"The item you selected is: " , DynListBox->SelectedItem->ToString()));
    	}
    	else if (sender->GetType()->ToString()->EndsWith(S"TextBox"))
    	{
    		Clipboard::SetDataObject(DynTextBox->Text);
    		MessageBox::Show(S"The Text is copied to the clipboard.");
    	}
    }
    
    private: void btnRemoveControl_Click(Object* sender, System::EventArgs* e)
    {
    	this->Controls->Remove(ControlObject);
    	ControlObject = NULL;
    }
    
    private: void DynTree_AfterSelect(Object* sender, System::Windows::Forms::TreeViewEventArgs* e)
    {
    	MessageBox::Show(String::Concat("The Node you clicked on is: ", e->Node->Text));
    }
    Note You must add the common language runtime support compiler option (/clr:oldSyntax) in Visual C++ 2005 to successfully compile the previous code sample. To add the common language runtime support compiler option in Visual C++ 2005, follow these steps:
    1. Click Project, and then click <ProjectName> Properties.

      Note <ProjectName> is a placeholder for the name of the project.
    2. Expand Configuration Properties, and then click General.
    3. Click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project setting in the right pane, click Apply, and then click OK.
    For more information about the common language runtime support compiler option, visit the following Microsoft Web site:

    /clr (Common Language Runtime Compilation)
    http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

  13. Press the CTRL+SHIFT+S key combination to save the project.
  14. Press the CTRL+SHIFT+B key combination to build the project.
  15. Press the CTRL+F5 key combination to run the application. The application runs, and Form1 appears.
  16. In the combo box, click TreeView, and then click Add Control.

    Note A new TreeView control is added.
  17. Click any node to test the AfterClick event of the TreeView control.
  18. Click Remove Control to remove the TreeView control from the Form1 window.
  19. Test the application for the other controls that are listed in the combo box.
Back to the top

Code discussion

  • In this sample, the ComboBox control contains the list of control types that you add dynamically. You populate this list in the Load event of the form.
  • You declared three specific control objects in the initial statements of the definition for Form1 so that you can use the individual functionality of these control objects in your program. By declaring specific control types, you can also access Microsoft IntelliSense while you are programming.
  • In the btnAddControl_Click event handler, determine if another control is already loaded. If another control is loaded, remove the existing control and then add the new control that was selected in the combo box. Make sure that the combo box has a valid selection. If the selection is not valid, the program generates a message box and exits the event handler without processing more statements. If the selection is valid, call the AddControl method with appropriate parameters.
  • In the AddControl method, the __typeof(Form) statement returns the type object of the Form type. You use the Assembly method of this object to retrieve an instance of the assembly where the Form class is defined. After getting the assembly instance, the asmb object is created. You use the CreateInstance method of the asmb object with a ControlType string parameter to create an instance of the control. After the control is created, you add it to the current form by using the Controls->Add method. Then, by using the EndsWith method of the String class, you check the type of control that is passed to this procedure as the second argument. Depending on the control type, you set the individual properties of the control in the if...else...if... block. You use the += operator to connect the specific event of the dynamically-added control with the event handler. For ListBox and TextBox controls, you connected the SelectedIndexChanged and the DoubleClick events with the DynCtrl_Event event handler. For the TreeView control, you used a separate event handler (DynTree_AfterSelect) to connect the control with the AfterSelect event of the TreeView control.
  • The event handler for the TreeView control requires a different signature from that of the other two controls. The second argument in the DynTree_AfterSelect event handler is of type System::Windows::Forms::TreeViewEventArgs; for the DynCtrl_Event event handler, you use type System::EventArgs. The System::Windows::Forms::TreeViewEventArgs type provides additional information, such as the properties of the selected node.
Back to the top

REFERENCES

For more information about adding a control on a form if the control type is hard coded, visit the following Microsoft Developer Network (MSDN) Web site:For more information about event handlers, visit the following MSDN Web site:Back to the top

Modification Type:MajorLast Reviewed:1/4/2006
Keywords:kbWindowsForms kbTreeView kbMessageBox kbListBox kbide kbForms kbEditCtrl kbCtrlCreate kbCtrl kbControl kbComboBox kbButton kbEvent kbHOWTOmaster KB815779 kbAudDeveloper