Changing tab order of controls while running

Discussion in 'Questions (Windows Mobile)' started by Woinowski, Jan 11, 2008.

  1. Woinowski

    Woinowski Active Member Licensed User

    I know how to change the tab order of controls in the designer (send to back), but I have an application with some runtime generated controls.

    Interestingly, the tab order is just the reverse of the generation order, which is slightly annoying (it would mean to use a For/Next Loop with STEP - 1 to get it all in the right order ;-)

    Therefore it would be very nice to be able to manipulate the tab order differently. Is this possible?
     
  2. Cableguy

    Cableguy Expert Licensed User

    You can use the lostfocus event to make the next control gain focus in the order you want...
     
  3. Woinowski

    Woinowski Active Member Licensed User

    Nice idea ...

    ... although a little bit like shooting yourself in the foot :sign0162:
     
  4. Cableguy

    Cableguy Expert Licensed User

    I don't really understand you'r comment...
    You say it's a nice idea, but a bit like shooting yourself in the foot, why? it gets the job done...
    Another way is to edit the spb file and invert the order of the control-creators code...
     
  5. willisgt

    willisgt Active Member Licensed User

    I'm having the same issue - a program which creates a great many controls dynamically, which really screws up the tab order. In my case, I always want the tab order to be the same, so I could potentially use Cableguy's idea of using the lostFocus event.

    Woinowski, it sounds as though you want to be able to manipulate the tab order any way you want. I haven't tried this one yet (probably will this weekend), but it might work...

    Put an ArrayList on your form. Every time you create a control dynamically, put the name of the control into the list. When you're finished creating controls, run through all of the items in the array list and do something like:

    Code:
    sub form1_SetTabOrder
       
    For i = 0 to ArrayList1.Count - 1
          
    Control( ArrayList1.Item(i) ).BringToFront
       
    Next
    end sub
    You could alter the tab order by removing items from and inserting items into the array list; just be sure to call the subroutine again when you're done changing the contents of the list.

    Like I say, I haven't tried this one yet.

    Gary
     
  6. Woinowski

    Woinowski Active Member Licensed User

    Why I think these solutions are strange

    Simple: Setting Focus according to tab order is something that can be handled perfectly well by the Framework (CF) or the Operating System (Windows [Mobile]).

    Also, it should be done this way.

    Faking (overriding) a tab order by catching events is something only real programmers do. :sign0060: Have a look at this http://www.pbm.com/~lindahl/real.programmers.html

    Probably you understand why I think this is shooting yourself into the foot. Hopefully, you haven't been offended by my answer.

    PS: Feels also a little bit like back in the good old VIC 20 times. :cool:
     
  7. agraham

    agraham Expert Licensed User

    Thanks for the link, I remember when that was published though I haven't seen it for years, nor the story of Mel. I have saved them to show and explain the to a younger generation! As you and I, apparently being of a certain age, know there is MORE than an element of truth in those tales of the early days.

    PS: TRS80-Model 1's set me off. - My brother was into Commodore Pets. Those machines set off the Motorola approach vs the Intel approach schism that persists in some form to this very day.
     
  8. willisgt

    willisgt Active Member Licensed User

    A problem with my approach...

    I finally got around to trying the solution I suggested (placing the names of the controls in an arrayList, running through the list, and using .bringToFront to set the tab order).

    The form this is called from contains a control called 'arrayFormMedsTabOrder'.

    Here's the relevant code:

    Code:
    sub formMeds_Show

       ...

          arrayFormMedsTabOrder.Add( 
    "formMedsHeader" )
          arrayFormMedsTabOrder.Add( 
    "labelMedsNDC" )
          arrayFormMedsTabOrder.Add( 
    "textMedsNDCLabeler" )
          arrayFormMedsTabOrder.Add( 
    "labelMedsNDCSep" )
          arrayFormMedsTabOrder.Add( 
    "textMedsNDCProduct" )
          arrayFormMedsTabOrder.Add( 
    "labelMedsProduct" )
          arrayFormMedsTabOrder.Add( 
    "textMedsProduct" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsSearch" )
          arrayFormMedsTabOrder.Add( 
    "labelMedsGeneric" )
          arrayFormMedsTabOrder.Add( 
    "textMedsGeneric" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsClear" )
          arrayFormMedsTabOrder.Add( 
    "labelMedsDose" )
          arrayFormMedsTabOrder.Add( 
    "textMedsDose" )
          arrayFormMedsTabOrder.Add( 
    "labelMedsRoute" )
          arrayFormMedsTabOrder.Add( 
    "comboMedsRoute" )
          arrayFormMedsTabOrder.Add( 
    "labelMedsFrequency" )
          arrayFormMedsTabOrder.Add( 
    "textMedsFrequency" )
          arrayFormMedsTabOrder.Add( 
    "labelMedsDiagnosis" )
          arrayFormMedsTabOrder.Add( 
    "textMedsDiagnosis" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsDXSearch" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsPrev" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsNext" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsMenu" )

          setFormTabOrder( 
    "formMeds" )

       ...

    end sub
    and...

    Code:
    Sub setFormTabOrder( pArray )

       ctl = 
    "array" & pArray & "TabOrder"
       
       
    For x = 0 To Control( ctl, ArrayList ).Count - 1
          
    ControlControl( ctl, ArrayList ).Item( x ) ).BringToFront
       
    Next

    End Sub
    The code produces no errors, but does not produce the desired tab order. In one place, it jumps halfway through the list; in another, it tabs backwards (relative to what I expect). It works properly on about the last half of the list.

    Anyone have any ideas?

    :sign0163:

    Gary

    (I finally have a free weekend, so I'll have to spend some of it dusting off my TRS-80, Atari 2600, or maybe the Exidy Sorcerer... ) :)
     
    Last edited: Jan 18, 2008
  9. agraham

    agraham Expert Licensed User

    Not really - I am sure that the array list will be in the correct order. I would try excluding from the list the form and labels as they cannot gain the focus so are not really in the tab order - see if that makes a difference.
     
  10. willisgt

    willisgt Active Member Licensed User

    I removed all the labels from the list. Changing the code to:

    Code:
    arrayFormMedsTabOrder.Add( "textMedsNDCLabeler" )
          arrayFormMedsTabOrder.Add( 
    "textMedsNDCProduct" )
          arrayFormMedsTabOrder.Add( 
    "textMedsProduct" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsSearch" )
          arrayFormMedsTabOrder.Add( 
    "textMedsGeneric" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsClear" )
          arrayFormMedsTabOrder.Add( 
    "textMedsDose" )
          arrayFormMedsTabOrder.Add( 
    "comboMedsRoute" )
          arrayFormMedsTabOrder.Add( 
    "textMedsFrequency" )
          arrayFormMedsTabOrder.Add( 
    "textMedsDiagnosis" )
          arrayFormMedsTabOrder.Add( 
    "textMedsDiagnosisDesc" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsDXSearch" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsPrev" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsNext" )
          arrayFormMedsTabOrder.Add( 
    "btnMedsMenu" )
    did not change the tab order. :sign0148:

    The behavior is the same whether I'm just running the code (F5), or a compiled executable.

    I've got to be missing something really simple here...

    Gary
     
  11. agraham

    agraham Expert Licensed User

    If you can post a bit code that shows the effect for you I'll have a play with it and see if it does the same here.
     
  12. willisgt

    willisgt Active Member Licensed User

    I've copied the relevant code into the attached example. It behaves exactly the same way as the larger application it was copied out of.

    Thanks for taking the time to look at this...

    Gary
     
  13. david

    david Member Licensed User

    Actuallly, I don't think you are missing anything simple.

    I have been doing work on a Wasp 3200 bar code device. I have to account for bar code input, key board input and sip input.

    In addition, I have to move the user back and forth between fields on lost focus events where I encounter errors.

    The primary spec. called for me to move the user around based upon hitting the enter key. That is relatively easy, but once you start adding error messages, on lost focus events and sometimes on key enter events, you start to get weird results.

    The particularly application that gave me the most trouble has 29 fields laid out on one screen but on various panels that I expose or hide depending upon the runtime data entry.

    I can get it to work perfectly when I create a windows executable, only to have it fail on the device side. Eventually, I used global error flags to keep track of where I was and how the application should respond.

    My particular problems seem to be the result of timing that varies from the windows executable (where I do my initial testing) to the finished product on the device.

    My conclusion is that it is entirely a Windows .Net problem. It has nothing to do with Basic4PPC (which I think is a wonderful development platform). My application ended working well, but with over 4,000 lines of code.

    If you remember, Sun Micro Systems Java advertisements, "Write Once Run Anywhere" and if you ever tried to implement that on multiple platforms, you will know that the slogan was true only if you didn't care which window appeared first or how the various dialogs appeared. I think Microsoft is coming up against the same problem. They will never admit it. They will just leave developers to think they are missing "something really simple".

    Good Luck.

    Regards,

    David
    P.S. I really do love Basic4PPC. However, Erel still must work within the confines of .NET. Don't blame him or the product. Just bear in mind that Basic4PPC is years ahead of Microsoft's own Visual Studio products for hand held development.
     
  14. willisgt

    willisgt Active Member Licensed User

    David, I'm curious to know more about your approach to this problem. How exactly did you make use of globals to solve the problem?

    In this case, the form is static and I can use .lostFocus to direct input to the next field. However, much of this application uses forms where the controls are generated dynamically. LostFocus gets a little dicey on those forms.

    So, while I'm hoping to resolve the problem with the code I posted (as it would solve my problem in all cases), I'm looking for alternatives in case it can't be resolved.

    This program gets released to our clients on Wednesday, whether the tab order is correct or not.

    :sign0082:

    Gary
     
  15. agraham

    agraham Expert Licensed User

    I've played with this now and yes, the tab order doesn't get set properly at runtime. However in the help BringToFront is only documented as setting the Z-order, i.e. the visible layering and not the tab order. It seems to be an unwarranted assumption that because BringToFront and SendToBack seem to affect both Z-order and Tab-Order in the Designer then BringToFront at runtime will do both as well.

    You probably know this, but in case others reading this are unaware of it, where the controls are created at design time you can get the tab order you want by selecting the controls by turn in the tab order you want and selecting SendToBack for each one. Whether this is by design, as it is not documented, or a welcome side effect I don't know.

    Perhaps Erel will comment if he catches this post?
     
  16. agraham

    agraham Expert Licensed User

    You could try playing with this library. No guarantees that it will always work. Only works in optimised compile mode - will warn otherwise.

    Code:
    TabOrder.New1(B4PObject(1),TabControlNames(),NumOfControls)
    Invoke it as above passing an array of the controls in the required tab order together with how many of them are in the array. If you don't pass all the tabbable controls on a form then you may get odd results.

    Version of your example enclosed that tabs properly. I've hacked the library into it - you will want to tidy it up.
     
  17. willisgt

    willisgt Active Member Licensed User

    Very cool - it does exactly what I need!

    Naturally, this is something I ( and probably more than a few others ) would like to see incorporated into, say, ControlsEX.dll.

    Thanks again for taking time to look at this!

    Gary
     
  18. Cableguy

    Cableguy Expert Licensed User

    All this can be very easely avoided if we can do 2 "simple" things:

    1-Plan better our apps and the controls we wich to incorporate...and create/place them at runtime in the inverse order, we wich the tabs to be...
    2-Edit or create an automated (app) editing tool to re-write the control creation lines in the .b4p file.

    Still I set back and was hopping to see what Agrahams aproch would bring, results wise, and as I espected, only the z-order gets changed...
    This is a very common confusion...z-orde=tab order? = FALSE...
    So now, and using the words of david:
    "In addition, I have to move the user back and forth between fields on lost focus events where I encounter errors."

    Wich takes me to my first reply to this thread...
     
  19. agraham

    agraham Expert Licensed User

    Sorry Cableguy - I DO understand the differences between tab order and z-order as is clear from my post #15. It IS the tab order that my little library sets. In fact it sets the TabIndex property for each control given to it in the order in which they are placed in the array and obviously works for me and Gary. It needs a library as this property is not available in B4PPC. Why do you think it is setting the z-order?
     
  20. Cableguy

    Cableguy Expert Licensed User

    I was not refering to your DLL, but to the array/bringtofront aproach...
    Sorry if I was somewhat missunderstood...

    Still, if the only need is to invert the tab-order, a simple "batch" app would fullfill the need, editing the spb file, and reversing the object creation order..
    Your DLL is very usefull, and this feature is also handy if one set the control in an non-inverted tab order....
     
Loading...