Announcement

Collapse
No announcement yet.

Editing Textbox contents

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

    #21
    >but I can't keep the user from tabbing away or clicking on another control, leaving the >invalid data in place.

    By the time you get WM_COMMAND/EN_KILLFOCUS the user is already out of the field.

    You can do what you want to do here by subclassing, picking off the Tab key and if the user is not allowed to experience the default behavior of <TAB>, eating the WM_CHAR message by not passing it to the default handler.

    Alternately, you can avoid the need to subclass by POSTing a message to yourself to set the focus. Because you post (vs send) this message it's turn won't come until all the 'regular' activity associated with this keystroke has been processed.

    Eg

    Code:
    %PWM_SETMYFOCUS =  %WM_USER + 1
    ...
        CASE %WM_COMMAND/EN_KILLFOCUS 
           if Bad_Data THEN 
              DIALOG POST CB.HNDL, %PWM_SETMYFOCUS, ID_OF_CONTROL, %NULL
    
    
       CASE %PWM_SETMYFOCUS 
             CONTROL SET FOCUS   CB.HNDL,  CB.WPARAM
    MCM
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


      #22
      Michael,

      A previous respondent suggested posting my focus message using Control Post. I tried that, but found I didn't understand the logistics --- where it went and what should the parameters be. It didn't work as I understood his suggestion.

      HOWEVER, after extensive experimentation, I figured out how to properly use Dialog Post. Thank you. One of my pitfalls is that I don't know enough about what exists yet. I keep scanning the documentation and trying this and that, but I keep missing things that prove useful.

      Having made extensive use of Trace Print, I now have a much better feeling for the flow of control (or lack thereof). Now, if I only knew what all the message numbers meant. Ahhh, perhaps over time.

      Anyway, thanks for your help. You and trace were the tools I needed to crack my nut.

      Steve

      Comment


        #23
        Playing with the example posted, (as you would - data entry routines are such fun!) I made the following observations..

        Using EN_KILLFOCUS - When a bad entry is detected and focus is shifted back to the original TextBox, another EN_KILLFOCUS is generated if the next control (briefly focussed) was also a TextBox !

        Displaying a MsgBox messes around with the detection of which control currently has focus and causes additional Killfocus / Setfocus messages.
        Shifting to another window and back messes around with the Killfocus / Setfocus messages.

        Subclassing the TextBoxes allows the use of WM_KILLFOCUS instead - which has the advantage of occurring BEFORE focus is moved to another control (wparam tells you where it's headed)

        Taking control of the Tab key (and the Enter key) is advantageous in Data Entry situations. It can allow the user to move more easily between data entry points.
        Control can be accomplished by Subclassing, Keyboard hooks or by setting up Accelerator Tables (e.g. below).
        There are lots of examples on the forums (Search for GWL_WNDPROC, WH_KEYBOARD, ACCEL ATTACH)

        When trying to understand / trace the flow of the messages in a GUI program, MsgBoxes can be be quite disruptive - better to use WinBeep and text messages in the dialog's caption bar (Dialog Set Text..) instead.
        Here's a modified version which uses some of the above:
        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
        %LBL_HWRange = 1105
        %LBL_ExRange = 1106
        #PBFORMS END CONSTANTS
        %ID_TAB   = 1020
        %ID_RTN   = 1021
         
        %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  -  Ensure focus cues are shown
              DIALOG SEND CB.HNDL, %WM_UPDATEUISTATE, MAKLNG(%UIS_CLEAR, %UISF_HIDEFOCUS OR %UISF_HIDEACCEL), 0
         
            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 %ID_TAB, %ID_RTN                       ' process TAB or Return key IDs set in AccelTbl
                  ThisScore = GetDlgCtrlID(GetFocus)                            ' where are we?
                  SELECT CASE ThisScore
                    CASE %IDC_TB_HomeworkScore, %IDC_TB_Exam1Score              ' TextBoxes
                      IF SizeError THEN
                        DIALOG POST CB.HNDL, %UM_DOMYFOCUSTHING, ThisScore, 0   ' NO tabbing away from error
                      ELSE
                        SendMessage CB.HNDL, %WM_NEXTDLGCTL, GetNextDlgTabItem(CB.HNDL, GetFocus, %FALSE), 1
                        ' WM_NEXTDLGCTL sets focus & default push button styles ' Tab on to next control
                      END IF
                    CASE ELSE   ' e.g. %IDC_BN_Estimate, %IDC_BN_Exit           ' Buttons
                      IF CB.CTL = %ID_RTN THEN        ' Enter Key
                        PostMessage GetFocus, %BM_CLICK, 0, 0                   ' "press" w/ Rtn OR Space bar
                      ELSE                            ' Tab Key
                        SendMessage CB.HNDL, %WM_NEXTDLGCTL, GetNextDlgTabItem(CB.HNDL, GetFocus, %FALSE), 1
                        ' == SetFocus GetNextDlgTabItem(Cb.Hndl, GetFocus, %FALSE)
                      END IF
                  END SELECT
         
                CASE %IDC_TB_HomeworkScore
                  IF CB.CTLMSG = %EN_CHANGE THEN ' after typed data is displayed back to user
                    Validate CB.HNDL, CB.CTL     ' Validate text / set SizeError = 1 if bad
                  END IF
         
                CASE %IDC_TB_Exam1Score
                   IF CB.CTLMSG = %EN_CHANGE THEN ' after typed data is displayed back to user
                     Validate CB.HNDL, CB.CTL     ' Validate text / set SizeError = 1 if bad
                   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
         
            CASE %UM_DOMYFOCUSTHING
            ' Process user message to set focus where correction required
              CONTROL SET FOCUS CB.HNDL, CB.WPARAM
              CONTROL SHOW STATE CB.HNDL, CB.WPARAM + 100, %SW_SHOW     ' label ID = Control ID + 100
          END SELECT
        END FUNCTION
        '------------------------------------------------------------------------------
        ' ** Dialogs **
        '------------------------------------------------------------------------------
        FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
         LOCAL lRslt AS LONG
         LOCAL hAccel AS DWORD
         DIM AccelTbl(1) AS ACCELAPI            ' Create AccelTable (could subclass for control of Tab key)
            AccelTbl(0).FVIRT   = %FVIRTKEY     ' flag (indicates key member is a virtual-key code)
            AccelTbl(0).KEY     = %VK_RETURN    ' Enter key (could be ASCII Char code, see FVIRT)
            AccelTbl(0).CMD     = %ID_RTN       ' accelerator ID for %WM_COMMAND / CB.CTL
         
            AccelTbl(1).FVIRT   = %FVIRTKEY
            AccelTbl(1).KEY     = %VK_TAB
            AccelTbl(1).CMD     = %ID_TAB
         
        #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
            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
            CONTROL ADD LABEL,   hDlg, %LBL_HWRange, "< Range 0 - 100", 175, 32, 90, 20
            CONTROL SET COLOR    hDlg, %LBL_HWRange, %RED, -1
            CONTROL SHOW STATE   hDlg, %LBL_HWRange, %SW_HIDE
            CONTROL ADD LABEL,   hDlg, %LBL_ExRange, "< Range 0 - 100", 175, 72, 90, 20
            CONTROL SET COLOR    hDlg, %LBL_ExRange, %RED, -1
            CONTROL SHOW STATE   hDlg, %LBL_ExRange, %SW_HIDE
         
          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
          CONTROL SEND hDlg, %LBL_HWRange, %WM_SETFONT, hFont2, 0
          CONTROL SEND hDlg, %LBL_ExRange, %WM_SETFONT, hFont2, 0
        #PBFORMS END DIALOG
         
            ACCEL ATTACH hDlg, AccelTbl() TO hAccel           '** control Tab and Return keys
         
          LOCAL hWnd, OldProc AS LONG
         
            hWnd=GetDlgItem(hDlg, %IDC_TB_HomeworkScore)
            OldProc=SetWindowLong(hWnd, %GWL_WNDPROC, CODEPTR(TB_SubClassProc))
            hWnd=GetDlgItem(hDlg, %IDC_TB_Exam1Score)
            OldProc=SetWindowLong(hWnd, %GWL_WNDPROC, CODEPTR(TB_SubClassProc))
            SetProp hDlg, "OldProc", OldProc
         
          DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
         
        #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
          DeleteObject hFont1
          DeleteObject hFont2
        #PBFORMS END CLEANUP
         RemoveProp hDlg, "OldProc"
         FUNCTION = lRslt
        END FUNCTION
        '------------------/ShowDialog1
         
        FUNCTION Validate(BYVAL hWnd AS LONG, BYVAL ContID AS LONG) AS LONG
         LOCAL EditString AS STRING
         
           CONTROL GET TEXT hWnd, ContID TO EditString
           IF VAL(EditString) > 100 OR VERIFY(EditString, ".0123456789") THEN             ' validation test(s) fails so
              WinBeep 400,200
              SizeError = 1
              'MSGBOX "Must be 100 or less", %MB_TASKMODAL      ' using msgbox causes havoc w/focus handling
              DIALOG POST hWnd, %UM_DOMYFOCUSTHING, ContID, 0
              FUNCTION  = 0
           ELSE
              CONTROL SHOW STATE hWnd, ContID + 100, %SW_HIDE   ' use labels for user alerts
              SizeError = 0
              FUNCTION  = 1
           END IF
        END FUNCTION
        '------------------/Validate
         
        FUNCTION TB_SubClassProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
         LOCAL OldProc AS LONG
          SELECT CASE wMsg
            CASE %WM_KILLFOCUS        ' Sent before focus lost. wparam = where focus will go next
              IF GetDlgCtrlID(wparam) <> %IDC_BN_Exit AND GetDlgCtrlID(wparam) <> 0 THEN  ' Focus not shifting to Exit Button
                Validate (GetParent(hWnd), GetDlgCtrlID(hWnd))                            ' or to another window
              END IF
            END SELECT
         
         OldProc  = GetProp(GetParent(hWnd), "OldProc")
         FUNCTION = CallWindowProc(oldProc, hWnd, wMsg, wParam, lParam)
        END FUNCTION
        '------------------/TB_SubClassProc
        Rgds, Dave

        Comment


          #24
          Dave,

          Many thanks for your efforts on my behalf. I shall do my best to figure out how what you've done works.

          I have to say that while I understand the concepts of object oriented programming, every time I try to understand how to use it, I become bogged down and confused. So when someone says "subclassing" to me (as several have and as I saw in lots of posts to this forum), I have a tendency to look elsewhere because I know I'm not ready for it. That being said, I have discovered how my approach (I did finally get it to work by setting flags so I wouldn't try to set the focus during message box processing and then discovered I didn't really need the dialog post rigamarole) gets tangled up because the focus is set several times. Making sure the focus never leaves is MUCH preferrable to putting it back. I also like your approach to notifying the user; it avoids the extra "work" of responding to the message box itself and keeps the user's attention on the textboxes. I'm not a fan of the beep though. I personally keep my sound off almost all the time. In a room full of computers or even in a room with just two, the noises can be very distracting (sort of like cell phones "ringing").

          Again, thanks for your effort and time. I'm off to discover the magical world of subclassing. Or at least your example of it.

          Steve

          Comment


            #25
            Originally posted by Steve Frye View Post
            I'm not a fan of the beep though. I personally keep my sound off almost all the time. In a room full of computers or even in a room with just two, the noises can be very distracting (sort of like cell phones "ringing").

            Steve
            That's a good point but I think not in this case though. If the user is intent on entering a series of numbers (maybe from a written list) his focus will not likely be on the screen, certainly not the dialog caption. Without something to cause refocus when he makes an entry error, he could be quite aways down the list before he realizes the error of his meandering ways.

            Code:
             WinBeep 200, 10 'adjust according to taste
            is not very intrusive (for example).

            ==============================================
            "When you do the common things in life
            in an uncommon way,
            you will command the attention of the world."
            George Washington Carver (1864-1943)
            ==============================================
            Last edited by Gösta H. Lovgren-2; 26 May 2009, 10:38 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


              #26
              I think beeps can be annoying too - but I like using them (and dialog title messages) for trouble shooting during development. Perhaps (optional) clicks are OK in the final app?

              So when someone says "subclassing" to me (as several have and as I saw in lots of posts to this forum), I have a tendency to look elsewhere because I know I'm not ready for it.
              Sure you are!

              Just think about this:

              You are already familar with Application-defined window procedures - you use ShowDIALOG1Proc() in the example that you posted.
              By now you also know that not all messages are available to the Application-defined procedure, some are handled internally by the OS.

              (The 'Default Window Procedure' provided by the OS also provides default processing for any window messages that an application-defined proc could but does not process. This function ensures that every message is processed).

              When you subclass a control, you redirect it's messages to your own procedure before they get to the default window procedure. Thus you can react to messages that you would otherwise not have access to. (e.g. WM_KILLFOCUS, WM_CHAR etc).
              After picking out the messages that you want to deal with, you allow the rest to pass on through to the original default window procedure to handle. Easy!

              Here's how it's done...
              Code:
              ' In ShowDIALOG1Proc():
               
               LOCAL hCtl    AS DWORD
               LOCAL OldProc AS LONG
               
               SELECT CASE CBMSG
               
                CASE %WM_INITDIALOG 
                  hCtl = GetDlgItem(CBHNDL, %IDC_CTLID)       ' (change %IDC_CTLID to your control ID)
               
                   ' SetWindowLong() changes %GWL_WNDPROC of the specified window (ie the address of it's Window Procedure)
                  OldProc = SetWindowLong(hCtl, %GWL_WNDPROC, CODEPTR(SubClassProc))
               
                   ' Store the address of original default windows procedure (returned by SetWindowLong) - needed later
                  SetProp (hCtl, "OldProc", OldProc)          ' SetProp stores OldProc address in a property list for hCtl
                                                              ' (you could use a Global to store the address..)
               CASE %WM_LimitedSetOfMsgs
                 ' ..etc                                      ' 'Regular' messages - WM_COMMAND etc
               
               CASE %WM_DESTROY
                  SetWindowLong hCtl, %GWL_WNDPROC, OldProc   ' Remove subclassing and Prop when closing
                RemoveProp (hCtl, "OldProc")
               END SELECT
              END FUNCTION 
              -------------------/
               
              ' Add the subclass procedure:
               
              FUNCTION SubClassProc(BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
               LOCAL OldProc AS LONG
               
                SELECT CASE wMsg
                CASE %WM_VariousOtherMessages                  ' Things like WM_KILLFOCUS
                  ' ..etc                                      ' & WM_CHAR are available here
               
               END SELECT                                      ' retrieve the original address from the Property list &
                                                               ' pass all other messages on to original default WinProc
               OldProc = GetProp (hWnd, "OldProc")
               FUNCTION = CallWindowProc(OldProc, hWnd, wMsg, wParam, lParam)
              END FUNCTION
              '------------------/
              Rgds, Dave

              Comment


                #27
                Gosta,

                Your point about entering lots of numbers only to discover nothing is going in is a good one. A small example is entering a phone number in web applications. When I see three separate text boxes for area code, exchange, and number, I automatically assume that the focus will jump from one to the next as the requisite digits are entered. Unfortunately, some "programmers" don't code that way and I then find that I've entered the whole phone number into the first box or after 3 digits, it ignored what I typed.

                So I guess I see the value of a low volume sound to indicate an error.

                Thanks.

                Steve

                Comment


                  #28
                  Dave,

                  As time has gone on, and I've struggled with my puzzle, I feel I'm getting better prepared for "subclassing". I thank you for your efforts to educate me and drag me into the new (for me) world. I appreciate the effort you've put into writing the latest example and annotating it for me. One of my problems is that I don't know the context. I feel like I'm reading a foreign language book, and I have to look up every third or fourth word. Re-education is the pits. Oh well, time to get on with my sub-classing studies.

                  Thanks again,

                  Steve

                  Comment


                    #29
                    You may be overthinking subclassing, Steve. (Lord knows I did when I first started - and a long time afterward.) It might help to look at it this (over simple) way. When the user takes an action (typing in a Textbox for example) messages are sent to the CallBack. Others Windows background stuff may be sending msgs to/through the CallBack as well.

                    In this case the programmer is only interested in those msgs relating to whether or not the user has/is typing what the programmer wants/expects. But there is so much stuff going on in the Callback and the way Windows works it's not so easy to isolate just those actions.

                    So what "subclassing" does is tell the msgs from the textbox to "go here first" (the subclass) where the programmer can more easily pick out (act on) those msgs he is interested in (letters, numbers, tabs,, ....). Then go on the the Callback (or not).

                    Again, the easiest subclassing example I have found to use and understand is the SubClass sample in PBWin9. (It's really not hard at all once you look at it simply. It's easy to get lost in the wizardry and advance programming techniques often discussed/displayed here. - DDT ONLY Forum anyone?)

                    ======================================
                    "But at my back I always hear
                    Time's winged chariot hurrying near."
                    Andrew Marvell (1621-1678)
                    ======================================
                    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


                      #30
                      I feel like I'm reading a foreign language book, and I have to look up every third or fourth word. Re-education is the pits
                      I could not help but be struck by the irony of this statement considering comments in your 'thread starter' post:
                      I'm a newbie to PowerBasic and not very proficient at VB...
                      Even were you proficient at VB, it wouldn't have helped a whole lot. VB did you the 'favor' of hiding all the messy details of message handling in exchange for 'simple programs, quickly.'

                      This is the exact reason I proselytize almost nonstop about the need for all programmers - regardless of source language - to have a solid understanding of fundamentals...in this case, the fundamentals of Windows' GUI programs.

                      Starting with a tool like - among many others - VB, you can have working applications quickly without investing the time to learn those fundamentals. It's only later you learn this expedience was not free, and you need to make that same investment in fundamentals if you want to go beyond bland applications with simple features.

                      As the Pennzoil man tells us, "You can pay me now, or you can pay me later." Later always comes.

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

                      Comment


                        #31
                        Gosta and Michael,

                        Thanks for your words of encouragement. Michael, I've almost always been of your view --- it really bothers me when all these applications hide what they do in order to simplify my life. When something goes wrong, I have no idea what to do. Of course, even if everything is out in the open, an investment in learning what is going on and how to deal with it must be made.

                        Way back in my Cobol, PL/1, Fortran, DOS (yes, I'm old days, I always wanted to know one level (at least) below where I was working. That is, if I was writing code in Cobol, I wanted to know what assembler was being generated and to some extent, what the parts of the computer were (processor, channels, memory, DASD, Tape), what they were doing, and how they interacted. But it's been a long time and while I still have conceptual knowledge, the details have to be relearned (I can still write a pretty useful command prompt program, which I do from time to time --- favorite languate for that is REXX, but it is an interpreted language and has to be installed on a system before a script will run. So its not good for a quick utility that I want to give someone else.

                        Again, thanks for all the help you guys have been. I've learned alot but I've only come "10 miles with 10,000 miles to go" as James Taylor sings now and again.

                        Steve

                        Comment

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