A new method for the System Object #

General discussions on potential enhancements to the APL+Win system.

A new method for the System Object #

Postby Ajay Askoolum » June 9th, 2018, 1:01 pm

I am looking for a new method with the system object # to display application messages, something like
Code: Select all
'#' ⎕wi 'Alert' 'Recalculating ..'
with a built in timer (any number of milliseconds up to a minute) that can automatically remove the notification. The timer counts down from time the notification is (re-)initialized.

This is a little like the Excel StatusBar functionality that allows any arbitrary message to be displayed.
Code: Select all
    Application.StatusBar = "Recalculating ..."
This can be a very convenient way to provide feedback from long running processes without the overhead of a user-defined function that creates a form for the same purpose.

The system object # is available from the interactive session or a user interface - so the feedback will work regardless of context. When APL+Win is an ActiveX server (i.e. no interactive session or user interface), this can re-route the message via the existing Notify method.
Ajay Askoolum
 
Posts: 884
Joined: February 22nd, 2007, 2:16 am
Location: United Kingdom

Re: A new method for the System Object #

Postby brent hildebrand » June 10th, 2018, 3:45 am

I'm assuming Ajay, you are speaking about the development interpreter. In a runtime system, you would need a user defined window to provide feedback. So, with that in mind try the following function for providing information to yourself on a running program in the development environment. It may not work, and it might require []WGIVE to get the Session Manager's statusbar to paint correctly. The function finds the statusbar, then writes text into it, using Defer so it occurs when the Session Manager has already written to it, so the function then over-write what is there.

Code: Select all
    ∇ SetAplStatusText rarg;h
[1]   ⍝ Set status text in APL+Win Development Interpreter
[2]   h←'#' ⎕wi 'hwndmain'
[3]   h←⎕wcall 'GetWindow' h 'GW_CHILD'
[4]   h←⎕wcall 'GetWindow' h 'GW_HWNDNEXT'
[5]   :assert 'msctls_statusbar32'≡∊↑/⎕wcall 'GetClassName' h (255⍴' ') 255 h
[6]   '#' ⎕wi 'Defer' ("⎕wcall 'SetWindowText' ",(⍕h)," '",rarg,"'")
    ∇


SetAplStatusText "Recalculating ..."
brent hildebrand
 
Posts: 538
Joined: February 12th, 2007, 5:53 pm
Location: Loma Linda, CA

Re: A new method for the System Object #

Postby Ajay Askoolum » June 10th, 2018, 5:47 am

Hi Brent,

Very clever.

I think the final h on line 5 is superfluous?
Code: Select all
      SetAplStatusText 'new update'
