Creating the new form

You will create a new Windows Form that will be used in place of the base form. This new form will display both the content from the Dexterity-based window, as well as the additional controls you are adding.

Adding the new form

To add the new form, complete the following procedure:

  1. Add a new Windows Form to the project.

From the Project menu, choose Add Windows Form.

  1. Name the new form.

In the Add New Item window, name the new Windows Form. Click Add.

  1. View the code for the new form.

In the Solution Explorer, right-click on the form and choose View Code to display the code for the new form.

  1. Add a namespace reference for the form code.

Add a using statement to provide convenient access to the code in the Microsoft.Dexterity.Shell namespace.

using Microsoft.Dexterity.Shell;

  1. Specify the form inheritance.

By default, the class for the new form will inherit from the Form class. To be used as a form factory, it must inherit from the proper class in the Microsoft.Dexterity.Shell namespace. The inherited class depends on the window type of the Dexterity-based window for which the form factory is being created.

When you specify the inherited class from the Microsoft.Dexterity.Shell namespace, the Windows Form will be redrawn with window elements that match Microsoft Dynamics GP.


For instance, the following C# code shows the Windows Form class that will be used for the About Box form in Microsoft Dynamics GP. Notice how the form class inherits from the DexTaskForm class. The default constructor is also shown.

namespace FormFactorySample
{
	public partial class SampleForm : DexTaskForm
	{
		public SampleForm()
		{
			InitializeComponent();
	}
}
}

Adding a new form constructor

Add an additional constructor to instantiate the form that will contain both the Dexterity-based window content, as well as your new controls. You will call this constructor from the form factory class. The set of parameters for the constructor depends on the type of form.

For forms that inherit from the DexTaskForm class, the new constructor must have the following parameters:

[spacer]

Parameter

Type

Description

name

string

The display name for the Dexterity window.

windowType

DexWindowType

An enumeration that specifies the window type. The following values are possible:

Lookup

ModalDialog

ModlessDialog

Palette

Primary

Toolbar

Wizard

flags

FormFlags

A bitmask that specifies properties of the Dexterity window. The available flags are:

TNTClose

TNTDialog

TNTHGrow

TNTHScroll

TNTResize

TNTVGrow

TNTVScroll

windowState

WindowState

The initial appearance of the window.

minClientSize

System.Drawing.Size

Minimum size that the Dexterity window can be reduced to.

clientSize

System.Drawing.Size

The initial size that the Dexterity window will have. This value includes the standard window elements, such as the title bar.

hResizeable

bool

Specifies whether the window can be resized horizontally.

vResizeable

bool

Specifies whether the window can be resized vertically.

productId

short

The dictionary ID of the product that defines the Dexterity-based window.

formId

short

The form ID of the form resource that defines the Dexterity-based window.

windowId

short

The window ID of the window resource that defines the Dexterity-based window.

modified

bool

Indicates whether the form resource was retrieved from the forms dictionary for the product.


For forms that inherit from the DexDialogForm class, the new constructor must have the following parameters:

[spacer]

Parameter

Type

Description

name

string

The display name for the Dexterity window.

windowType

DexWindowType

An enumeration that specifies the window type. The following values are possible:

Lookup

ModalDialog

ModlessDialog

Palette

Primary

Toolbar

Wizard

flags

FormFlags

A bitmask that specifies properties of the Dexterity window. The available flags are:

TNTClose

TNTDialog

TNTHGrow

TNTHScroll

TNTResize

TNTVGrow

TNTVScroll

windowState

WindowState

The initial appearance of the window.

minClientSize

System.Drawing.Size

Minimum size that the Dexterity window can be reduced to.

productId

short

The dictionary ID of the product that defines the Dexterity-based window.

formId

short

The form ID of the form resource that defines the Dexterity-based window.

windowId

short

The window ID of the window resource that defines the Dexterity-based window.

modified

bool

Indicates whether the form resource was retrieved from the forms dictionary for the product.


Like the default constructor, the new constructor should call the InitializeComponent() method for the form.

As an example, the following C# code shows the additional constructor that will create the new Windows form to be used as the wrapper for the About Box window in Microsoft Dynamics GP.

public SampleForm(string name, DexWindowType windowType, FormFlags flags,
WindowState windowState, System.Drawing.Size minClientSize, System.Drawing.Size
clientSize, bool hResizeable, bool vResizeable, short productId, short formId,
short windowId, bool modified)
{
	InitializeComponent();
}

Creating the new form layout

Use Visual Studio’s graphical form designer to create the layout for the new form. When you view the form in the designer, you will see that it contains a “content panel” control into which you will add your controls. This control is added automatically by the form class inherited from the Microsoft.Dexterity.Shell namespace.

[spacer]

The new form layout must provide a control that will host the content from the Dexterity-based window. It must also contain the additional controls you are adding to the form. One basic way to accomplish this is through the SplitContainer control, which is a standard .NET control. Drag this control out from the Toolbox into the content panel. The left panel of the split container will host the Dexterity-based window content. The right panel of the split container will host the new controls you are adding. The following illustration shows the new form after the split container control was added.

[spacer]

You could use any of the other layout controls, such as the TableLayoutPanel, when defining the form layout. Which you choose will depend on your layout needs.

Setting the size of the form

The Dexterity runtime doesn’t know how large the new form with its additional controls will need to be to display properly. Code in your form factory must specify the size to accommodate the Dexterity-based content, as well as the new controls you have added. You must override the protected GetPreferredClientSize method to specify the size the new form will have. You are specifying the outside dimensions of the form, including the borders, title bar, etc. The value you return indicates the size the form will have.

