Try OpenEdge Now
skip to main content
Programming Interfaces
External Program Interfaces : Shared Library and DLL Support : Code samples : Examples of static access to a shared library
 
Examples of static access to a shared library
The following examples show several variations on the use of the PROCEDURE and DEFINE PARAMETER statements for static access to a shared library.
In this example, the ABL MESSAGE statement displays a message in an alert box. It then calls the MessageBoxA routine from user32.dll to display the same message in an identical alert box, as shown:
i-dllex1.p
/* i-dllex1.p */

DEFINE VARIABLE iResult AS INTEGER NO-UNDO.

MESSAGE " It's a whole new world!"
VIEW-AS ALERT-BOX MESSAGE BUTTONS OK TITLE "ABL DLL Access".

RUN MessageBoxA (0, " It's A Whole New World!",
"ABL DLL Access - from the DLL!", 0, OUTPUT iResult).

PROCEDURE MessageBoxA EXTERNAL "user32.dll":
  DEFINE INPUT PARAMETER hwnd    AS LONG.
  DEFINE INPUT PARAMETER mbtext  AS CHARACTER.
  DEFINE INPUT PARAMETER mbtitle AS CHARACTER.
  DEFINE INPUT PARAMETER style   AS LONG.
  DEFINE RETURN PARAMETER result AS LONG.
END.
The following procedure uses the sndPlaySoundA routine from winmm.dll. The procedure allows the user to select a sound to play and then invokes the DLL routine to play the sound. The DLL routine takes two input parameters and returns a status code, as shown:
i-dllex2.p
DEFINE VARIABLE wave-name   AS CHARACTER NO-UNDO INITIAL ?.
DEFINE VARIABLE play-status AS INTEGER   NO-UNDO.

SYSTEM-DIALOG GET-FILE wave-name
TITLE "Choose the Sound"
FILTERS "Wave Files (*.wav)" "*.wav"
MUST-EXIST USE-FILENAME.

RUN sndPlaySoundA (INPUT wave-name, INPUT 2, OUTPUT play-status).

PROCEDURE sndPlaySoundA EXTERNAL "winmm.dll":
DEFINE INPUT PARAMETER ic   AS CHARACTER.
DEFINE INPUT PARAMETER ish  AS LONG.
DEFINE RETURN PARAMETER osh AS LONG.
END PROCEDURE.
Note: You must have a sound driver installed on your machine to play sounds.
The following code sample demonstrates calling the C library function atoi to get the value of the character form of an integer:
DEFINE VARIABLE in-string AS MEMPTR  NO-UNDO.
DEFINE VARIABLE out-int   AS INTEGER NO-UNDO.

ASSIGN
  SET-SIZE(in-string)      = 10
  PUT-STRING(in-string, 1) = "150".

RUN atoi (INPUT in-string, OUTPUT out-int).
MESSAGE "ATOI RESULT: " out-int VIEW-AS ALERT-BOX.

PROCEDURE atoi EXTERNAL "/usr/lib/libc.so.1":
  DEFINE INPUT  PARAMETER b       AS MEMPTR.
  DEFINE OUTPUT PARAMETER ret-val AS SHORT.
END PROCEDURE.
The declaration of the C function being called looks like this:
int atoi(const char *str)
The following procedure defines and displays a shaded ellipse in the current window using DLL functions from the Windows graphics library. This requires initialization of a small structure (ElipRegion).
Note that ABL has no knowledge of any graphics that you create using DLLs. You must ensure that ABL does not refresh the window you are using while the graphics are displayed. Otherwise, the graphics disappear during a window system refresh. (You can help to mitigate this by providing a graphics refresh option within your OpenEdge application.) The i-dllex3.p procedure displays a preparatory message ("Preparing drawing"), and pauses to realize the current window before calling the DLL routines that display the filled ellipse. The procedure pauses by default before it terminates, allowing the ellipse to remain on the display, as shown:
i-dllex3.p
/* DLL routine to create an elliptic region */
PROCEDURE CreateEllipticRgnIndirect EXTERNAL "gdi32.dll":
DEFINE RETURN PARAMETER RegionHandle AS LONG.
DEFINE INPUT  PARAMETER RegionSpec   AS MEMPTR.
END PROCEDURE.