⎕WCALL CALL ERROR: Wrong number of arguments
SetAplStatusText[5] :assert 'msctls_statusbar32'≡∊↑/⎕wcall 'GetClassName' h (255⍴' ') 255 h
After removing it, it works in interactive mode.
However, when I have it inside a long running function, the message is always 'Executing' i.e. the interpreter is overriding the display. After the function completes, the final meeage sent by your function appears.Also, when the argument is a scalar, I get
Code: Select all
⎕WCALL CONVERSION ERROR: Character scalar pointer not allowed with [Compatibility]EnhancedWCALL = 1
>[#;] ⎕wcall 'SetWindowText' 197730 '8'
In a runtime environment, I can use a progress bar.
I am looking for a simple way of displaying progress without the screen scrolling or having to write acres of code up front.
Ajay Askoolum
 
Posts: 884
Joined: February 22nd, 2007, 2:16 am
Location: United Kingdom

Re: A new method for the System Object #

Postby Ajay Askoolum » June 10th, 2018, 6:17 am

I added []wgive 1 into your function - that overrides the 'Executing' message in the status bar while my function is running.

That will do; it gives me what I sought.

Thanks, Brent.
Ajay Askoolum
 
Posts: 884
Joined: February 22nd, 2007, 2:16 am
Location: United Kingdom

Re: A new method for the System Object #

Postby brent hildebrand » June 10th, 2018, 10:33 am

Ajay Askoolum wrote:Hi Brent,

I think the final h on line 5 is superfluous?
Code: Select all
      SetAplStatusText 'new update'
⎕WCALL CALL ERROR: Wrong number of arguments
SetAplStatusText[5] :assert 'msctls_statusbar32'≡∊↑/⎕wcall 'GetClassName' h (255⍴' ') 255 h

After removing it, it works in interactive mode.

I added this line just to confirm that I had found the right control. How I knew what to execute was from using the Microsoft program SPY++. What I do not know is if this same sequence for finding the Session statusbar works for all versions, though I suspect it will work for most.

Ajay Askoolum wrote:However, when I have it inside a long running function, the message is always 'Executing' i.e. the interpreter is overriding the display. After the function completes, the final meeage sent by your function appears.Also, when the argument is a scalar, I get
Code: Select all
⎕WCALL CONVERSION ERROR: Character scalar pointer not allowed with [Compatibility]EnhancedWCALL = 1
>[#;] ⎕wcall 'SetWindowText' 197730 '8'
Just ravel the message (,'8') and try that. I should have put that in my code, but did not anticipate that you would have entered a scale. And YES - the last "h" is superfluous. I don't know how that got into the code I posted!

Ajay Askoolum wrote:I added []wgive 1 into your function - that overrides the 'Executing' message in the status bar while my function is running.

That will do; it gives me what I sought.
[]WGIVE 1 - be careful of that, as it will greatly slow down your function. You can use []WGIVE 0, and perhaps puts that in the SetAplStatusText function to yield to Windows at that point to allow it to paint the statusbar. []WGIVE 1 will cause APL to yield at every opportunity. In some long running functions, I do sometimes set a non-zero value, the value depending on your system, but it is often 1000 or 2000. I know the documentation say 100, but you need to experiment to find the right value for your system.

Ajay Askoolum wrote:Thanks, Brent.
I hope it works. You can also read the text in the statusbar by changing the line in the code from SetWindowText to GetWindowText. And note, this only works in the development interpreter, not in the runtime interpreter, because the runtime does not have a session manager, and it should generate an ASSERTION ERROR. So here is the code with the errant "h" removed:

Code: Select all
    ∇ SetAplStatusText rarg;h
[1]   ⍝ Set status text in APL+Win Development Interpreter
[2]   h←'#' ⎕wi 'hwndmain'
[3]   h←⎕wcall 'GetWindow' h 'GW_CHILD'
[4]   h←⎕wcall 'GetWindow' h 'GW_HWNDNEXT'
[5]   :assert 'msctls_statusbar32'≡∊↑/⎕wcall 'GetClassName' h (255⍴' ') 255
[6]   '#' ⎕wi 'Defer' ("⎕wcall 'SetWindowText' ",(⍕h)," '",rarg,"'")
    ∇
brent hildebrand
 
Posts: 538
Joined: February 12th, 2007, 5:53 pm
Location: Loma Linda, CA

Re: A new method for the System Object #

Postby Davin Church » June 10th, 2018, 11:28 am

I thought you didn't want to have to use subroutines? For myself, I frequently use my "PopNote" utility to pop up a little message in the middle of the screen and destroy it when I'm done. I do that all over my applications when I want people to "please wait" while I do stuff. It works with both development and run-time and is a lot more effective for my users who ignore any status bar messages I give them. I have a timer function that can destroy it after a set time if you prefer.

Alternatively, I've also got a "progress bar" utility that creates and manages little standalone progress bar windows on the screen if you're doing something that has defined steps and a known end. It's terribly easy to use and I've taken to putting it all over my personal programs that take more than a few seconds to complete.
Davin Church
 
Posts: 651
Joined: February 24th, 2007, 1:46 am


Return to APL+Win Wish-List

Who is online

Users browsing this forum: No registered users and 11 guests