Announcement

Collapse
No announcement yet.

Double Focus..

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Double Focus..

    This probably belongs to
    - "Doctor, doctor, my arm hurts when I do like this!"
    - "Then don't do like that. Next please.."

    Click image for larger version  Name:	DualFocus.jpg Views:	15 Size:	11.0 KB ID:	783533
    How many controls can have focus? I have seen some strange focus problems with DDT dialogs, but this one was new to me. At least from what I can remember. If a listbox is created before other controls, pressing Tab results in that both the ListBox and next control will get a focus rect. Not a big problem and easily fixed, but funny to see two controls get focus at same time. Following code shows "problem" - compile, run and press Tab key to see dual focus effect. Press once more and ListBox + Button 2 gets focus. And no, adding a Dialog procedure changes nothing - it's creation order that matters - if buttons or some other control is created first, problem is gone.
    Code:
    #COMPILE EXE
    #INCLUDE "WIN32API.INC"
    %IDC_LISTBOX1 = 161
    
    '====================================================================
    FUNCTION PBMAIN () AS LONG
      LOCAL c, hDlg AS LONG
    
      DIALOG NEW 0, "Press Tab key",,, 170, 118, %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg
    
      '------------------------------------------------------------------
      CONTROL ADD LISTBOX, hDlg, %IDC_LISTBOX1, , 5, 6, 102, 120
      FOR c = 1 TO 10
          LISTBOX ADD hDlg, %IDC_LISTBOX1, FORMAT$(c, "00")
      NEXT
      '-------------------------------------------------------------------
      CONTROL ADD BUTTON, hDlg, %IDOK,     "Button 1", 115,  80, 50, 14
      CONTROL ADD BUTTON, hDlg, %IDCANCEL, "Button 2", 115, 100, 50, 14
    
      '-------------------------------------------------------------------
      DIALOG SHOW MODAL hDlg
    
    END FUNCTION
    Last edited by Borje Hagsten; 4 Aug 2019, 08:18 AM.

  • #2
    Good morning, Borje!

    After pressing TAB, the focus goes to the button. The rectangle left behind in the ListBox is not a focus rectangle, but rather an item-selected rectangle. Yes?

    Isn't this analogous to the windows setting for a ListView that allows the current selection to remain visible when focus is lost?

    Comment


    • #3
      Gary,
      I believe you are spot on. The focus should be indicated by the highlighting around the button edge. Easy to test the focus. Press the SPACE BAR or ENTER. Yes?

      Comment


      • #4
        Yes, but since nothing is selected, there should be no focus rect in list and from what I have learned over the years - there should only be one focus rect. If I start the test prog and press down arrow, first item is selected in list (without focus rect, in spite down arrow indicates ListBox has focus at start!) - then press Tab, I same same result - focus rect on both the selected item and a button. Like I said, behaviour changes if a button - or any other control - is created first, then all is like it should be. See also DrawFocusRect. Have only seem this dual forus rect issue in DDT dialogs, so something is different under the hood there. Not a big problem, only I haven't seen it happen like this before.

        Comment


        • #5
          Borje,
          If memory serves me correctly it seems like I have run into this effect on the SDK side as well. Hard to pin down exactly. You know me, I do some weird stuff until I get it the way I think it should be. Likely I avoided that behavior by creating another control first.

          One way I have avoided it is by using owner drawn buttons and assigning focus to the listbox after I create the page of controls. Usually I do not use the TAB to move from button to button. Voice control makes the mouse and keyboard inputs nearly obsolete for my apps so I really don't need that functionality. Yes, I know that is radical. But hey, the method alleviates the need to track the focus from button to button. Much simpler to program. I use TAB only in textboxes.

          I hope this helps.
          Last edited by Jim Fritts; 4 Aug 2019, 04:03 PM.

          Comment


          • #6
            Hi Börje,

            Interesting...
            I have only one focus rectangle using SDK CreateWindow() for the main window and controls.
            If I build the same dialog using SDK DialogBoxIndirectParam() instead of DDT,
            with controls in the same order then I got the same behavior as you do.
            So it seems that it is more a Microsoft thing than a DDT one.
            Last edited by Pierre Bellisle; 5 Aug 2019, 08:49 AM.

            Comment


            • #7
              Pierre,
              Thank you for doing that test.

              Borje,
              Another way I use to hide that behavior is to add the listbox data after the other controls are created. That changes the focus. Right?
              Last edited by Jim Fritts; 4 Aug 2019, 04:02 PM.

              Comment


              • #8
                Good to know, Pierre - thanks!
                No Jim, same result if items are added last. Control creation order seems to be what counts. It is also interesting to see that if one start the test program and press down arrow first, item 1 in listbox is selected - this showing that listbox has focus (as it should, being the first control created = top zorder) - but no focus rect is drawn until I press tab key, then both button and selected listbox item gets focus rect. Windows dialog engine moves in mysterious ways.

                Comment


                • #9
                  Borje,
                  I see what is going on. The Listbox is defaulted as %WS_TABSTOP so once you press the TAB button then button 1 has the highlight and focus. Press the TAB button again and button 2 has the highlight and focus. Press the TAB button again and the Listbox has the focus but button 1 has the highlight indicating the default button when the Listbox gets the focus. Which is the same button that is highlighted if you click off the dialog and back on the dialog unless button 2 had the focus when you clicked off the dialog then the focus returns to button 2 when you click back on the dialog.

                  Once the focus is back on the Listbox then you will likely need to refresh the button statuses to not highlighted. (I haven't had to do that for a while.)

                  In this case when button 2 loses focus to the listbox the system is confused. Focus goes to the Listbox while the highlight goes to the default button.

                  Note:
                  After the initial TAB press UP DOWN arrows will do the same thing. When the focus gets to the Listbox it is stuck there until you press the TAB button again.

                  See that is why I don't use TABs.

                  Comment


                  • #10
                    Borje,

                    Dialog's "mysterious ways"

                    The problem seems to be related to the way that UI cues are shown.

                    Initially, the default is for UI Cues to be hidden until after there has been a user action - key(arrow, Tab) or mouse press

                    It's interesting to note that if either one of your test buttons are clicked before the first tab or arrow key press occurs, the Listbox behaviour is modified and it no longer displays a focus rectangle 'out of turn'.

                    Also noted that Button 1 gets it's darker (default button) outline courtesy of it's ID (%IDOK) (rather than it's tab order). If you change the ID eg to 1001, there is no heavy border on the button unless it has focus.


                    As you commented, there are several ways that the observed 'problem' can be avoided including:

                    ~ The order in which controls are created.
                    ~ Using a Themed Dialog (Common-Controls version 6)
                    ~ Show the Dialog with UI cues initially NOT hidden.
                    Code:
                        Dialog Send hDlg, %WM_UPDATEUISTATE, MakLng(%UIS_CLEAR, %UISF_HIDEFOCUS Or %UISF_HIDEACCEL), 0  ' don't hide cues
                      DIALOG SHOW MODAL hDlg
                    Rgds, Dave

                    Comment


                    • #11
                      Click image for larger version  Name:	New Bitmap Image.jpg Views:	0 Size:	11.0 KB ID:	783618
                      This is interesting. Double Highlight.
                      NOTE:
                      The TAB stop at the listbox was removed.

                      Code:
                      #COMPILE EXE
                      #INCLUDE "WIN32API.INC"
                      %IDC_LISTBOX1 = 161
                      'For Borje
                      'Something interesting. I hope you enjoy it.
                      GLOBAL hDlg AS DWORD
                      GLOBAL LastButton         AS INTEGER
                      
                      '====================================================================
                      FUNCTION PBMAIN () AS LONG
                        LOCAL c AS LONG
                      
                        DIALOG NEW 0, "Press Tab key",,, 170, 150, %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg
                      
                        '------------------------------------------------------------------
                        CONTROL ADD LISTBOX, hDlg, %IDC_LISTBOX1, , 5, 6, 102, 120, %LBS_STANDARD, %WS_EX_CLIENTEDGE
                        FOR c = 1 TO 10
                            LISTBOX ADD hDlg, %IDC_LISTBOX1, FORMAT$(c, "00")
                        NEXT
                        '-------------------------------------------------------------------
                        'When you click on the listbox then the default button is highlighted (%IDCANCEL)
                        CONTROL ADD BUTTON, hDlg, %IDCANCEL, "Cancel", 115, 80, 50, 14, %BS_DEFPUSHBUTTON OR %WS_TABSTOP
                        CONTROL ADD BUTTON, hDlg, 50, "Other", 115, 100, 50, 14, %WS_TABSTOP
                        CONTROL ADD BUTTON, hDlg, %IDOK,     "Ok", 115,  60, 50, 14, %WS_TABSTOP
                      
                        '-------------------------------------------------------------------
                      
                        DIALOG SHOW MODAL hDlg CALL DlgProc  'JF added
                        'DIALOG SHOW MODAL hDlg
                      
                      END FUNCTION
                      
                      '_________________________________________________________________ JF added
                      '
                      ' SUB SetButtonFocus(hDlgName, %ID_SELECTEDBUTTON, %ID_DEFAULTBUTTON)
                      '_________________________________________________________________
                      
                      SUB SetButtonFocus(BYVAL hDlgName AS DWORD, AAA AS INTEGER, BBB AS INTEGER)
                      
                        CONTROL SEND hDlgName, AAA, %BM_SETSTYLE, %BS_PUSHBUTTON, %TRUE
                        CONTROL SET FOCUS hDlgName, BBB
                        CONTROL SEND hDlgName, BBB, %BM_SETSTYLE, %BS_DEFPUSHBUTTON, %TRUE
                      
                        LastButton = BBB   'the last button with focus
                      END SUB
                      
                      
                      CALLBACK FUNCTION DlgProc() AS LONG
                          SELECT CASE CB.MSG
                              CASE %WM_INITDIALOG
                              CASE %WM_COMMAND
                                  SELECT CASE CB.CTL
                                      CASE %IDOK
                                          'When you press OK the CANCEL button is highlighted.
                                          'This is interesting:
                                          'If the OK button is pressed and the focus was previously on the Listbox then
                                          'both the OK button and the OTHER button are highlighted.
                                          SetButtonFocus(hDlg, %IDOK, %IDCANCEL)
                                      CASE %IDCANCEL
                                          'When you press CANCEL the OTHER button is highlighted
                                          SetButtonFocus(hDlg, %IDCANCEL, 50)
                                      CASE 50
                                          'When you press OTHER the OK button is highlighted
                                          SetButtonFocus(hDlg, 50, %IDOK)
                      
                                      CASE %IDC_LISTBOX1
                                          SELECT CASE CB.CTLMSG
                      
                                              CASE %LBN_SETFOCUS
                                                  '? "here 1"
                                                  'When the listbox gains focus then the default button is highlighted (%IDCANCEL)
                                              CASE %LBN_KILLFOCUS
                                                  '? "here 2"
                                                  'When the list box loses focus by pressing on a button like OK or CANCEL the OTHER button is highlighted
                                                  SetButtonFocus(hDlg, %IDCANCEL, 50)
                                          END SELECT
                                  END SELECT
                          END SELECT
                      END FUNCTION

                      Comment


                      • #12
                        More traditional method that does act correctly with a little help.

                        Code:
                        #COMPILE EXE
                        #INCLUDE "WIN32API.INC"
                        %IDC_LISTBOX1 = 161
                        'For Borje
                        'More traditional method
                        GLOBAL hDlg AS DWORD
                        GLOBAL LastButton         AS INTEGER
                        
                        '====================================================================
                        FUNCTION PBMAIN () AS LONG
                          LOCAL c AS LONG
                        
                          DIALOG NEW 0, "Press Tab key",,, 170, 150, %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg
                        
                          '------------------------------------------------------------------
                          CONTROL ADD LISTBOX, hDlg, %IDC_LISTBOX1, , 5, 6, 102, 120, %LBS_STANDARD, %WS_EX_CLIENTEDGE
                          FOR c = 1 TO 10
                              LISTBOX ADD hDlg, %IDC_LISTBOX1, FORMAT$(c, "00")
                          NEXT
                          '-------------------------------------------------------------------
                          'When you click on the listbox then the default button is highlighted (%IDCANCEL)
                          CONTROL ADD BUTTON, hDlg, %IDCANCEL, "Cancel", 115, 80, 50, 14, %BS_DEFPUSHBUTTON OR %WS_TABSTOP
                          CONTROL ADD BUTTON, hDlg, 50, "Other", 115, 100, 50, 14, %WS_TABSTOP
                          CONTROL ADD BUTTON, hDlg, %IDOK,     "Ok", 115,  60, 50, 14, %WS_TABSTOP
                        
                          '-------------------------------------------------------------------
                        
                          DIALOG SHOW MODAL hDlg CALL DlgProc  'JF added
                          'DIALOG SHOW MODAL hDlg
                        
                        END FUNCTION
                        
                        '_________________________________________________________________ JF added
                        '
                        ' SUB SetButtonFocus(hDlgName, %ID_SELECTEDBUTTON, %ID_DEFAULTBUTTON)
                        '_________________________________________________________________
                        
                        SUB SetButtonFocus(BYVAL hDlgName AS DWORD, AAA AS INTEGER, BBB AS INTEGER)
                        
                          CONTROL SEND hDlgName, AAA, %BM_SETSTYLE, %BS_PUSHBUTTON, %TRUE
                          CONTROL SET FOCUS hDlgName, BBB
                          CONTROL SEND hDlgName, BBB, %BM_SETSTYLE, %BS_DEFPUSHBUTTON, %TRUE
                        
                          LastButton = BBB   'the last button with focus
                        END SUB
                        
                        
                        CALLBACK FUNCTION DlgProc() AS LONG
                            SELECT CASE CB.MSG
                                CASE %WM_INITDIALOG
                                    SetButtonFocus(hDlg, LastButton, %IDCANCEL)
                        
                                CASE %WM_COMMAND
                                    SELECT CASE CB.CTL
                                        CASE %IDOK
                                            SetButtonFocus(hDlg, LastButton, %IDOK)
                                        CASE %IDCANCEL
                                            SetButtonFocus(hDlg, LastButton, %IDCANCEL)
                                        CASE 50
                                            SetButtonFocus(hDlg, LastButton, 50)
                        
                                        CASE %IDC_LISTBOX1
                                            SELECT CASE CB.CTLMSG
                        
                                                CASE %LBN_SETFOCUS
                                                    LastButton = %IDCANCEL
                        
                                                CASE %LBN_KILLFOCUS
                                            END SELECT
                                    END SELECT
                            END SELECT
                        END FUNCTION

                        Comment


                        • #13
                          Yes Jim, there are some things to consider when using dialog engine. Creation order (zorder) is one. I remember we had discussions about tab control in a dialog years ago and the outcome of those I think was to insert an "invisible" label first, before the actual tab dialogs, else focus would not work like it should with the tab control. Thanks for testing different ways and show other "problems" and their solution.

                          Comment


                          • #14
                            Yes, Borje, I vaguely remember the same discussion. You are welcome.

                            Comment

                            Working...
                            X