1. Troy Cowan
  2. PowerBuilder
  3. Tuesday, 11 July 2023 17:30 PM UTC

Hi all. I have a request for advice on how to handle a situation. 

We have a PowerBuilder app of some complexity. For some reason, some of our users are in the habit of double clicking, rather than single clicking (AKA clicking) on a particular commandbutton on a particular response window. I don't know why, and we can't seem to get them to stop doing this. 

Unfortunately, what ends up happening is that the (single) click handler runs, and the second click gets queued up to be handled after the click event finishes. Or that's how it seems to me. One possible outcome of the click handler is to make the entire response window close. Thus, when the event finishes, the button that used to be under the cursor is no longer there, and if the user is unlucky, the cursor is over a different commandbutton on a different window. The handler of that commandbutton's click event runs, much to the surprise of the user. 

Aside from training, can anyone think of a way of handling this situation? Ideas we have come up with so far are: 

  • Employ a "are you sure" type message box on the first commandbutton. 
  • Move the controls around on the second window so that there is nothing in the space where the cursor would be.

We also tried adding a Sleep() before exiting the first click handler, but it seems like the second click event just stays queued up during the entire click handler, Sleep() and all.

Roland Smith Accepted Answer Pending Moderation
  1. Friday, 21 July 2023 15:03 PM UTC
  2. PowerBuilder
  3. # 1

You could add an instance variable that tracks the last time the button was clicked. If the two clicks are too close together, return from the event. I would use the timeGetTime Windows function which returns the current system time in milliseconds.

The very last line of code in the event will record the milliseconds in the instance variable.

The first line of code in the event will subtract the instance variable from the current value. If the difference is too small (under 100 for example) then Return.

 

Function ulong timeGetTime ( ) Library "winmm.dll"

https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timegettime

 

Comment
  1. Miguel Leeuwe
  2. Friday, 21 July 2023 18:43 PM UTC
The disadvantage is that you have to correct the code in all of your already scripted buttons.
  1. Helpful
  1. Roland Smith
  2. Friday, 21 July 2023 19:09 PM UTC
Maybe it could be incorporated into the button ancestor object.
  1. Helpful
  1. Miguel Leeuwe
  2. Saturday, 22 July 2023 05:38 AM UTC
Yes, but somehow, you'd have to check in the inherited object whether to execute the code or not by checking on for example the AncestorReturnValue.

Something like:

if AncestorReturnValue = 1 then

return

end if



Not a lot of code, but still might be a lot of work if you have a lot of buttons. For a datawindow button, it would be more complicated.

To be honest, I believe in user education and don't think all of this is worth the trouble.

regards
  1. Helpful
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Thursday, 20 July 2023 20:52 PM UTC
  2. PowerBuilder
  3. # 2

Hi Everyone;

  After extensive testing using a Ribbon Bar; Picture Button; Command Button and CB within a DW control  -  I have now opened a new support ticket for issues around these controls on properly handling a double click. I have now tested my Test Case in PB 2019R3 through PB 2022 R2 beta and on W10 & W11.

  You can read all about my reported bug in ticket # 10581

Regards ... Chris

Comment
  1. Miguel Leeuwe
  2. Friday, 21 July 2023 08:22 AM UTC
That's great Chris! Thanks for your contribution to this. BTW: 've added a comment to the ticket.

regards
  1. Helpful
  1. Chris Pollach @Appeon
  2. Friday, 21 July 2023 14:21 PM UTC
Hi Miguel;

Thanks .. yes, I saw your comment on the ticket back to Ken. ;-)

I also added some more $0.02 to the thread this AM.

I see that Ken has now transferred the ticket over to Engineering.

Regards ... Chris
  1. Helpful
There are no comments made yet.
Troy Cowan Accepted Answer Pending Moderation
  1. Wednesday, 12 July 2023 12:45 PM UTC
  2. PowerBuilder
  3. # 3

Hi Chris, thanks!

