1. Daniel Vivier
  2. PowerBuilder
  3. Thursday, 18 October 2018 15:56 PM UTC

OK, here's a tough one! We have a need to detect, in an event in the main window, whether any response window is open. Currently the only reliable way we have found to do that is we wrote a function that lists every known response window and returns whether any of them are open, like:

if IsValid(w_response1) or IsValid(w_response2) ... or IsValid(w_responseN) then
    return TRUE
else
    return FALSE
end if

Obviously this is a maintenance concern, because you could forget to add a new window to the function we have that makes that determination.

We tried to think through a lot of other options but didn't come up with anything else that was both reliable and minimally invasive on our current codebase.

The reason we need this, by the way, is we have a file association that should trigger an action (importing a file) on the main window's menu. If the program is already open, a 2nd copy of it is opened by the file association, which then sends a message to the 1st copy's main window to give it the file name, then exits. The first copy gets that message, but it's only reasonable for it to proceed with the action if the user isn't busy doing something else in a response window! (The user is given a messagebox, telling them they can process the file later, if they are in fact in a response window.)

We considered a bunch of other approaches. One was reading lists of objects from the program's PBLs with LibraryDirectory(), but the problem there is that you can't call IsValid on a string that is the name of a window, in order to find out whether it's open - it has to be an actual window variable.

Another approach we considered was overriding Open and OpenWithParm with our own functions, that set a variable (say, gbNotInMainWindow), do the appropriate open, then on return from the open unset that variable. The problem with that is that if one response window opens a 2nd response window, on return from the 2nd one, gbNotInMainWindow will be set back to FALSE, when it should still be TRUE!

Does anybody have any better ideas for how to handle this that are not maintenance concerns like our current solution? Thanks.

 

Accepted Answer
Ronnie Po Accepted Answer Pending Moderation
  1. Thursday, 18 October 2018 16:25 PM UTC
  2. PowerBuilder
  3. # Permalink

Hi Dan,

This suggestion assumes that all of your response windows inherit from a common ancestor (for example. w_response_base). If they don't, it may be worth the one-time exercise of creating a common base class and editing the source of each response window to have it inherit from the base class.

Then, simply:

1. Declare a global integer variable to contain the number of open response windows.

int gi_responseWinCount

2. Place the following code snippets in the open() and close() events, respectively, of the ancestor response window.

// Add to w_response_base open() event

gi_responseWinCount += 1

// Add to w_response_base close() event

gi_responseWinCount += -1

3. To determine whether a response window is open, just check if gi_responseCount > 0

 

Hope that helps...

Comment
  1. Daniel Vivier
  2. Thursday, 18 October 2018 17:13 PM UTC
Wow, ask and ye shall receive! That's a good answer - thank you.



Of course, it requires us to edit each of our non-main windows to add that inheritance, and make sure the Open and Close events extend ancestor script.



Also in our case, we have a common PBL used by several applications, and as such, it doesn't have access to each application's global variables. (We inject an nvo_global object, which is in the common PBL, into most windows - its instance variables replace most of what used to be our applications' globals.)



I think the best way to handle the issue about the windows in the common PBL is to have the incrementing and decrementing done by a function, say gf_increment_window_count(Boolean increment). If increment is TRUE, it increments it, if FALSE, it decrements it. We will have a do-nothing copy of that in the common PBL (to allow calls to the function in common windows to compile, when we compile common alone) and a working copy of it in the app's main PBL, that actually increments/decrements a real global variable. Since the main PBL comes earlier in the library list order than the common PBL, the real function will be the one that always actually gets called.
  1. Helpful
  1. Ronnie Po
  2. Thursday, 18 October 2018 17:54 PM UTC
No problem! One other thought. Since you mentioned overriding Open() and OpenWithParm(), you can possibly avoid having to create the common ancestor window if you perform the increments in those functions, and the decrements in Close() and CloseWithReturn()...
  1. Helpful
There are no comments made yet.


There are replies in this question but you are not allowed to view the replies from this question.