Escape key in Net component captured in COBOL with odd value

I have a COBOL program that opens a window and hosts a NET UserControl component, which has been declared in the Screen Section.  I would like to allow the user to press the ESC key and have the program close.  I have tried to capture the key in the NET component, but it looks like control goes directly back to COBOL and bypasses any event handlers in the component completely.  I am OK with that, as I wanted to handle it in COBOL anyway.  I started with a delegate event handler, as shown in AmortControl, but when I found that the key was not being captured in the component, I removed the event handler since there was no way to fire it. 

The problem I have is that when the exception is caught in the screen accept statement, and I proceed to evaluate the value, it is MSG-VALIDATE.  In other screens of the COBOL program, the ESC key (pressed in COBOL) closes the currently running program.  I am unsure where MSG-VALIDATE came from.  I ran AmortControl for comparison.  When I press ESC when it is running, it also triggers the ON EXCEPTION of the accept statement, but I don't recognize any of the values I can see for event-occurred or event-type.  And while the program does close, it seems the code processing is unnatural.

I have built AmortControl from the source code, running the DLL through NETDEFGEN to get the CPY and event DLL, making sure to put both DLLs in the folder with wrun32.  But as I said, it doesn't appear that processing runs through the event DLL anyway.  I'm running extend 10.0.0, Windows 10, 32-bit for development, just a desktop application for now, but the app will be run through a remote desktop also.