I have a couple of questions.

How critical is it to add this new code into its own event handler? I tried it both ways and I can't see any difference. Is it just good practice or what?

 

 

Can you give me the theory on what is happening? Here's my attempt at it: 

1) First click happens

2) Click handler is entered

3) Button is disabled

4) Other code in click handler runs. Some time while this is happening, the second click occurs (over the disabled button).

5) The Yield() allows the second click to "process", which since it is over a disabled button, is a do-nothing. 

6) Not exactly sure what the Message.Processed = true is doing.

     (Note: I tried running with and without Message.Processed = true and could not detect any difference in behavior)

7) Button is re-enabled and (original) click event handler finishes. 

 

If this is right or close, then I see there may be a race condition happening: maybe the event handler takes 0.5 seconds (there is some database manipulation going on in it). The time between clicks might be 0.4 seconds, in which case the added code should effectively make that second click go away. 

But what if the time between clicks is 0.51 seconds? Then the handler is finished, and the second click will take place over whatever control happens to be there, same as what I have now. Is that correct?

 

 

 

Comment
  1. John Fauss
  2. Tuesday, 18 July 2023 15:20 PM UTC
Setting Message.Processed = True tells PB to NOT pass the event to the under-the-covers "default Windows procedure" (also known as "DefWindowProc") for subsequent processing by other object (such as a parent control or window/). The default value for this property is False, whereby PB will pass the event to DefWindowProc. The DefWindowProc is the mechanism that Windows uses internally to propagate event messages up the object hierarchy, giving each control, window, etc. an opportunity to process an event occurrence. You may not see any tangible difference, but it your code takes some action in response to an event message and you do NOT want any other code to see/process the same event, then the accepted practice is to set Message.Processed = True. HTH.
  1. Helpful 2
There are no comments made yet.
Miguel Leeuwe Accepted Answer Pending Moderation
  1. Wednesday, 12 July 2023 01:35 AM UTC
  2. PowerBuilder
  3. # 4

@Chris,

here's the adapted sample app with your suggested code. See attached. PB2019 R3 build 2797

regards

Attachments (2)
Comment
  1. Miguel Leeuwe
  2. Friday, 14 July 2023 16:41 PM UTC
Agreed, so that leaves the option of not using ue_clicked and putting the posted call to the event that enables the button in a try ... catch. Should work I'd say, but haven't tried it yet myself. I'm going to try it right now.
  1. Helpful
  1. Miguel Leeuwe
  2. Saturday, 15 July 2023 04:52 AM UTC
Well, after having to wait for all of our backup stuff finishing, I've finally tried to incorporate my proposed solution(s) to the PFC u_cb button.

For some reason neither work. Not using a ue_clicked, nor using the normal clicked. Not sure why, but life's too short. My method of using a cpu() time difference would work, but as you stated correctly, that would mean having to check in each clicked script on the ancestorReturnValue to continue the script or not.

So my best bet is to simply educate our users to not do any double-clicks on a command button.

regards

:)
  1. Helpful
  1. Chris Pollach @Appeon
  2. Saturday, 15 July 2023 13:01 PM UTC
Mi Miguel;

Yes, it's one thing to handle this at the "concrete" level but a whole new "ball of wax" to implement at the "base" ancestor level.

Regards ... Chris
  1. Helpful
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Tuesday, 11 July 2023 21:42 PM UTC
  2. PowerBuilder
  3. # 5

Hi Troy / Miguel;

  I have this working very well & it's really simple to code.

  • Create a User Event on the CB (ie: oe_enable)
  • Post the UE on the Clicked event ...

THIS.enabled    =    FALSE
THIS.POST Event oe_enable( )

  • In the UE run the following code ...

Message.Processed  = TRUE
Yield ( )
THIS.enabled = TRUE

Note1: that this can be easily adapted in an ancestor CommandButton or PictureButton control. Also, no fancy timers, sleepers, switches, etc needed.

