Announcement

Collapse
No announcement yet.

Editing Textbox contents

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

    Editing Textbox contents

    I'm a newbie to PowerBasic and not very proficient at VB, but I've written some fairly complex stuff in VB long ago. I'm using PB because I want to create distributable code that doesn't require .net.

    I am trying to create an application that students can use to estimate what their grade will be by entering scores they've got and possible scores on future assignments. Very simple in concept. Several text boxes where decimal numbers can be entered and a couple of buttons.

    I'm having trouble controlling the focus. My intent is to validate data upon its display back to the user, and if the data is in error and display a message box indicating what's wrong. I want to prevent focus from changing so long as there is an error in the content of a textbox.

    Below is an extract of my code which demonstrates my problem. When an error occurs in the content of the 2nd textbox, focus transfers to the 1st textbox, and won't change until I type something in the first textbox. I can't figure out what's happening and thus can't fix it. It must have something to do with the flow of control via the messages, but I'm so ignorant of message flow it's pathetic. I hope to fix that as time goes on, but for now if anyone can explain what's happening and/or how to get the focus in the right place (on the textbox containing the error), I would much appreciate it.

    Thanks in advance,
    Steve
    Code:
    #PBFORMS CREATED V1.51
    #COMPILE EXE
    #DIM ALL
    '------------------------------------------------------------------------------
    ' ** Includes **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN INCLUDES
    #IF NOT %DEF(%WINAPI)
    #INCLUDE "WIN32API.INC"
    #ENDIF
    #INCLUDE "PBForms.INC"
    #PBFORMS END INCLUDES
    '------------------------------------------------------------------------------
    '------------------------------------------------------------------------------
    ' ** Constants **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN CONSTANTS
    %IDD_DIALOG1 = 101
    %IDC_LBL_HomeworkScore = 1001
    %IDC_LBL_ExamScores = 1002
    %IDC_TB_HomeworkScore = 1005
    %IDC_TB_Exam1Score = 1006
    %IDC_TB_FinalExamScore = 1012
    %IDC_BN_Estimate = 1014
    %IDC_BN_Exit = 1015
    #PBFORMS END CONSTANTS
     
    '------------------------------------------------------------------------------
    '------------------------------------------------------------------------------
    ' ** Declarations **
    '------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS DECLARATIONS
    '------------------------------------------------------------------------------
    '------------------------------------------------------------------------------
    ' ** Main Application Entry Point **
    '------------------------------------------------------------------------------
    FUNCTION PBMAIN()
    GLOBAL SizeError, ThisScore AS LONG
    ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION
    '------------------------------------------------------------------------------
    '------------------------------------------------------------------------------
    ' ** CallBacks **
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
      LOCAL EditString, GoodDataString AS STRING
      LOCAL Category, Assignment AS LONG
      SELECT CASE AS LONG CB.MSG
         CASE %WM_INITDIALOG
         ' Initialization handler
         CASE %WM_NCACTIVATE
            STATIC hWndSaveFocus AS DWORD
            IF ISFALSE CB.WPARAM THEN
            ' Save control focus
            hWndSaveFocus = GetFocus()
           ELSEIF hWndSaveFocus THEN
           ' Restore control focus
              SetFocus(hWndSaveFocus)
              hWndSaveFocus = 0
           END IF
        CASE %WM_COMMAND
        ' Process control notifications
           SELECT CASE AS LONG CB.CTL
              CASE %IDC_TB_HomeworkScore
                  ThisScore=%IDC_TB_HomeworkScore
                  IF CB.CTLMSG = %EN_KILLFOCUS THEN
                     IF SizeError THEN
                        CONTROL SET FOCUS CB.HNDL, ThisScore
                     END IF
                 END IF
                 IF CB.CTLMSG = %EN_CHANGE THEN ' after typed data is displayed back to user
                    SizeError=0
                    CONTROL GET TEXT CB.HNDL, ThisScore TO EditString
                      IF VAL(EditString)>100 THEN
                         SizeError=-1
                         MSGBOX "Must be 100 or less", %MB_TASKMODAL
                         CONTROL SET FOCUS CB.HNDL, ThisScore
                      END IF
                 END IF
             CASE %IDC_TB_Exam1Score
                 ThisScore=%IDC_TB_Exam1Score
                 IF CB.CTLMSG = %EN_KILLFOCUS THEN
                    IF SizeError THEN
                       CONTROL SET FOCUS CB.HNDL, ThisScore
                    END IF
                END IF
            IF CB.CTLMSG = %EN_CHANGE THEN ' after typed data is displayed back to user
                SizeError=0
                CONTROL GET TEXT CB.HNDL, ThisScore TO EditString
                IF VAL(EditString)>100 THEN
                   SizeError=-1
                   MSGBOX "Must be 100 or less", %MB_TASKMODAL
                   CONTROL SET FOCUS CB.HNDL, ThisScore
                END IF
           END IF
     
       CASE %IDC_BN_Estimate
           IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
              MSGBOX "%IDC_BN_Estimate=" + _
              FORMAT$(%IDC_BN_Estimate), %MB_TASKMODAL
           END IF
       CASE %IDC_BN_Exit
          IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
              DIALOG END CBHNDL, %IDD_Dialog1
          END IF
      END SELECT
    END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    '------------------------------------------------------------------------------
    ' ** Dialogs **
    '------------------------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    LOCAL lRslt AS LONG
    #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
    LOCAL hDlg AS DWORD
    LOCAL hFont1 AS DWORD
    LOCAL hFont2 AS DWORD
    DIALOG NEW hParent, "Grade Estimator", 105, 91, 320, 385, TO hDlg
    CONTROL ADD LABEL, hDlg, %IDC_LBL_HomeworkScore, "Homework Score", 10, _
    20, 100, 20
    CONTROL ADD LABEL, hDlg, %IDC_LBL_ExamScores, "Exam Scores", 30, 60, _
    80, 20
    20
    CONTROL ADD TEXTBOX, hDlg, %IDC_TB_HomeworkScore, "", 115, 30, 45, 20, _
    %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %ES_RIGHT OR _
    %ES_AUTOHSCROLL, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR _
    %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
    CONTROL ADD TEXTBOX, hDlg, %IDC_TB_Exam1Score, "", 115, 70, 45, 20, _
    %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %ES_RIGHT OR _
    %ES_AUTOHSCROLL, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR _
    %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
    CONTROL ADD BUTTON, hDlg, %IDC_BN_Estimate, "Estimate", 10, 350, 55, 20
    CONTROL ADD BUTTON, hDlg, %IDC_BN_Exit, "Exit", 255, 350, 45, 20
    hFont1 = PBFormsMakeFont("MS Sans Serif", 16, 400, %FALSE, %FALSE, _
    %FALSE, %ANSI_CHARSET)
    hFont2 = PBFormsMakeFont("MS Sans Serif", 12, 400, %FALSE, %FALSE, _
    %FALSE, %ANSI_CHARSET)
    DIALOG SEND hDlg, %WM_SETFONT, hFont1, 0
    CONTROL SEND hDlg, %IDC_LBL_HomeworkScore, %WM_SETFONT, hFont2, 0
    CONTROL SEND hDlg, %IDC_LBL_ExamScores, %WM_SETFONT, hFont2, 0
    CONTROL SEND hDlg, %IDC_TB_HomeworkScore, %WM_SETFONT, hFont2, 0
    CONTROL SEND hDlg, %IDC_TB_Exam1Score, %WM_SETFONT, hFont2, 0
    CONTROL SEND hDlg, %IDC_BN_Estimate, %WM_SETFONT, hFont2, 0
    CONTROL SEND hDlg, %IDC_BN_Exit, %WM_SETFONT, hFont2, 0
    #PBFORMS END DIALOG
    DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
    DeleteObject hFont1
    DeleteObject hFont2
    #PBFORMS END CLEANUP
    FUNCTION = lRslt
    END FUNCTION
    Last edited by Steve Frye; 22 May 2009, 07:09 PM.

    #2
    A. Please read up on How to use Code Tags and edit your post to add same .
    B. here
    Code:
     
    IF VAL(EditString)>100 THEN
       SizeError=-1
       MSGBOX "Must be 100 or less", %MB_TASKMODAL
    END IF
    ... you need to set the focus after the MSBOX is dismissed, because clicking OK takes the focus. Eg
    Code:
     
    IF VAL(EditString)>100 THEN
       SizeError=-1
       MSGBOX "Must be 100 or less", %MB_TASKMODAL
       CONTROL SET FOCUS   where_to_go_following_an_error 
    END IF
    FWIW, 'controlling the focus when doing character by character edits" has been the subject of many threads here.

    Also FWIW, for your numeric field edits, have you considered using style ES_NUMBER and then sending the EM_SETLIMITTEXT message to limit the number of digits which may be entered? It won't help above because "100" has three digits but so does "999" - but if you have a "zero to 99" limiting text to two numeric digits is pretty easy to handle by letting Windows do the dirty work.

    MCM
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


      #3
      Thank you for your suggestion. However, I did try putting a set focus after the msgbox as you suggested. It doesn't change the behavior. That is when I pulled out my last remaining hair and posted my plea.

      I looked at defining the textbox as numeric, but that apparently excludes decimal points. Plus, long ago, I wrote a program to collect data and assumed that a numeric edit would ensure a nice numeric number. Having assured my teamlead that my code was unbreakable, I watched him enter a string of decimal points which promptly broke my code. So I'm doing more extensive editing than is contained in my extract. I just wanted as simple a bit of code as possible and still illustrate the problem.

      I've looked at lots of the posts that talk about keystroke editing. I need to understand eventually, but right now I don't need keyup and keydown and the detailed control those posts are after. I'm happy with my ability to edit the data; I just can't control the focus.

      And thanks for the link. I'll fix the my original post soon.

      Steve Frye

      Comment


        #4
        Steve, you can check for values in the Callback. This example doesn't care how many decimals there are (for example) as long as the value is over 1.


        '[code]'
        Code:
        'PBWIN 9.01 - WinApi 05/2008 - XP Pro SP3
        #Dim All 
        #Compile Exe  
        #Optimize SPEED
        #Debug Display On'off for production code
         
        #Include "WIN32API.INC"
        #Include "COMDLG32.INC"
        #Include "InitCtrl.inc"
        '
        Global hdlg As Dword                
        %Id_Exit_Btn = 1000
        %Id_Sample_Textbox = 1001
        %Id_Show_Result_Btn = 1002
        ' 
        Macro Common_Locals 'Macro easier than retyping and maintains coding consistency
          Global Dlg_hght, Dlg_Wd As Long 'Global in case want to use in Controls
          Local Stile, Row, col, hght, wd, Longest,ctr, ln, ln1, i As Long
          Local  l, s As String
        End Macro  
        '
        CallBack Function Dialog_Processor              
          Common_Locals                                           
          Select Case CbMsg     'This is TO determine the message TYPE 
             '       
             Case %WM_INITDIALOG'<- Initialiaton when the program loads 
               Control Set Focus CB.Hndl, %Id_Sample_Textbox
             '
             Case %WM_SYSCOMMAND 'Traps Any Alt key but only F4 closes              
             '
             Case %WM_COMMAND  'This processes command messages
               Select Case CbCtl
         [B]        Case %Id_Show_Result_Btn [/B]
        [B]        [COLOR=red]   Control Get Text CbHndl, %Id_Sample_Textbox To l$[/COLOR][/B]
        [B][COLOR=red]             Local Grade01 As Single[/COLOR][/B]
        [B][COLOR=red]             Grade01 = Val(l$)[/COLOR][/B]
        [B][COLOR=red]              If Grade01 > 100 Then [/COLOR][/B]
        [B][COLOR=red]                ? "Grade over 100 not allowed", , FuncName$[/COLOR][/B]
        [B][COLOR=red]                  Control Set Focus CB.Hndl, %Id_Sample_Textbox[/COLOR][/B]
        [B][COLOR=red]               ElseIf grade01 < 1  Then[/COLOR][/B]
        [B][COLOR=red]                ? "Grade under 1 not allowed", , FuncName$[/COLOR][/B]
        [B][COLOR=red]                  Control Set Focus CB.Hndl, %Id_Sample_Textbox[/COLOR][/B]
        [B][COLOR=red]                Else 'grade good to here[/COLOR][/B]
        [B][COLOR=red]                 ? Using$("Good Grade of ###.##", Grade01),, FuncName$[/COLOR][/B]
        [B][COLOR=red]          '       Control Set Focus CB.Hndl, %Next_Grade_box[/COLOR][/B]
        [B][COLOR=red]              End If[/COLOR][/B]
                 Case %Id_Exit_Btn
                   Select Case CbCtlMsg        
                      Case 0
                        Dialog End CbHndl 'Applikation beenden
                   End Select
               End Select
          End Select
        End Function
        '
        Function PBMain
          Common_Locals
         
           Stile = Stile Or %WS_CAPTION
           Stile = Stile Or %WS_SYSMENU
           Stile = Stile Or %WS_THICKFRAME 
           Stile = Stile Or %WM_HELP 
           Stile = Stile Or %WS_Border  'doesn't do anything
          Dlg_hght = 100
          Dlg_Wd = 400
          'Dialog Font "Consolas", 72 ' Big Unicodes
          Dialog New Pixels, hdlg, "Demo", , , Dlg_Wd, Dlg_Hght, Stile To hdlg 'centered
          Row = 10
          col = 10
          Wd = 40
          Hght = 12
          Control Add Label, hdlg, -1, " Algebra ", Col, Row, Wd, Hght
         
          s$ = " "
          Reset stile  'not needed here       
          Col = Col + Wd + 10 'just past label 
          Hght =  20' 15 * 10 'Plenty room for 10 lines of text
          Wd = 50 'Dlg_Wd - 40 - 30 'minus the label and leave a little
          Control Add TextBox, hdlg, %Id_Sample_Textbox, s$, Col, Row, Wd, Hght, Stile
           hght = 25   
           Wd = Dlg_Wd - 20
           Col = 10 'center
           Row = Dlg_hght - (Hght * 2) - 4 'Just off bottom
             Control Add Button, hdlg, %Id_Show_Result_Btn, "Show Textbox Results", col, row, Wd, Hght
           Row = Dlg_hght - Hght - 2 'Just off bottom
             Control Add Button, hdlg, %Id_Exit_Btn, "Abandon Ship", col, row, Wd, Hght
         
             Dialog Show Modal hDlg   Call Dialog_Processor
        End Function  'Applikation beenden
        '
        It's a pretty day. I hope you enjoy it.

        Gösta

        JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
        LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

        Comment


          #5
          Gosta,

          I think you misunderstood my problem. I can edit the contents fine; I can't control the focus.

          Editing: For decimal points, I use parsecount(string,".") and if the result is greater than 2 then I know there are too many decimal points. To check for non-numerics, I remove$(string, ANY "0123456789.") and if the length of the resulting string is greater than 0 then there are non-numerics in the string. With these two tests I'm sure the content is a valid number.

          Your code accepts 1.1.1 and returns 1.10; it accepts 1a5 and returns 1.00. I've learned from long experience that anything that can be entered will be entered, so I need to ensure that I detect all invalid data and nag the user until he/she corrects it or quits. I also want to detect the errors while the user is entering each score rather than waiting until all scores are entered and the "estimate" button is clicked.

          My problem is the control of the focus. After I detect an error in ANY text box (my program has 8 textbox controls) and display a messagebox, the focus always comes back to the first textbox. I have tried setting the focus at different locations in the code; tried using the equate instead of the ThisScore variable; tried commenting out the %WM_NCACTIVATE case (because the documentation says that it controls the focus in some circumstances). But always the first textbox gets the focus after an error in any textbox is detected.

          Steve

          Comment


            #6
            Can you post a sample? (Seeing how its your code you are writing).

            I have seen similar problems sending keys from one app to another (One I wrote, One that someone else wrote), but seeing code from the writer of both and demonstrates the problem goes a LONGGGGgggg way for a "pair of fresh eyes"
            Engineer's Motto: If it aint broke take it apart and fix it

            "If at 1st you don't succeed... call it version 1.0"

            "Half of Programming is coding"....."The other 90% is DEBUGGING"

            "Document my code????" .... "WHYYY??? do you think they call it CODE? "

            Comment


              #7
              Steve, a couple of things. I think you should put the
              Static hWndSaveFocus AS DWORD above the select case with the local
              declarations in the callback. You might try a Sleep and/or EXIT FUNCTION
              with the set focus. Sleep after the message box and before the set focus,
              and exit function after the set focus.
              Client Writeup for the CPA

              buffs.proboards2.com

              Links Page

              Comment


                #8
                Cliff,
                Please see the first post in this thread for code that demonstrates my problem.

                An additional piece information. To test the code I enter 111 in the second textbox. When the first 1 is entered, it is echoed to the screen and the focus remains with the second text box as expected; When the 2nd 1 is entered, it is echoed to the screen and the focus remains on the 2nd textbox as expected; when I enter the third 1, it is echoed to the screen and the msgbox appears as expected; when I respond to the msgbox, the focus is now in the first textbox. To complicate matters, I put an if statement above the size test saying "if len(editstring)>1 then msgbox "testing" ". So after the 2nd 1 is echoed to the screen, this testing box is displayed. After responding to the message box, the focus is on the SECOND textbox as it should be.

                Why should an "if" and msgbox after the 2nd 1 produce different results from an "if" (which essentially detects the third digit) and msgbox after the 3rd 1 produce a shift in focus?

                I'll appreciate any help your fresh eyes.

                Steve

                Comment


                  #9
                  Fred,
                  The "Static hWndSaveFocus AS DWORD" was generated in that location by PBForms. But I moved it and no joy. I tried your suggestion and put "exit function" after the "control set focus", but also no joy. "sleep 20"....no joy.

                  Thanks for your thoughts.

                  Steve

                  Comment


                    #10
                    Originally posted by Steve Frye View Post
                    Gosta,

                    I think you misunderstood my problem. I can edit the contents fine; I can't control the focus.
                    I thought I did understand your problem (at least as you stated it). You said you were having s problem with too many decimals (for example). I showed that. I didn't think you needed to be shown how to trap every mis entry

                    You said you were having a problem with focusing. The example I showed doesn't have a focus problem and shows how to (re)set focus to the offending control.

                    Is this any closer?

                    '
                    Code:
                    'PBWIN 9.01 - WinApi 05/2008 - XP Pro SP3
                    #Dim All 
                    #Compile Exe  
                    #Optimize SPEED
                    #Debug Display On'off for production code
                     
                    #Include "WIN32API.INC"
                    #Include "COMDLG32.INC"
                    #Include "InitCtrl.inc"
                    '
                    Global hdlg As Dword                
                    %Id_Exit_Btn = 1000
                    %Id_Algebra_Tb = 100
                    %Id_History_TB = 101
                    %Id_Chemistry_TB = 102
                    %Id_Grades_Avg_TB = 200
                    %Id_Show_Result_Btn = 1002
                    ' 
                    Macro Common_Locals 'Macro easier than retyping and maintains coding consistency
                      Global Dlg_Ht, Dlg_Wd As Long 'Global in case want to use in Controls
                      Local Id, Stile, Row, col, Ht, wd, Longest,ctr, ln, ln1, i As Long
                      Local  l, s As String
                    End Macro  
                    '
                    CallBack Function Dialog_Processor              
                      Common_Locals                                           
                      Select Case CbMsg     'This is TO determine the message TYPE 
                         '       
                         Case %WM_INITDIALOG'<- Initialiaton when the program loads 
                           Control Set Focus CB.Hndl, %Id_Algebra_tb
                         '
                         Case %WM_SYSCOMMAND 'Traps Any Alt key but only F4 closes              
                         '
                         Case %WM_COMMAND  'This processes command messages
                           Select Case CB.Ctl
                             Case %Id_Show_Result_Btn       
                               Local Grade_Avg, grades, grade As Single
                               Reset grades, Grade_Avg
                               For ctr = %Id_Algebra_tb To %Id_Chemistry_TB
                                Control Get Text CB.Hndl, ctr To l$
                                  Grade = Val(l$)
                                   If Grade > 100 Then 
                                     ? "Grade over 100 not allowed " & l$, , FuncName$
                                       Control Set Focus CB.Hndl, ctr
                                       Exit Function
                                    ElseIf grade < 1  Then
                                     ? "Grade under 1 not allowed in " & l$, , FuncName$
                                       Control Set Focus CB.Hndl, ctr
                                       Exit Function
                                   End If
                                   Incr grades
                                   Grade_Avg = Grade_Avg + grade
                                Next ctr   
                                 'got here so must be valid
                                 Control Set Text CB.Hndl, %Id_Grades_Avg_TB, Using$("###.## ", Grade_Avg / Grades)
                             Case %Id_Exit_Btn
                               Select Case CbCtlMsg        
                                  Case 0
                                    Dialog End CbHndl 'Applikation beenden
                               End Select
                           End Select
                      End Select
                    End Function
                    '
                    Function PBMain
                      Common_Locals
                     
                       Stile = Stile Or %WS_CAPTION
                       Stile = Stile Or %WS_SYSMENU
                       Stile = Stile Or %WS_THICKFRAME 
                       Stile = Stile Or %WM_HELP 
                       Stile = Stile Or %WS_Border  'doesn't do anything
                      Dlg_Ht = 200
                      Dlg_Wd = 200
                      'Dialog Font "Consolas", 72 ' Big Unicodes
                      Dialog New Pixels, hdlg, "Demo", , , Dlg_Wd, Dlg_Ht, Stile To hdlg 'centered
                      Reset stile  'not needed here       
                      Row = 10
                      col = 10
                      Wd = 50
                      Ht = 20
                      s$ = " Algebra ":  Control Add Label, hdlg, -1, s$, Col, Row, Wd, Ht
                       Id = %Id_Algebra_tb
                        Control Add TextBox, hdlg, Id, "90", Col + Wd + 10, Row, Wd, Ht, Stile
                     
                      Row = Row + ht
                      s$ = " History ":  Control Add Label, hdlg, -1, s$, Col, Row, Wd, Ht
                       Id = %Id_History_tb
                        Control Add TextBox, hdlg, Id, "80", Col + Wd + 10, Row, Wd, Ht, Stile
                     
                      Row = Row + ht
                      s$ = " Chemistry ":  Control Add Label, hdlg, -1, s$, Col, Row, Wd, Ht
                       Id = %Id_Chemistry_tb
                        Control Add TextBox, hdlg, Id, "60", Col + Wd + 10, Row, Wd, Ht, Stile
                      Row = Row + ht
                      Row = Row + ht
                      Row = Row + ht
                      s$ = " Average ":  Control Add Label, hdlg, -1, s$, Col, Row, Wd, Ht
                       Id = %Id_Grades_Avg_TB
                        Control Add TextBox, hdlg, Id, s$, Col + Wd + 10, Row, Wd, Ht, Stile
                     
                     
                     
                     
                       Ht = 25   
                       Wd = Dlg_Wd - 20
                       Col = 10 'center
                       Row = Dlg_Ht - (Ht * 2) - 4 'Just off bottom
                         Control Add Button, hdlg, %Id_Show_Result_Btn, "Estimated Average", col, row, Wd, Ht
                       Row = Dlg_Ht - Ht - 2 'Just off bottom
                         Control Add Button, hdlg, %Id_Exit_Btn, "Abandon Ship", col, row, Wd, Ht
                     
                         Dialog Show Modal hDlg   Call Dialog_Processor
                    End Function  'Applikation beenden
                    '
                    Last edited by Gösta H. Lovgren-2; 22 May 2009, 08:59 PM.
                    It's a pretty day. I hope you enjoy it.

                    Gösta

                    JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
                    LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

                    Comment


                      #11
                      Gosta,

                      Thank you for your latest efforts. You have provided a workable way for me to do almost what I wanted, which may be good enough.

                      Sometimes I get fixated on wanting to understand why what I am trying doesn't work, rather than on how to get at least a workable solution.

                      The only thing I wanted to do that your code doesn't do is detect an error as the characters are typed in rather than after the action button is pressed. My code detects them, but somehow can't manage to get the focus on the offending textbox. Of the two, yours produces reasonable results, mine doesn't, so yours is better.

                      Thank you again for your efforts.

                      Steve

                      Steve

                      Comment


                        #12
                        Originally posted by Steve Frye View Post
                        The only thing I wanted to do that your code doesn't do is detect an error as the characters are typed in rather than after the action button is pressed. My code detects them, but somehow can't manage to get the focus on the offending textbox.
                        Steve
                        To do what you want (check each character as it is typed in), you'll pretty much have to get into subclassing. Not really difficult but much more sophisticated than the above code. There is an excellent example of subclassing in the PBx folders. Lots (and lots) of examples on the forums but none, imo, easier to understand than the PBx example.

                        =====================================
                        I always admired atheists.
                        I think it takes a lot of faith.
                        Diane Frolov and Andrew Schneider,
                        Northern Exposure, Seoul Mates, 1991
                        =====================================
                        It's a pretty day. I hope you enjoy it.

                        Gösta

                        JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
                        LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

                        Comment


                          #13
                          Hi Steve,

                          Just for laughs, here is a slightly modified version of the code from your first post. It's so late here it's early again, or I'd give some explanation and format the code a bit better, but it will have to wait until later.

                          Code:
                          #PBFORMS CREATED V1.51
                          #COMPILE EXE
                          #DIM ALL
                          '------------------------------------------------------------------------------
                          ' ** Includes **
                          '------------------------------------------------------------------------------
                          #PBFORMS BEGIN INCLUDES
                          #IF NOT %DEF(%WINAPI)
                          #INCLUDE "WIN32API.INC"
                          #ENDIF
                          #INCLUDE "PBForms.INC"
                          #PBFORMS END INCLUDES
                          '------------------------------------------------------------------------------
                          '------------------------------------------------------------------------------
                          ' ** Constants **
                          '------------------------------------------------------------------------------
                          #PBFORMS BEGIN CONSTANTS
                          %IDD_DIALOG1 = 101
                          %IDC_LBL_HomeworkScore = 1001
                          %IDC_LBL_ExamScores = 1002
                          %IDC_TB_HomeworkScore = 1005
                          %IDC_TB_Exam1Score = 1006
                          %IDC_TB_FinalExamScore = 1012
                          %IDC_BN_Estimate = 1014
                          %IDC_BN_Exit = 1015
                          #PBFORMS END CONSTANTS
                          
                          %UM_DOMYFOCUSTHING = %WM_USER + 1234
                          
                          '------------------------------------------------------------------------------
                          '------------------------------------------------------------------------------
                          ' ** Declarations **
                          '------------------------------------------------------------------------------
                          DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
                          DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                          #PBFORMS DECLARATIONS
                          '------------------------------------------------------------------------------
                          '------------------------------------------------------------------------------
                          ' ** Main Application Entry Point **
                          '------------------------------------------------------------------------------
                          FUNCTION PBMAIN()
                          GLOBAL SizeError, ThisScore AS LONG
                          ShowDIALOG1 %HWND_DESKTOP
                          END FUNCTION
                          '------------------------------------------------------------------------------
                          '------------------------------------------------------------------------------
                          ' ** CallBacks **
                          '------------------------------------------------------------------------------
                          CALLBACK FUNCTION ShowDIALOG1Proc()
                            LOCAL EditString, GoodDataString AS STRING
                            LOCAL Category, Assignment AS LONG
                            SELECT CASE AS LONG CB.MSG
                               CASE %WM_INITDIALOG
                               ' Initialization handler
                               CASE %WM_NCACTIVATE
                                  STATIC hWndSaveFocus AS DWORD
                                  IF ISFALSE CB.WPARAM THEN
                                  ' Save control focus
                                  hWndSaveFocus = GetFocus()
                                 ELSEIF hWndSaveFocus THEN
                                 ' Restore control focus
                                    SetFocus(hWndSaveFocus)
                                    hWndSaveFocus = 0
                                 END IF
                              CASE %WM_COMMAND
                              ' Process control notifications
                                 SELECT CASE AS LONG CB.CTL
                                    CASE %IDC_TB_HomeworkScore
                                        ThisScore=%IDC_TB_HomeworkScore
                                        IF CB.CTLMSG = %EN_KILLFOCUS THEN
                                           IF SizeError THEN
                                              'CONTROL SET FOCUS CB.HNDL, ThisScore
                                              CONTROL POST CB.HNDL, CB.CTL, %UM_DOMYFOCUSTHING, CB.CTL, 0
                                           END IF
                                       END IF
                                       IF CB.CTLMSG = %EN_CHANGE THEN ' after typed data is displayed back to user
                                          SizeError=0
                                          CONTROL GET TEXT CB.HNDL, ThisScore TO EditString
                                            IF VAL(EditString)>100 THEN
                                               SizeError=-1
                                               MSGBOX "Must be 100 or less", %MB_TASKMODAL
                                               'CONTROL SET FOCUS CB.HNDL, ThisScore
                                               CONTROL POST CB.HNDL, CB.CTL, %UM_DOMYFOCUSTHING, CB.CTL, 0
                                            END IF
                                       END IF
                                   CASE %IDC_TB_Exam1Score
                                       ThisScore=%IDC_TB_Exam1Score
                                       IF CB.CTLMSG = %EN_KILLFOCUS THEN
                                          IF SizeError THEN
                                             'CONTROL SET FOCUS CB.HNDL, ThisScore
                                             CONTROL POST CB.HNDL, CB.CTL, %UM_DOMYFOCUSTHING, CB.CTL, 0
                                          END IF
                                      END IF
                                  IF CB.CTLMSG = %EN_CHANGE THEN ' after typed data is displayed back to user
                                      SizeError=0
                                      CONTROL GET TEXT CB.HNDL, ThisScore TO EditString
                                      IF VAL(EditString)>100 THEN
                                         SizeError=-1
                                         MSGBOX "Must be 100 or less", %MB_TASKMODAL
                                         'CONTROL SET FOCUS CB.HNDL, ThisScore
                                         CONTROL POST CB.HNDL, CB.CTL, %UM_DOMYFOCUSTHING, CB.CTL, 0
                                      END IF
                                 END IF
                          
                                CASE %UM_DOMYFOCUSTHING
                                   CONTROL SET FOCUS CB.HNDL, CB.WPARAM
                          
                             CASE %IDC_BN_Estimate
                                 IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                    MSGBOX "%IDC_BN_Estimate=" + _
                                    FORMAT$(%IDC_BN_Estimate), %MB_TASKMODAL
                                 END IF
                             CASE %IDC_BN_Exit
                                IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                    DIALOG END CBHNDL, %IDD_Dialog1
                                END IF
                            END SELECT
                          END SELECT
                          END FUNCTION
                          '------------------------------------------------------------------------------
                          '------------------------------------------------------------------------------
                          ' ** Dialogs **
                          '------------------------------------------------------------------------------
                          FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                          LOCAL lRslt AS LONG
                          #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
                          LOCAL hDlg AS DWORD
                          LOCAL hFont1 AS DWORD
                          LOCAL hFont2 AS DWORD
                          DIALOG NEW hParent, "Grade Estimator", 105, 91, 320, 385, TO hDlg
                          CONTROL ADD LABEL, hDlg, %IDC_LBL_HomeworkScore, "Homework Score", 10, _
                          20, 100, 20
                          CONTROL ADD LABEL, hDlg, %IDC_LBL_ExamScores, "Exam Scores", 30, 60, _
                          80, 20
                          20
                          CONTROL ADD TEXTBOX, hDlg, %IDC_TB_HomeworkScore, "", 115, 30, 45, 20, _
                          %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %ES_RIGHT OR _
                          %ES_AUTOHSCROLL, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR _
                          %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
                          CONTROL ADD TEXTBOX, hDlg, %IDC_TB_Exam1Score, "", 115, 70, 45, 20, _
                          %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %ES_RIGHT OR _
                          %ES_AUTOHSCROLL, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR _
                          %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
                          CONTROL ADD BUTTON, hDlg, %IDC_BN_Estimate, "Estimate", 10, 350, 55, 20
                          CONTROL ADD BUTTON, hDlg, %IDC_BN_Exit, "Exit", 255, 350, 45, 20
                          hFont1 = PBFormsMakeFont("MS Sans Serif", 16, 400, %FALSE, %FALSE, _
                          %FALSE, %ANSI_CHARSET)
                          hFont2 = PBFormsMakeFont("MS Sans Serif", 12, 400, %FALSE, %FALSE, _
                          %FALSE, %ANSI_CHARSET)
                          DIALOG SEND hDlg, %WM_SETFONT, hFont1, 0
                          CONTROL SEND hDlg, %IDC_LBL_HomeworkScore, %WM_SETFONT, hFont2, 0
                          CONTROL SEND hDlg, %IDC_LBL_ExamScores, %WM_SETFONT, hFont2, 0
                          CONTROL SEND hDlg, %IDC_TB_HomeworkScore, %WM_SETFONT, hFont2, 0
                          CONTROL SEND hDlg, %IDC_TB_Exam1Score, %WM_SETFONT, hFont2, 0
                          CONTROL SEND hDlg, %IDC_BN_Estimate, %WM_SETFONT, hFont2, 0
                          CONTROL SEND hDlg, %IDC_BN_Exit, %WM_SETFONT, hFont2, 0
                          #PBFORMS END DIALOG
                          DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                          #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
                          DeleteObject hFont1
                          DeleteObject hFont2
                          #PBFORMS END CLEANUP
                          FUNCTION = lRslt
                          END FUNCTION
                          Hope it helps anyway.

                          Regards,

                          Pete. :sleeping:

                          Comment


                            #14
                            Here's something to get you started. This is the subclass procedure I use to edit for valid hex characters.

                            The control itself is created with style ES_UPPERCASE - but note when getting the raw data in this subclass procedured you can get lowercase letters and have to allow for that. (Windows does the upper-casing AFTER this procedure handles the character).

                            Code:
                            FUNCTION DelimiterHexEditProc (BYVAL hWnd AS LONG, BYVAL wMSG AS LONG, BYVAL wPAram AS LONG, BYVAL lParam AS LONG) AS LONG
                            
                              STATIC dwProc AS DWORD, BeenHere AS LONG
                              LOCAL szProp AS ASCIIZ * 64
                              LOCAL  idCtrl AS LONG
                              LOCAL  szText AS ASCIIZ * %MAX_PATH, lText AS LONG
                              LOCAL  ichar  AS LONG
                            
                            
                              IF ISFALSE beenHere THEN
                                  BeenHere = %TRUE
                                  szProp   = $PROP_OLD_WNDPROC
                                  dwProc   = getProp (hWnd, szProp)
                              END IF
                            
                              SELECT CASE AS LONG wMSg
                            
                                     CASE %WM_GETDLGCODE
                                         'FUNCTION =  %DLGC_WANTALLKEYS     ' With DLCG_WANTCHARS all regular keys work but no WM-CHAR message
                                         FUNCTION = %DLGC_WANTCHARS         ' doc says "WM_CHAR messages"
                                         'FUNCTION   = %DLGC_WANTMESSAGE
                                         EXIT FUNCTION
                            
                                     CASE  %WM_CHAR                      '"An application should return zero if it processes this message. "
                                        ' LOWRD wparam = "the character code of the key"
                                         IF wparam = %VK_TAB THEN
                                             ' standard TAB behavior
                                               SetFocus       GetnextDlgTabItem(GetParent(hWnd), hWnd, (GetKeyState(%VK_SHIFT) < 0))
                                               FUNCTION = 0
                                               EXIT FUNCTION
                            
                                         ELSE  ' not tab
                                            iChar  = LOWRD(WParam)
                                            SELECT CASE AS LONG iChar
                                                CASE &h30 TO &h39, &h41 TO &h46, _    ' OK characters 0-9 and A-F
                                                     &h61 TO &h66, _                  ' lower case a-f, will be uppercased when they get in
                                                     %VK_TAB, %VK_HOME, %VK_END, %VK_BACK, _      ' expected control characters
                                                     %VK_RIGHT, %VK_LEFT, %VK_INSERT, %VK_DELETE, _
                                                     %vK_ESCAPE
                                                    EXIT SELECT                      ' allow normal processing
                                                CASE ELSE
                                                    MessageBeep  %MB_ICONHAND
                                                    FUNCTION = 0
                                                    EXIT FUNCTION    ' bypass normal processing
                                            END SELECT
                                         END IF
                            
                                   END SELECT
                                   ' if message not handled (if handled proc was exited), call default handler
                                   FUNCTION = CallWindowProc (dwProc, hWnd, wMsg, wParam,lparam)
                            
                            END FUNCTION
                            MCM
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                              #15
                              Pete,

                              It may be just for laughs, but it seems to work EXACTLY like I originally wanted it to.

                              THANKS.

                              Steve
                              Last edited by Steve Frye; 23 May 2009, 10:55 AM.

                              Comment


                                #16
                                Pete,

                                Upon further review, I find that I can tab away from a textbox containing invalid data. This means I would have to replicate my editing in the Estimate button control to ensure I have valid data.

                                I don't understand why the code under "if %en_killfocus" doesn't prevent the focus from leaving a textbox containing invalid data until the data has been at least changed (and then the "if %en_change" should see if the data is valid and allow the focus shift or not).

                                I tried putting an "if %en_setfocus ..." statement under the Estimate button case to set the focus back to the previous control, but that didn't work for me either.

                                Any further thoughts? Thanks.

                                Steve

                                Comment


                                  #17
                                  don't understand why the code under "if %en_killfocus" doesn't prevent the focus from leaving
                                  A lot of notification messages are just that: notifications.

                                  While some notification messages DO give you a chance to 'do something' the vast majority simply TELL you something and are not ASKing you so much as the time of day.

                                  MCM
                                  Michael Mattias
                                  Tal Systems (retired)
                                  Port Washington WI USA
                                  [email protected]
                                  http://www.talsystems.com

                                  Comment


                                    #18
                                    Michael,

                                    Thanks. I was less than precise in my statement. I understand that the %en_killfocus is a notification. I thought that having been notified, I could redirect the focus back where I wanted it. Of course I anticipate that it will take place quickly enough that the user will not notice, which may be another issue if I can ever find a way to redirect the focus.

                                    Comment


                                      #19
                                      don't understand why the code under "if %en_killfocus" doesn't prevent the focus from leaving
                                      Your validating routine is not sophisticated enough. Try this mod to see what's going on..
                                      Code:
                                          CONTROL GET TEXT CB.HNDL, ThisScore TO EditString
                                            Dialog Set Text Cb.Hndl, "EN_CHANGE Val "+"'"+format$(Val(EditString))+"'"    ' < MOD
                                            IF VAL(EditString)>100 THEN
                                               SizeError=-1...
                                      eg "1a111" evaluates to 1 because Val returns the number up to first non numeric char.
                                      You could try something like..
                                      Code:
                                            IF VAL(EditString)>100 OR VERIFY(EditString, ".0123456789") THEN
                                      Rgds, Dave

                                      Comment


                                        #20
                                        Dave,

                                        The edit is not my problem. In my real code, I first check to see if the contents are null, then for multiple decimal points, then for ".0123456789", and finally for greater than 100. I only included one edit in the code extract I provided because my issue involves controlling the focus and I only needed one edit to illustrate it.

                                        Thanks to others who have responded, I can now put the focus on the textbox with invalid data, but I can't keep the user from tabbing away or clicking on another control, leaving the invalid data in place. I thought my "if %EN_KILLFOCUS" code would result in returning the focus to the invalid data if the user tabbed or clicked away. But it doesn't.

                                        To illustrate my real problem, run the code in my first post of this thread. Type 50 in the first textbox; type 111 in the second textbox. Note that after each of the first two 1's, the focus remains in the textbox so you can type another character. Upon typing the 3rd 1, the message box appears noting that the number must be less than or equal to 100. Upon responding to the message box, you will find the focus in the first textbox and you will not be able to tab out or click out until you change the contents of the first textbox (so that the edit will clear the SizeError flag, I assume). What I intended was that after the user responds to the message box, the focus should return to the second textbox, and remain their until it's contents are changed.

                                        Peter Jinks posted an improvement (instead of a Control Set Focus, he suggested a function which posted the Set Focus) which returns the focus to the second textbox (which contains 111) after the edit, but it allows the user to tab or click away from the invalid entry. I thought the code under KillFocus would return the user to the invalid data if the user tried to change the focus to another control. This is the part I don't understand. I'm now using trace so I can follow what the sequence of events is. I'm thinking that somewhere, somehow my Set Focus is being superceded by some other message processing.

                                        Thanks for your interest, time, and thoughts.

                                        Steve

                                        Steve
                                        Last edited by Steve Frye; 24 May 2009, 08:27 AM.

                                        Comment

                                        Working...
                                        X
                                        😀
                                        🥰
                                        🤢
                                        😎
                                        😡
                                        👍
                                        👎