What am I not understanding? 

  • Does your accept screen look something like: perform until some-value, or accept screen on exception perform some-para

    The perform until some-value may be where some-value has a value in working storage like 27 which is the default value for the escape key. An on exception phrase captures function key values including the escape key. Many Acu style COBOL programs have a working storage 77 Key-status is special-names CRT status pic 9(4), with some 88 levels below that including exit-pushed value 27.
  • Yes, we do have those values declared:
    88 tab-button-pushed value 9.
    88 exit-button-pushed value 13.
    88 cancel-button-pushed value 27.
    88 quit-button-pushed value 27.

    And the accept statement:
    accept full-listing-screen
    allowing messages from any thread
    on exception
    perform net-grid-event
    end-accept

    And when I am in the NET component and I press ESC, the on exception phrase is activated, and net-grid-event is performed.
    NET-GRID-EVENT.
    if event-type = msg-net-event
    evaluate event-data-2
    when @UserControl1_DoubleClkBtnPressed
    perform process-item-selected
    end-evaluate
    end-if.

    When I check event-type, it is 16391, which is MSG-VALIDATE.
    78 MSG-VALIDATE VALUE 16391.

    If I saw that the event-type was 27, then I could create a when for that, and everything would work as I want. But I don't know what to do with an ESC that comes back as MSG-VALIDATE. Event-data-1 and event-data-2 are both empty. It seems that ESC should have a different event code.
  • Do you key-status or some other variable for the CRT status. Let's say you use key-status.
    NET-GRID-EVENT.
    accept key-status from escape.
    evaluate true
    when cancel-button perform exit-program-routine
    end-evaluate
    if event-type = msg-net-event
    evaluate event-data-2 ....

    .Net / ActiveX controls and mouse movements generate events. Keys such as esc, function keys generate exception values. You have to look for both.
  • I'm revisiting this with a little more information from testing. I am able to reproduce my issue in AmortControl. When I tested in AmortControl, I discovered that, after pressing ESC, a msg-validate event is generated, which is processed in the NET component event paragraph. No further processing is required, so control returns to the screen accept. I press ESC a second time, and crt status now holds the value 27, which is the value of ESC, and that value is processed as defined. So issue 1 is that I have to press the ESC key twice to get the expected event value.

    At that point, I tested AmortControl by commenting out the read-only entry boxes that display as part of the COBOL screen, to more closely simulate my application. Again, the first exception value event type generated was msg-validate. When I pressed ESC a second time, instead of getting a crt status of 27, I got a status of 9. This is exactly what my application is doing, which I don't understand. I was able to test the reverse, in that I added a small read-only box to my application screen. I still had to hit the ESC key 2 times, but the second time, I saw that crt status contained the value of 27, which is what I've been looking for. So issue 2 is that in order to have the ESC value correctly generated, I need to have at least 1 entry field (or possibly a different control) displayed on the screen, in addition to my NET component. Unfortunately, having that entry field in addition to my NET component is not ideal. With the first ESC press, focus goes to that box, and off my NET component.

    These 2 stated issues are the things I need to resolve somehow, even if it's just an explanation for why it has to work this way.
  • I believe I can explain, your screen (window) has an event procedure paragraph. Typically msg-validate means that the user has exited the control and so msg-validate allows the program to validate or verify whatever data within the control you want. Event processing occurs BEFORE the Screen ACCEPT has been terminated. So the esc 27 while valid, is not seen due to the entire screen having the event processing being done, and then once you're back in the screen 27 is seen as that is an exception or termination value, which terminates the accept. Instead of having the event procedure tied to the screen, have it with just the control and see if you see the UI and flow work in a way that makes sense to you.
    Are you using the sample AmortControl.cbl, as that example program has the event tied to the control and not to the entire screen. When you start commenting out other fields on the UI, you may only be leaving the .Net control, which would mean the esc key has the program process the event for that control, msg-validate, and when it does not find anything to do, returns to the accept statement, forcing you to use the esp key twice.

    NET-GRID-EVENT.
    if event-type = msg-net-event
    evaluate event-data-2
    when @UserControl1_DoubleClkBtnPressed
    perform process-item-selected
    end-evaluate

    accept key-status from escape

    evaluate key-status

    when 27 perform exit-routine

    end-evaluate
    end-if.

     When you run the example anortcontrol program, the focus is on a listbox (a .Net control), if you tab to 1 of the push buttons and use the esc key, the program exits right away.

    I hope this helps.

  • It helps, in that it validates what I said--when there is a COBOL control displayed on the screen that can be tabbed to, the ESC key works fine. When there is no COBOL control displayed, just a NET component, I get the msg-validate event-type that processes in the NET component paragraph, processing returns to the screen accept, and with a second press of ESC, I get a crt status of 9. I added the code you gave above, but because the ESC 27 is not generated, processing falls through without performing exit-routine.

    You can duplicate what I'm seeing by commenting out the read-only entry fields and the Exit button in AmortControl.cbl, leaving just the NET part of the screen display and the COBOL labels. It sounds like what you are saying is that I cannot have just a NET component on a COBOL screen and expect the ESC key to work--I must have at least 1 COBOL component that can be tabbed into, and then the key will work.

    And my event procedure paragraph is tied just to my NET component, as shown in AmortControl.cbl. However, I'm using AmortControl as a program common between us, so you can see this issue is not because of my application. Rather, the behavior of my application can be duplicated by AmortControl. If I am able to resolve my issues using AmortControl, I will be able to transfer the fix to my application.
  • The amortcontrol accept statement

    PERFORM UNTIL Exit-Pushed
    ACCEPT screen-1
    ON EXCEPTION PERFORM Acu-Screen1-Evaluate-Func
    END-ACCEPT
    END-PERFORM.
    Look at the evaluate, it is only looking for one type of event.
    EVALUATE TRUE
    WHEN Event-Occurred
    IF Event-Type = Cmd-Close
    PERFORM Acu-Screen1-Exit
    END-IF
    END-EVALUATE

    If you change that so that is also looks for exception or termination values, you should be able to capture the 27 on the first entry, and not on the 2nd.
  • I commented out the auto-generated event logic and added PERFORM CHECK-KEY-STATUS.
    We had multiple copybooks with CHECK-KEY-STATUS as the only routine at Cisco, and the
    copybook we used depended upon the type of screen we were using. By doing it this way
    you can put the exception logic first and exclude any event logic you think is unnecessary.
    In the Acucobol-GT documentation, Acucorp admitted the exception logic was more stable.
    Trick is to know that if you regenerate you have to comment out the auto-generated code
    again and copy and uncomment the code bypass. Typically, the build won't require
    adjusting it again, but it doesn't hurt to verify.
  • Changing the code as you suggest did not change the execution. Unfortunately, the first paragraph that is triggered by ESC is usercontrol-events. It seems I would have to set some termination value in that paragraph, in order to tell the ACCEPT to just go ahead and process the next exception, except there's nothing there, until the second press of ESC. And even then, it's not what I expect. What is a crt status of 9?
  • GeorgeK, I typed a response, but it disappeared. The event logic for the NET component has to be there to handle the delegate events that come from NET. I understand what you are saying, and my application does something similar, where the screen accept is in a copybook that is used in several programs. The major issue I see is that with no COBOL controls on the screen, it feels like things "behind the scenes" are not processing as they would if there were at least 1 COBOL control on the screen.