The dexClientSize parameter passed in to this method contains the dimensions of the Dexterity-based content that the new form must host. You can also call the GetPreferredClientSize method from the form base class to get the outer dimensions of the base Dexterity window. Together, these values can be used to help you compute the size of the window.

The following example is the C# code that sets the size of the form that will display the About Box content, as well as some additional controls added for the form factory. The code is part of the class for the new form, located in the same class as the default constructor. It overrides the protected GetPreferredClientSize method. This example sets the total size of the window.

protected override Size GetPreferredClientSize(Size dexClientSize, DexWindowType
windowType, short productId, short formId, short windowId, bool modified,
bool apply)
{
	Size baseClassSize;
	if (apply)
	{
		// Store the size of the About Box content area
		AboutBoxSize = dexClientSize;

		// Query the base class to get the outer dimensions of the Dexterity window
		baseClassSize = base.GetPreferredClientSize(dexClientSize, windowType,
		productId, formId, windowId, modified, apply);

		// Add width for the splitter and new control area
		baseClassSize.Width += (splitContainer1.SplitterWidth + 150);

		return baseClassSize;
}
	else
	{
		return base.GetPreferredClientSize(dexClientSize, windowType, productId,
		formId, windowId, modified, apply);
}
}

The position of the splitter that divides the Dexterity-based window content from the .NET content must also be specified. This can be done in an override for the protected OnResize method for the base class. Typically, the position can be set to the width of the inner content area for the Dexterity-based window.

protected override void OnResize(EventArgs e)
{
	// Call OnResize for the base class
	base.OnResize(e);

	// When the window is resized, set the position of the splitter
	try
	{
		if (splitContainer1 != null)
		{
			// Use the value of the inner content of the Dexterity-based
			// window, saved from the GetPreferredClientSize method.
			splitContainer1.SplitterDistance = AboutBoxSize.Width;
			splitContainer1.IsSplitterFixed = true;
	}
}
	catch (ArgumentOutOfRangeException)
	{
		// Invalid size specified -- Ignore the error
}
}

Specifying the Dexterity-based content host

You must specify which control on your form will host the Dexterity-based window content. You do this by overriding the protected DexHostContainer method. The method must return the control to be used so the Dexterity runtime can display the content.

The following example is the C# code that specifies the left panel of the SplitContainer control will be used to host the Dexterity-based window content. The code is part of the class for the new form, located in the same class as the default constructor. It overrides the protected DexHostContainer method.

protected override Control DexHostContainer
{
	get
	{
		return splitContainer1.Panel1;
}
}

Adding additional controls

You can add additional controls to the new form simply by dragging them out from the Toolbox, just as you would any other .NET application.

If your code must interact with the Dexterity-based content (such as setting or retrieving window fields, or accessing the table buffers for the form) you can do this using techniques from Visual Studio Tools. You will need to include references to the Microsoft.Dexterity.Bridge assembly, as well as the application assembly for each dictionary whose resources you want to access. Often, this will be the application assembly for the Dynamics dictionary. You can register for Visual Studio Tools events in the form factory class. Refer to the Visual Studio Tools Programmer’s Guide for more information.

It’s important when writing code for the form that you handle any exceptions your code could generate. If you don’t handle the exceptions, they will be passed to the Dynamics runtime as unhandled exceptions, causing the application to shut down.


Complete form example

The following C# code is the complete form code for the new form used to add additional controls to the About Box window in Microsoft Dynamics GP.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Dexterity.Shell;

namespace FormFactorySample
{
	public partial class SampleForm : DexTaskForm
	{
		static Size AboutBoxSize;

		public SampleForm()
		{
			InitializeComponent();
	}

		public SampleForm(string name, DexWindowType windowType, FormFlags flags,
		WindowState windowState, System.Drawing.Size minClientSize,
		System.Drawing.Size clientSize, bool hResizeable, bool vResizeable,
		short productId, short formId, short windowId, bool modified)
		{
			InitializeComponent();
	}

		protected override Size GetPreferredClientSize(Size dexClientSize,
		DexWindowType windowType, short productId, short formId, short windowId,
		bool modified, bool apply)
		{
			Size baseClassSize;
			if (apply)
			{
				// Store the size of the About Box content area
				AboutBoxSize = dexClientSize;

				// Query the base class to get the outer dimensions of the Dexterity
				// window
				baseClassSize = base.GetPreferredClientSize(dexClientSize, windowType,
				productId, formId, windowId, modified, apply);

				// Add width for the splitter and new control area
				baseClassSize.Width += (splitContainer1.SplitterWidth + 150);

				return baseClassSize;
		}
			else
			{
				return base.GetPreferredClientSize(dexClientSize, windowType,
				productId, formId, windowId, modified, apply);
		}
	}

		protected override void OnResize(EventArgs e)
		{
			// Call OnResize for the base class
			base.OnResize(e);

			// When the window is resized, set the position of the splitter
			try
			{
				if (splitContainer1 != null)
				{
					// Use the value of the inner content of the Dexterity-based
					// window, saved from the GetPreferredClientSize method.
					splitContainer1.SplitterDistance = AboutBoxSize.Width;
					splitContainer1.IsSplitterFixed = true;
			}
		}
			catch (ArgumentOutOfRangeException)
			{
				// Invalid size specified -- Ignore the error
		}
	}

		protected override Control DexHostContainer
		{
			get
			{
				return splitContainer1.Panel1;
		}
	}

		private void button1_Click(object sender, EventArgs e)
		{
			MessageBox.Show("This is .NET code");
	}
} 
}


Documentation Feedback