Use SOURCE-PROCEDURE to identify your caller
- Last Updated: April 15, 2024
- 3 minute read
- OpenEdge
- Version 13.0
- Documentation
You have seen the THIS-PROCEDURE system handle, which holds the handle of the
current procedure. Another similar built-in handle is the SOURCE-PROCEDURE system handle. Whenever the AVM executes a
RUN statement, the SOURCE-PROCEDURE handle in the
called procedure returns the procedure handle of the caller.
To use SOURCE-PROCEDURE to identify your caller:
- To capture the
SOURCE-PROCEDUREwhen the Order window first starts up, add this definition to the Definitions section of h-OrderWin.w:/* Local Variable Definitions --- */ DEFINE VARIABLE hSource AS HANDLE NO-UNDO. - Add another line to its main block, to save off the value on start-up:
ASSIGN THIS-PROCEDURE:PRIVATE-DATA = STRING(OrderNum) hSource = SOURCE-PROCEDURE. ... - Add a new fill-in to the window called iOtherOrder, with a label of Other Order.
- Add a new button called BtnAlign, with a label of
Align Order.
You can put a rectangle around them to group them if you want, like this:
- Code this
CHOOSEtrigger for BtnAlign:DO: DEFINE VARIABLE hOtherWin AS HANDLE NO-UNDO. DEFINE VARIABLE hWindow AS HANDLE NO-UNDO. RUN fetchOrderWin IN hSource (INPUT iOtherOrder:SCREEN-VALUE, OUTPUT hOtherWin). IF VALID-HANDLE(hOtherWin) THEN DO: ASSIGN hWindow = hOtherWin:CURRENT-WINDOW hWindow:ROW = THIS-PROCEDURE:CURRENT-WINDOW:ROW + 1 hWindow:COLUMN = THIS-PROCEDURE:CURRENT-WINDOW:COLUMN + 3. END. END.This code runs an internal procedure in its source (the main window), which takes an Order number as input and returns as output the handle of the window with that Order number in it. The code then uses the
CURRENT-WINDOWattribute of that other window and theCURRENT-WINDOWattribute ofTHIS-PROCEDUREto align the other window just below and to the right of this one. - In h-CustOrderWin6.w, add another variable to the
Definitions section:
DEFINE VARIABLE cOrderNumbers AS CHARACTER NO-UNDO.This variable holds a list of all the Order numbers the procedure opens up windows for.
- Add a statement to the BtnOrder (Order
Detail) button to save off the Order number
of each window as it is created, in addition to its procedure handle:
DO: DEFINE VARIABLE hOrder AS HANDLE NO-UNDO. RUN h-OrderWin.w PERSISTENT SET hOrder (BUFFER Order). ASSIGN cOrderHandles = cOrderHandles + (IF cOrderHandles NE "" THEN "," ELSE "") + STRING(hOrder) cOrderNumbers = cOrderNumbers + (IF cOrderNumbers NE "" THEN "," ELSE "") + STRING(Order.OrderNum). END. - Define the new fetchOrderWin internal procedure in
h-CustOrderWin6.w:
/*--------------------------------------------------------------------- Purpose: Returns the procedure handle to the instance of h-OrderWin.w that displays the requested Order Number, Notes: ---------------------------------------------------------------------*/ DEFINE INPUT PARAMETER pcOrderNum AS CHARACTER NO-UNDO. DEFINE OUTPUT PARAMETER phOrderWin AS HANDLE NO-UNDO. DO iHandle = 1 TO NUM-ENTRIES(cOrderNumbers): IF ENTRY(iHandle, cOrderNumbers) = pcOrderNum THEN DO: phOrderWin = WIDGET-HANDLE(ENTRY(iHandle,cOrderHandles)). RETURN. END. END. END PROCEDURE.This code acts as an API call that other procedures like the instances of
h-OrderWincan run to obtain data from the main window. It looks through the list of Order numbers and, when it finds the one that was requested, it passes back as output the matching procedure handle for that Order.
To test out this latest change:
- Run h-CustOrderWin6.w.
- Open a couple of Order Detail windows.
- In one of them, enter the Order number displayed in the
other, and click the Align Order button (or tab out of the
fill-in and press ENTER to do the same thing.) The windows
should align like this:
Why did you use a button with a CHOOSE trigger instead of just defining
a LEAVE trigger for the fill-in? In this case, without the button the
fill-in would be the only enabled object in the window, so its LEAVE
trigger would not fire. You need at least two enabled objects in a window in order to
leave one of them. So the button gives you something to tab into and click.
This latest example shows you in simple terms how you can provide an API in a procedure that other persistent procedures can use to get information from, or to invoke actions in, and a couple of different ways to obtain the handles of other running procedures you are interested in.