1. Dan Black
  2. PowerBuilder
  3. Thursday, 19 September 2019 20:35 PM UTC

Hi, (this is version 2017 R3)

I have data from 4 or 5 different database tables that I need to display as a single unit in the user interface (and allow for datawindow updating).

It's a bit painful and messy, but I would like it to feel seemless as they tab through the fields. This means the tabbing has to change the focus from one column to another (handled fine by tab order within the datawindow), but it also has to skip out of that regular tabbing and change focus to a different datawindow control... it would have to do this a few times to work.

Here (see attached Personal_Info.PNG) is an example where the dob, gender, married and referred by are in one datawindow A (and table), and overlaid on top is another datawindow B (and table) with next of kin and family dr.

So pressing tab from the married field should move the focus into the next of kin (overriding it's default of moving to the referred by field). And tabbing from the family dr field should move focus to the referred by field.

In the keydown event of A:

STRING sl_current_column
LONG ll_return

ll_return = 0

IF key = KeyTab! AND keyflags = 1 THEN
    bi_tab = FALSE
    bi_shift_tab = TRUE
ELSEIF key = KeyTab! THEN
    bi_tab = TRUE
    bi_shift_tab = FALSE
ELSE
    bi_tab = FALSE
    bi_shift_tab = FALSE
END IF

sl_current_column = This.GetColumnName()

CHOOSE CASE sl_current_column

     CASE 'married'
         IF bi_tab THEN
             tab_main.tp_base.dw_next_of_kin.SetFocus()
             ll_return = 1
         END IF

    CASE 'referral_by'
         IF bi_shift_tab THEN
             tab_main.tp_base.dw_base.SetFocus()
             ll_return = 1
         END IF
END CHOOSE

bi_tab = FALSE
bi_shift_tab = FALSE

RETURN ll_return

This kind of works... I can see the focus change to the field I want, but then it changes to a different datawindow altogether. Almost like what would happen if you tabbed through a datawindow's fields, the focus would move to the next control on the window.

It's like the tab event was captured by something else that was listening and moved it along even though I've tried to stop it by returning 1 in the keydown event. I've tried adding keydown/keyup/key event listeners to the other objects on the window (and the window itself) but none of them fire after the keydown event returns 1.

 

I'd like to see if anyone else has had success with this kind of thing before I throw it out.

Another option I'm considering is putting all fields from all tables in one datawindow and changing the updateable fields at runtime during the save, to manually save across all tables.

Attachments (1)
Accepted Answer
Miguel Leeuwe Accepted Answer Pending Moderation
  1. Thursday, 19 September 2019 21:31 PM UTC
  2. PowerBuilder
  3. # Permalink

I've done exactly what you have described, but without having a tabpage.

See the attached mini-app.

My wild guess is that when you do the "tab_main.tp_base.dw_next_of_kin.SetFocus()" or the "tab_main.tp_base.dw_base.SetFocus()", something is executed in the tab or one of the tabpages.

Check their selectionChanged(), SelectionChanging() and getfocus events. Also look for the LoseFocus() of the datawindow controls.

Anyway, it's better to use the events "...tabout .. etc." mentioned by Michael.

Also the pbm_key event mentioned by Chris, I suppose you have done similar code on both datawindows?

 

Check for Losefocus and getfocus, it's probably something there.

Also see what happens if you do:

tab_main.tp_base.dw_next_of_kin.POST SetFocus()

instead of 

tab_main.tp_base.dw_next_of_kin.SetFocus()

 

NOTE: the attached sample (mini) app has been created with PB2019.

 

HIH

Attachments (1)
Comment
  1. Miguel Leeuwe
  2. Thursday, 19 September 2019 23:45 PM UTC
Just put a debug stop on the setfocus that you are doing in the key event. Then go "step by step" not "step over" with the debugger. What about the "create on demand" attribute on the Tab object? Any events on the tab (not tabpage)?

If you can/want, try to upload a small sample app in which the problem is reproduced. Don't worry about database, I'll just add some "fixed" data to the dw's.
  1. Helpful
  1. Michael Kramer
  2. Saturday, 21 September 2019 11:17 AM UTC
Playing devil's advocate here => Look out for POST calls during ItemChanged events! I have seen some crazy stuff over my 25+ year PB career.

Code being 20+ years old may even have calls to SetActionCode(int code). There act like "when you hit return; please behave like [return code]". Stemming from pre PB5 when you couldn't [return code] from events like ItemChanged/ItemError, Compiling these days result in WARNING but it is still valid syntax.

However, glad to see you have a solution,

/Michael
  1. Helpful
  1. Miguel Leeuwe
  2. Saturday, 21 September 2019 11:44 AM UTC
Hi,

True ... but maybe I've missed it. There's no itemChanged involved here, nor ItemError.

Good advice anyway, though it all depends what you do with 'post' in the itemChanged. Sometimes it's the solution for NOT having a problem in itemchanged.

Cheers
  1. Helpful
There are no comments made yet.
Miguel Leeuwe Accepted Answer Pending Moderation
  1. Saturday, 21 September 2019 03:13 AM UTC
  2. PowerBuilder
  3. # 1

Here's a corrected version of Dan's nice little test app to reproduce the problem.

I've only looked at what happens when TABbing, not when SHIFT+Tabbing. I suppose that would need some more correction, at least in the dwnBackTabOut or ...tabUout event.

It seems that doing a SetFocus() from within the pbm_dwnkey event, the effect of doing a "return 1" to cancel the pressed TAB key, that's not working and the TAB still goes through after having done the SetFocus(). It would go to the control with the next taborder. (by the way I corrected the taborders of the objects in the window to be sequential).

The problem is fixed by doing POST SetFocus().

I've also applied POST on the SetColumns() but that's NOT necessary, I just found out.

See the attached mutilated version that I made of Dan's app.

Attachments (1)
Comment
  1. Miguel Leeuwe
  2. Saturday, 21 September 2019 03:16 AM UTC
By the way, I've cleaned up the mess that I left here before with pasted sourcecode and some wrong conclusions due to some mistakes I made, so please refresh your page if your'e watching this right now. (sorry about that).
  1. Helpful
  1. Dan Black
  2. Monday, 23 September 2019 15:05 PM UTC
It's certainly not expected that the tab event would continue through after the return 1, but perhaps that's done so you can redirect the input into another field by using SetFocus...



It's been a while since I used a post to fix event issues, I had forgotten to try that :)



Thanks Miguel!
  1. Helpful
There are no comments made yet.
Dan Black Accepted Answer Pending Moderation
  1. Friday, 20 September 2019 16:36 PM UTC
  2. PowerBuilder
  3. # 2

I've done up a test app that reproduces the problem in PB2017R3. 

Attachments (1)
Comment
There are no comments made yet.
Dan Black Accepted Answer Pending Moderation
  1. Friday, 20 September 2019 14:46 PM UTC
  2. PowerBuilder
  3. # 3

I haven't been able to find the pbm_dwntabout event. I must just be in the wrong place?

Attachments (1)
Comment
  1. Dan Black
  2. Friday, 20 September 2019 15:00 PM UTC
:facepalm:
  1. Helpful
  1. Dan Black
  2. Friday, 20 September 2019 15:08 PM UTC
Thanks for you patience :)