/* DLL routine to get drawing object */
PROCEDURE GetStockObject EXTERNAL "gdi32.dll":
DEFINE RETURN PARAMETER ObjectHandle AS LONG.
DEFINE INPUT  PARAMETER ObjectType   AS LONG.
END PROCEDURE.

/* DLL routine to select region into device context */
PROCEDURE SelectObject EXTERNAL "gdi32.dll":
DEFINE INPUT PARAMETER DeviceHandle AS LONG.
DEFINE INPUT PARAMETER ObjectHandle AS LONG.
END PROCEDURE.

/* DLL routine to display region */
PROCEDURE PaintRgn EXTERNAL "gdi32.dll":
DEFINE INPUT PARAMETER DeviceHandle AS LONG.
DEFINE INPUT PARAMETER RegionHandle AS LONG.
END PROCEDURE.

/* DLL routine to get handle of window device context */
PROCEDURE GetDC EXTERNAL "user32.exe":
DEFINE RETURN PARAMETER DeviceHandle AS LONG.
DEFINE INPUT  PARAMETER WindowHandle AS LONG.
END PROCEDURE.

/* DLL routine to release device context handle */
PROCEDURE ReleaseDC EXTERNAL "user32.exe":
DEFINE INPUT PARAMETER DeviceHandle AS LONG.
END PROCEDURE.

/* DLL routine to delete elliptic region */
PROCEDURE DeleteObject EXTERNAL "gdi32.dll":
DEFINE INPUT PARAMETER RegionHandle AS LONG.
END PROCEDURE.

/* Variable Definitions */
DEFINE VARIABLE ElipRegion AS MEMPTR  NO-UNDO. /* Elliptic region struct. */
DEFINE VARIABLE hDevice    AS INTEGER NO-UNDO. /* Device context handle */
DEFINE VARIABLE hObject    AS INTEGER NO-UNDO. /* Drawing object handle */
DEFINE VARIABLE hRegion    AS INTEGER NO-UNDO. /* Elliptic region handle */
DEFINE VARIABLE erLeft   AS INTEGER INITIAL 1  NO-UNDO. /* Elliptic */
DEFINE VARIABLE erTop    AS INTEGER INITIAL 5  NO-UNDO. /* Coordinates */
DEFINE VARIABLE erRight  AS INTEGER INITIAL 9  NO-UNDO.
DEFINE VARIABLE erBottom AS INTEGER INITIAL 13 NO-UNDO.

/* Allocate and build elliptic region structure specifying rectangular
   coordinates of region */
SET-SIZE(ElipRegion) = 4 /* int left */
+ 4 /* int top */
+ 4 /* int right */
+ 4. /* int bottom */

PUT-LONG(ElipRegion, erLeft)   = 50.
PUT-LONG(ElipRegion, erTop)    = 50.
PUT-LONG(ElipRegion, erRight)  = 200.
PUT-LONG(ElipRegion, erBottom) = 100.

/* Initialize current window with PAUSE and display perfunctory message */
DISPLAY "Preparing drawing..." .
PAUSE.
/* Get device context, region, and drawing object handles */
RUN GetDC (OUTPUT hDevice, INPUT CURRENT-WINDOW:HWND).
RUN CreateEllipticRgnIndirect (OUTPUT hRegion, INPUT ElipRegion).
RUN GetStockObject (OUTPUT hObject, INPUT 4).

/* Select drawing object and region for device context, and paint region */
RUN SelectObject (INPUT hDevice, INPUT hObject).
RUN SelectObject (INPUT hDevice, INPUT hRegion).
RUN PaintRgn (INPUT hDevice, INPUT hRegion).

/* Free resources */
/* Free region structure */
SET-SIZE(ElipRegion) = 0.

/* Release device context */
RUN ReleaseDC (INPUT CURRENT-WINDOW:HWND, INPUT hDevice).

/* Delete elliptic region */
RUN DeleteObject (INPUT hRegion).

/* Wait for user to close window or hit Escape */
WAIT-FOR WINDOW-CLOSE OF CURRENT-WINDOW.