Try OpenEdge Now
skip to main content
GUI for .NET Programming
Accessing and Managing .NET Classes from ABL : Handling .NET events : Event handling example
 

Event handling example

The following procedure, EventHandlers.p, displays a form and draws or erases an octagon defined by a series of points that can change their locations depending on the following conditions:
*When the form (Octagons) that displays the octagon first opens.
*Whenever you click the Draw button (using a visible graphical pen color).
*Whenever you click the Erase button (using an invisible graphical pen color, the background color).
*Whenever the Octagons form is moved.
*Whenever the Octagons form is painted on the screen. Painting occurs when the form is first opened, whenever the form is resized, and when other forms and windows are dragged across the top of the Octagons form. (Painting, however, does not occur in the same way when the form is moved, which is why the form draws the octagon explicitly when it is moved.)
For information on locating and running this sample, see Example procedures.
Thus, the octagon displayed by EventHandlers.p continues to appear when its window is moved or stretched.
The points used to draw the octagon are maintained in a .NET array whose values are recalculated as necessary to allow the octagon to fit within the dimensions of the form client area. Another procedure example, PointerArray.p, is a simpler version of the same application. It performs the same octagon calculations and array operations in order to demonstrate the use of .NET array objects in ABL. (The difference between this EventHandlers.p example and PointerArray.p is that PointerArray.p draws the octagon only when you click a Draw button.) Therefore, for more information on the point calculations and array operations used in EventHandlers.p, see Example: Accessing a .NET array.
EventHandlers.p draws the octagon for all of the listed conditions by handling events on either the form or its buttons. It thus responds to all of these conditions by drawing the octagon for each of the following events:
*Click event on the rDrawBtn object
*Click event on the rEraseBtn object
*Move event on the rForm object
*Paint event on the rForm object
This is the mainline of EventHandlers.p, showing the code for UI initialization, event handler subscription, UI launch (displaying the form and blocking to handle the events), and procedure cleanup.
USING System.Windows.Forms.*  FROM ASSEMBLY.
USING Infragistics.Win.Misc.* FROM ASSEMBLY.
DEFINE VARIABLE rPointArray AS CLASS "System.Drawing.Point[]" NO-UNDO.
DEFINE VARIABLE rArray      AS CLASS System.Array             NO-UNDO.
DEFINE VARIABLE rPoint      AS CLASS System.Drawing.Point     NO-UNDO.
DEFINE VARIABLE rDrawBtn    AS CLASS UltraButton              NO-UNDO.
DEFINE VARIABLE rEraseBtn   AS CLASS UltraButton              NO-UNDO.
DEFINE VARIABLE rForm       AS CLASS Progress.Windows.Form    NO-UNDO.
DEFINE VARIABLE enColor     AS CLASS System.Drawing.Color     NO-UNDO.
DEFINE VARIABLE sqrt2       AS DECIMAL                        NO-UNDO.
DEFINE VARIABLE idx         AS INTEGER                        NO-UNDO.

FUNCTION AdjustOctagon RETURNS "System.Drawing.Point[]" FORWARD.

/* Create .NET Point array and a Point object to set its element values */
ASSIGN
  rPoint      = NEW System.Drawing.Point(0, 0)
  rArray      = System.Array:CreateInstance(rPoint:GetType( ), 8)
  rPointArray = CAST(rArray, "System.Drawing.Point[]").

/* Prepare UI to draw octagons */
ASSIGN
 rDrawBtn             = NEW UltraButton( )
  rDrawBtn:AutoSize     = TRUE
  rDrawBtn:Text         = "Draw"
  rDrawBtn:DialogResult = DialogResult:None
  rDrawBtn:Top          = 4
  rDrawBtn:Left         = 4.

ASSIGN
 rEraseBtn              = NEW UltraButton( )
  rEraseBtn:AutoSize     = TRUE
  rEraseBtn:Text         = "Erase"
  rEraseBtn:DialogResult = DialogResult:None
  rEraseBtn:Top          = 4
  rEraseBtn:Left         = 10 + (rDrawBtn:Width / 2).

ASSIGN
 rForm        = NEW Progress.Windows.Form( )
  rForm:Height = 300
  rForm:Width  = 300
  rForm:Text   = "Octagons".

rForm:Controls:Add(rDrawBtn).
rForm:Controls:Add(rEraseBtn).

ASSIGN
  sqrt2   = SQRT( 2.0 ) /* "Constant" needed to draw octagons */
  enColor = System.Drawing.Color:Black. /* Initial pen color */

/* Event handlers that draw and redraw the octagon */
rEraseBtn:Click:Subscribe("FormErase").
rDrawBtn:Click:Subscribe("FormDraw").
rForm:Move:Subscribe("FormMoveAndPaint").
rForm:Paint:Subscribe("FormMoveAndPaint").