I'm debugging now.
  1. Helpful
  1. Michael Kramer
  2. Friday, 20 September 2019 17:48 PM UTC
You're welcome. Dinner time now so I will check back in a few hours. /M
  1. Helpful
There are no comments made yet.
Michael Kramer Accepted Answer Pending Moderation
  1. Friday, 20 September 2019 00:33 AM UTC
  2. PowerBuilder
  3. # 4

Example of defining custom event for EventID = pbm_dwnTabOut

Attachments (1)
Comment
There are no comments made yet.
Dan Black Accepted Answer Pending Moderation
  1. Thursday, 19 September 2019 22:58 PM UTC
  2. PowerBuilder
  3. # 5

Thanks Miguel, Chris, and Michael,

I am starting think that the best way is to put everything in one datawindow. It will also be far easier to maintain if fields (or tables) are added in the future.

Dan

Comment
There are no comments made yet.
Miguel Leeuwe Accepted Answer Pending Moderation
  1. Thursday, 19 September 2019 21:46 PM UTC
  2. PowerBuilder
  3. # 6

Another thing to watch out for if you have more than one row on your datawindows.

Hitting enter and shift+enter key will change to next or previous row.

You can use the event mentioned by Michael "pbm_dwnProcessEnter" to prevent that from happening.

Comment
  1. Dan Black
  2. Thursday, 19 September 2019 22:47 PM UTC
Ya, I have come across posts about multiple rows and tabs/enters, but in this case it's just the one row in each datawindow.
  1. Helpful
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Thursday, 19 September 2019 20:59 PM UTC
  2. PowerBuilder
  3. # 7

Hi Dan;

  Are you using the PBM_DWNKEY event mapped to the DW Control via a User Event?

Regards ... Chris

Comment
  1. Dan Black
  2. Thursday, 19 September 2019 22:31 PM UTC
Yes, exactly as you describe.
  1. Helpful
There are no comments made yet.
Michael Kramer Accepted Answer Pending Moderation
  1. Thursday, 19 September 2019 20:55 PM UTC
  2. PowerBuilder
  3. # 8

Hi, there is a set of Tab event IDs associated with DataWindow controls. The IDs are:

  • pbm_dwnTabOut
  • pbm_dwnBackTabOut
  • pbm_dwnTabDownOut
  • pbm_dwmTabUpOut

These event IDs cover the TAB or arrow keys moving focus away from your DataWindow. Declare user event mapped to the Tab ID you need and you are good to go.

Inside the DataWindow there are event IDs for specific keys and keys in general:

  • pbm_dwEscape   <== Not DWN, only DW!
  • pbm_dwnProcessEnter
  • pbm_dwnKey

And you have the focus movement events as well:

  • ItemFocusChanged
  • RowFocusChanging
  • RowFocusChanged
  • GetFocus
  • LoseFocus

HTH /Michael

Comment
  1. Miguel Leeuwe
  2. Thursday, 19 September 2019 23:40 PM UTC
No they're quite old, I think at least since pb 6.5 or probably even earlier. To see them you have to do a "new event" and then pick them from the dropdown list under "event id" column.

The dw's key event with id "pb_dwnkey" that you are using also does not show by default, so has to have been added already by someone in the past. I guess that you'll be using some kind of ancestor object for your dw's, such as the u_dw of the pfc classes.
  1. Helpful
  1. Michael Kramer
  2. Friday, 20 September 2019 00:29 AM UTC
I created mapped user events back in PB4, maybe even PB3! True, not in predefined events list so you must create new events and map them to these EventIDs.

If you look at DataWindow's LoseFocus event you will see it is mapped to pbm_dwnKillFocus.

Each EventID has a predefined return datatype and parameter list. You can't change these.

I believe it was PB5 that introduced non-mapped user events so you can customize return type and parameter list just like for functions.

You will often find a user event for a DataWindow named ue_dropdown (or ue_dropdownopen) mapped to event ID pbm_dwnDropDown. That event fires immediately before a dropdown datawindow displays. This is where you find code like retrieving list of airports based on dynamically selected airline and departure airport.

HTH /Michael
  1. Helpful
  1. Michael Kramer
  2. Friday, 20 September 2019 00:33 AM UTC
I added reply #6 to include screen shot.
  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.