Using Windows Forms
System.Windows.Forms is a .NET namespace that provides a set of classes for creating the GUI for Microsoft Windows applications.
As an alternative to the built-in Dyalog GUI, Windows Forms has been superseded by Windows Presentation Foundation. This page is included to support existing Dyalog applications that make use of Windows Forms.
Creating GUI Objects
GUI objects are represented by .NET classes in the System.Windows.Forms .NET namespace. In general, these classes correspond closely to the GUI objects provided by Dyalog, which are themselves based on the Windows API.
For example, to create a form containing a button and an edit field, you would create instances of the Form, Button, and TextBox classes.
Object Hierarchy
The most striking difference between the Windows.Forms GUI and the Dyalog GUI is that in Windows.Forms the container hierarchy represented by forms, group boxes, and controls is not represented by an object hierarchy. Instead, objects that represent GUI controls are created stand-alone (that is, without a parent) and then associated with a container, such as a Form, by calling the Add method of the parent’s Controls collection.
Windows.Forms objects are associated with APL symbols that are namespace references, but Windows.Forms objects do not have implicit names.
Positioning and Sizing Forms and Controls
The position of a form or a control is specified by its Location property, which is measured relative to the top left corner of the client area of its container.
Location has a data type of System.Drawing.Point. To set Location, you must first create an object of type System.Drawing.Point and then assign that object to Location.
Similarly, the size of an object is determined by its Size property, which has a data type of System.Drawing.Size. For this, you must create a System.Drawing.Size object before assigning it to the Size property of the control or form.
Objects also have Top(Y) and Left(X) properties that can be specified or referenced independently. These accept simple numeric values.
The position of a Form can instead be determined by its DesktopLocation property, which is specified relative to the taskbar. Another alternative is to set the StartPosition property whose default setting is WindowsDefaultLocation, which represents a computed best location.
Modal Dialog Boxes
Dialog Boxes are displayed modally to prevent the user from performing tasks outside of the dialog box.
To create a modal dialog box, you create a Form, set its BorderStyle property to FixedDialog, set its ControlBox, MinimizeBox, and MaximizeBox properties to false, and display it using ShowDialog.
A modal dialog box has a DialogResult property that is set when the Form is closed or when the user presses OK or Cancel. The value of this property is returned by the ShowDialog method, so the simplest way to handle user actions is to check the result of ShowDialog and proceed accordingly.
The examples in this section can be found in the [DYALOG]\Samples\winforms\WINFORMS.dws workspace.
Example 1
This example illustrates a simple modal dialog box.
Function EG1 illustrates how to create and use a simple modal dialog box. Much of the function is self-explanatory, but some points are noteworthy:
-
Lines
[1-2]set⎕USINGto include the .NET namespacesSystem.Windows.FormsandSystem.Drawing. -
Lines
[6,8,9]create aFormand twoButtonobjects. As yet, they are unconnected. The constructor for both classes is defined to take no arguments, so the⎕NEWsystem function is only called with a class argument. -
Lines
[14]shows how theLocationproperty is set by first creating a newPointobject with a specific pair of (xandy) values. -
Lines
[18]computes the values for thePointobject forbutton2.Location, from the values of theLeft,Height, andTop<properties ofbutton1; thus positioningbutton2relative tobutton1.
∇ EG1;form1;button1;button2;true;false;⎕USING;Z
[1] ⎕USING←,⊂'System.Windows.Forms, System.Windows.Forms.dll'
[2] ⎕USING,←⊂'System.Drawing,System.Drawing.dll'
[3] true false←1 0
[4]
[5] ⍝ Create a new instance of the form.
[6] form1←⎕NEW Form
[7] ⍝ Create two buttons to use as the accept and cancel btns
[8] button1←⎕NEW Button
[9] button2←⎕NEW Button
[10]
[11] ⍝ Set the text of button1 to "OK".
[12] button1.Text←'OK'
[13] ⍝ Set the position of the button on the form.
[14] button1.Location←⎕NEW Point,⊂10 10
[15] ⍝ Set the text of button2 to "Cancel".
[16] button2.Text←'Cancel'
[17] ⍝ Set the position of the button relative to button1.
[18] button2.Location←⎕NEW Point, ⊂button1.Left button1. (Height+Top+10)
[19] -
Lines
[21,23]sets theDialogResultproperty ofbutton1andbutton2toDialogResult.OKandDialogResult.Cancelrespectively.DialogResultis an enumeration with a predefined set of member values. -
Similarly, lines
[32]defines theBorderStyleproperty of the form using theFormBorderStyleenumeration. -
Lines
[38 40]defines theAcceptButtonandCancelButtonproperties of theFormtobutton1andbutton2respectively. These have the same effect as the Dyalog GUI Default and Cancel properties. -
Lines
[42]sets theStartPositionof the Form to be centre screen. This is specified using an enumeration;FormStartPosition.
[20] ⍝ Make button1's dialog result OK.
[21] button1.DialogResult←DialogResult.OK
[22] ⍝ Make button2's dialog result Cancel.
[23] button2.DialogResult←DialogResult.Cancel
[24]
[25]
[26] ⍝ Set the title bar text of the form.
[27] form1.Text←'My Dialog Box'
[28] ⍝ Display a help button on the form.
[29] form1.HelpButton←true
[30]
[31] ⍝ Define border style of form to that of a dialog box.
[32] form1.BorderStyle←FormBorderStyle.FixedDialog
[33] ⍝ Set MaximizeBox to false to remove the maximize box.
[34] form1.MaximizeBox←false
[35] ⍝ Set MinimizeBox to false to remove the minimize box.
[36] form1.MinimizeBox←false
[37] ⍝ Set the accept button of the form to button1.
[38] form1.AcceptButton←button1
[39] ⍝ Set the cancel button of the form to button2.
[40] form1.CancelButton←button2
[41] ⍝ Set start position of the form to centre of the screen.
[42] form1.StartPosition←FormStartPosition.CenterScreen
[43]
-
Lines
[45 46]associate the buttons with theForm. TheControlsproperty of theFormreturns an object of typeForm.ControlCollection. This class has anAddmethod that is used to add a control to the collection of controls that are owned by theForm. -
Lines
[50]calls theShowDialogmethod (with no argument, hence the⍬). The result is an object of typeForm.DialogResult, which is an enumeration. -
Lines
[52]compares the result returned byShowDialogwith the enumeration memberDialogResult.OK(the primitive function=has been extended to compare objects).
[44] ⍝ Add button1 to the form.
[45] form1.Controls.Add button1
[46] ⍝ Add button2 to the form.
[47] form1.Controls.Add button2
[48]
[49] ⍝ Display the form as a modal dialog box.
[50] Z←form1.ShowDialog ⍬
[51] ⍝ Determine if the OK button was clicked on the dialog box.
[52] :If Z=DialogResult.OK
[53] ⍝ Display a message box saying that the OK button was clicked.
[54] Z←MessageBox.Show⊂'The OK button on the form was clicked.'
[55] :Else
[56] ⍝ Display a message box saying that the Cancel button was clicked.
[57] Z←MessageBox.Show⊂'The Cancel button on the form was clicked.'
[58] :EndIf
∇ Warning
The use of modal forms in .NET can lead to problematic situations while debugging. As the control is passed to .NET the APL interpreter cannot regain control in the event of an unforeseen error. Dyalog Ltd recommends changing the code to something like the following until the code is fully tested:
[52] form1.Visible←1
[53] :While form1.Visible ⋄ :endwhile Example 2
Functions EG2 and EG2A illustrate how the each operator (¨) and the extended namespace reference syntax in Dyalog can be used to produce more succinct, and no less readable, code:
∇ EG2;form1;label1;textBox1;true;false;⎕USING;Z
[1] ⎕USING←,⊂'System.Windows.Forms, System.Windows.Forms.dll'
[2] ⎕USING,←⊂'System.Drawing,System.Drawing.dll'
[3] true false←1 0
[4]
[5] ⍝ Create a new instance of the form.
[6] form1←⎕NEW Form
[7]
[8] textBox1←⎕NEW TextBox
[9] label1←⎕NEW Label
[10]
[11] ⍝ Initialize the controls and their bounds.
[12] label1.Text←'First Name'
[13] label1.Location←⎕NEW Point (48 48)
[14] label1.Size←⎕NEW Size (104 16)
[15] textBox1.Text←''
[16] textBox1.Location←⎕NEW Point (48 64)
[17] textBox1.Size←⎕NEW Size (104 16)
[18]
[19] ⍝ Add TextBox control to the form's control collection.
[20] form1.Controls.Add textBox1
[21] ⍝ Add Label control to the form's control collection.
[22] form1.Controls.Add label1
[23]
[24] ⍝ Display the form as a modal dialog box.
[25] Z←form1.ShowDialog ⍬
∇ In EG2A (an "improved" version of EG2), line [7] takes advantage of the fact that .NET classes are namespaces, so the expression Form TextBox Label is a vector of namespace references, and the expression ⎕NEW¨Form TextBox Label runs the ⎕NEW system function on each of them. Similarly, lines [10 11 12] combine the use of extended namespace reference and the each operator to set the Text, Location, and Size properties in several objects together:
∇ EG2A;form1;label1;textBox1;true;false;⎕USING;Z
[1] ⍝ Compact version of EG2 taking advantage of ref syntax and ¨
[2] ⎕USING←'System.Windows.Forms,System.Windows.Forms.dll'
[3] ⎕USING,←⊂'System.Drawing,System.Drawing.dll'
[4] true false←1 0
[5]
[6] ⍝ Create a new instance of the form, TextBox and Label.
[7] (form1 textBox1 label1)←⎕NEW¨Form TextBox Label
[8]
[9] ⍝ Initialize the controls and their bounds.
[10] (label1 textBox1).Text←'First Name' ''
[11] (label1 textBox1).Location←⎕NEW¨Point,¨⊂¨(48 48)(48 64)
[12] (label1 textBox1).Size←⎕NEW¨Size,¨⊂¨(104 16)(104 16)
[13]
[14] ⍝ Add Label and TextBox controls to the form's control collection.
[15] form1.Controls.AddRange⊂label1 textBox1
[16]
[17] ⍝ Display the form as a modal dialog box.
[18] Z←form1.ShowDialog ⍬
∇ Non-Modal Forms
Non-modal forms are displayed using the Run method of the System.Windows.Forms.Application object. This method is designed to be called once, and only once, during the life of an application, which seems problematic for during APL development. Fortunately, in practice the restriction is that Application.Run can only be run once on a single system thread but it can be run successively on different system threads. During development, you can, therefore, test a function that calls Application.Run by running it on a new APL thread using spawn (&) see Threading for further details.
There are several examples of non-modal forms in [DYALOG]\Samples:
-
DataGrid Examples
Three functions in the [DYALOG]\Samples\winforms\WINFORMS.dws workspace provide examples of non-modal forms. These examples also illustrate the use of theWinForms.DataGridclass.-
Function
Grid1is an APL translation of the example given in the help file for theDataGridclass in the .NET SDK Beta1. The original code has been slightly modified to work with the current version of the SDK. -
Function
Grid2is an APL translation of the example given in the help file for theDataGridclass in the .NET SDK Beta2. -
Function
Gridis an APL translation of the example given in the file:nonAPL C:\Program Files\Microsoft.NET\SDK\v1.1\... QuickStart\winforms\samples\Data\Grid\vb\Grid.vbThis example uses Microsoft SQL Server 2000 to extract sample data from the sample NorthWind database. To run this example, you must have SQL Server running and you must modify functionGrid_Loadto specify the name of your server.
-
-
GDIPLUS workspace
The [DYALOG]\Samples\winforms\GDIPLUS.dws workspace contains a sample that demonstrates the use of non-rectangular Forms. It is a direct translation into APL from a C# sample (WinForms-Graphics-GDIPlusShape) that was distributed on the Visual Studio .NET Beta 2 Resource CD. -
tetris workspace
The [DYALOG]\Samples\winforms\tetris.dws workspace contains a sample that demonstrates the use of graphics. It is a direct translation into APL from a C# sample (WinForms-Graphics-Tetris) that was distributed on the Visual Studio .NET Beta 2 Resource CD. -
webservices workspace
TheWFGOLFfunction in the [DYALOG]\Samples\asp.net\webservices\webservices.dws workspace performs the same task as theGOLFfunction in the same workspace, but it usesWindows.Formsinstead of the built-in Dyalog GUI.WFGOLFand its callback functionsWFBOOKandWFSSperform exactly the same task, with almost identical dialog box appearance, asGOLFand its callbacksBOOKandSS(described in Using GolfService from Dyalog).Information
When you run
WFGOLForGOLFfor the first time, you must supply an argument of1to force the creation of the proxy class for theGolfServiceweb service.