Note2: Tested on PB 2019R3, 2021, 2022 on W10 & W11.

Note3: PB 2019R3 test case now attached.

Regards ... Chris

 

Attachments (1)
Comment
  1. Chris Pollach @Appeon
  2. Wednesday, 19 July 2023 16:17 PM UTC
Hi Ben;

FYI: After more testing .. IF a Command Button or Picture Button control is placed within an MDI Application and their style is set to "Flat" then you are 100% correct - the DoubleClick issue does not occur and no special coding is required. However, if those controls are in an SDI based App (say one Main Window), then the two clicks would occur.

I noticed that my STD Framework's PB was *not* the "Flat" style - so I have now changed it to that style in the latest PB 2022 R2 framework version. So the PB DC issue will be fixed in the next STD Framework release for R2. ;-)

Regards ... Chris
  1. Helpful 1
  1. Benjamin Gaesslein
  2. Thursday, 20 July 2023 07:08 AM UTC
Yet another layer of this mystery is peeled back. Looks like this is a gift that keeps on giving. :)
  1. Helpful 1
  1. Chris Pollach @Appeon
  2. Thursday, 20 July 2023 14:32 PM UTC
Hi Ben;

Further testing has now revealed that a Ribbon Bar button and a CB residing in a DataWindow both *have* the Double Click problem in PB 2019R3.

I will now test this aspect in PB 2022 FR2 beta. Say tuned.

Regards ... Chris
  1. Helpful
There are no comments made yet.
Miguel Leeuwe Accepted Answer Pending Moderation
  1. Tuesday, 11 July 2023 20:00 PM UTC
  2. PowerBuilder
  3. # 6

Ok,

You're absolutely right. In older powerbuilder versions this would have probably worked :(

Ignore the picture, I've copied this from another sample app.

The only important thing are the 2 instance variables and the command button.

I've build in a delay to execute or not the button. I've used 1000 msecs of delay to rather execute the script or not, but you might want to make that delay bigger or smaller.

 

See the attached sample app. PB2019 R3.

Attachments (1)
Comment
  1. Miguel Leeuwe
  2. Tuesday, 11 July 2023 20:04 PM UTC
You could make a custom command button in which you put the delay. It would return a 0 or 1. Then when you inherit from that button, your inherited button could check on the AncestorReturnValue of the ancestor to know whether to execute or not.
  1. Helpful
  1. Miguel Leeuwe
  2. Tuesday, 11 July 2023 20:05 PM UTC
The instance variable would then also be defined in the ancestor button, so that every button has its own value, without interfering with any other button's values.
  1. Helpful
  1. Miguel Leeuwe
  2. Tuesday, 11 July 2023 20:25 PM UTC
You might also want to make this delay in a button "optional". Imagine you have a button that you want to be able to click very rapidly. I don't know, to increment a counter or something. So you could set this as a boolean variable in the ancestor command button "ib_noDoubleClickEnabled" .. Something like that.
  1. Helpful
There are no comments made yet.
Miguel Leeuwe Accepted Answer Pending Moderation
  1. Tuesday, 11 July 2023 17:42 PM UTC
  2. PowerBuilder
  3. # 7

Hi,

Have you tried to do:

This.Enabled = false at the beginning of the clicked event?

At the end of the event, you'd then do a:

This.Enabled = true

regards.

 

Comment
  1. Troy Cowan
  2. Tuesday, 11 July 2023 17:54 PM UTC
Well, I hadn't but I just tried. It didn't make any difference.



What I would like to do is have some way of clearing the second click from the queue, so that when the event handler from the first click finishes, the decks are cleared, so to speak.
  1. Helpful
  1. Miguel Leeuwe
  2. Tuesday, 11 July 2023 19:57 PM UTC
You're absolutely right. In older powerbuilder versions this would have probably worked :(

Please see my latest answer with an attached sample app made in 2019 R3.
  1. Helpful
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.