WAIT-FOR rForm:ShowDialog( ).

rForm:Dispose( ).
The WAIT-FOR statement invokes the ShowDialog( ) method to display the form as a modal dialog box and block for all events, including the button Click event to draw or erase the octagon. Closing the form then terminates the WAIT-FOR statement. For more information on this syntax for the WAIT-FOR statement, see Creating and Using Forms and Controls.
The effect is that clicking the Draw button makes the octagon visible and clicking the Erase button makes the octagon invisible, and the octagon continues to be visible or invisible while it changes its size, shape, and screen position as you resize or move the form until you click the other button.
Note: This effect works best if you set your Windows display properties so that Windows shows the contents of all windows when they are dragged. On Windows XP, you can find this setting by clicking the Effects button on the Appearance tab shown for the Display settings applet in the Control Panel.
So, EventHandlers.p uses an Erase button to erase the octagon and a Draw button to draw the octagon. In addition, it adds event handlers to maintain display of the form every time you change the form size or position. The event handlers ensure that all octagons remain erased once the Erase button is clicked or continue to be drawn once the Draw button is clicked. The octagons start out in a drawn state by initializing a System.Drawing.Color enumeration variable (enColor) with the Black enumeration member.
The Draw internal procedure is similar to the Draw internal procedure for the PointArray.p example described in Example: Accessing a .NET array. The difference in the version coded for EventHandlers.p is that this Draw procedure is not, itself, an event handler and therefore does not have event handler parameters.
PROCEDURE Draw:
  /* Draw octagon from point array */
  DEFINE VARIABLE rGraphics AS CLASS System.Drawing.Graphics NO-UNDO.
  DEFINE VARIABLE rPen      AS CLASS System.Drawing.Pen      NO-UNDO.

  ASSIGN
    rGraphics  = rForm:CreateGraphics( )
    rPen       = NEW System.Drawing.Pen(enColor)
    rPen:Width = 2.

  /* Pass adjusted point array to .NET method to draw octagon */
  rGraphics:DrawPolygon( rPen, AdjustOctagon( ) ).
END PROCEDURE.
Instead, this Draw procedure is called by the different event handlers in order to draw the octagon using the current pen color specified by enColor, which determines whether the octagon is actually drawn or erased.
The procedure continues with the same AdjustOctagon user-defined function and CalcOctagonSide internal procedure that are defined for PointArray.p.
FUNCTION AdjustOctagon RETURNS "System.Drawing.Point[]":
  ...
END FUNCTION.

PROCEDURE CalcOctagonSide:
  ...
END PROCEDURE.
This function and internal procedure implement the algorithm for calculating the points required to draw the octagon given the current dimensions of the form client area. For more information, see the description of these routines in Example: Accessing a .NET array.
Finally, EventHandlers.p defines its event handlers.
PROCEDURE FormErase:
  DEFINE INPUT PARAMETER sender AS CLASS System.Object    NO-UNDO.
  DEFINE INPUT PARAMETER e      AS CLASS System.EventArgs NO-UNDO.

  enColor = rForm:BackColor.
  RUN Draw.
END PROCEDURE.

PROCEDURE FormDraw:
  DEFINE INPUT PARAMETER sender AS CLASS System.Object    NO-UNDO.
  DEFINE INPUT PARAMETER e      AS CLASS System.EventArgs NO-UNDO.

  enColor = System.Drawing.Color:Black.  RUN Draw.
END PROCEDURE.

PROCEDURE FormMoveAndPaint:
  DEFINE INPUT PARAMETER sender AS CLASS System.Object    NO-UNDO.
  DEFINE INPUT PARAMETER e      AS CLASS System.EventArgs NO-UNDO.

  RUN Draw.
END PROCEDURE.
The difference between FormErase and FormDraw event handlers is in the pen color setting. To "erase" octagons, they are simply drawn with the color of the form background, and to "draw" them, they are drawn with the color black. The FormMoveAndPaint event handler responds to both the Move and Paint events by redrawing the octagon uses the most recent setting of enColor.
Note that the delegates for the Move and Paint events specify different event handler signatures. You can see this from the C# signatures for the different delegates shown in the Microsoft .NET Framework documentation. For example, this is the declaration for the EventHandler delegate used to define the Move event:
public delegate void EventHandler (Object sender, EventArgs e)
And this is the declaration for the PaintEventHandler delegate used to define the Paint event:
public delegate void PaintEventHandler (Object sender, PaintEventArgs e)
However, because the event handler required by EventHandlers.p for both events calls the Draw procedure in exactly the same way, and does not require access to its event arguments parameter, EventHandlers.p can define a single event handler for both events using the same signature based on the common base class for all event arguments (System.EventArgs).