Announcement

Collapse
No announcement yet.

Beginner on EnterMov.BAS

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

    Beginner on EnterMov.BAS

    I have taken the BAS program EnterMov.BAS from the samples file and modified the code to solve a triangle given any 3 of 3 sides or 3 angles. At this point I can enter the data into three text boxes. But how do I give variables say SideA$, sideB$, SideC$, angleA$ etc. those values so I can then perform calculations on them using say VAL(Side$) etc ???. How do I then put the results in their text boxes ???.

    I am familiar with VB5 (and have written a more extensive version of what I am trying to do here with PB) but PB processes seem very different.

    I would include the code here but I don't see any option to do so.
    Warren Sugden

    #2
    Just put the code between tags [ c o d e ] and [ / c o d e ] (tags without the spaces)
    Regards,
    Peter

    "Simplicity is a prerequisite for reliability"

    Comment


      #3
      Beginner in EnterMove.bas

      Peter

      I'm sorry, but I have absolutely no idea what your talking about.

      Warren
      Warren Sugden

      Comment


        #4
        Include this in your post:

        [ c o d e ]
        ...
        ...
        Here goes your source code
        ...
        ...
        [ / c o d e ]
        Regards,
        Peter

        "Simplicity is a prerequisite for reliability"

        Comment


          #5
          beginner on entermov.bas

          Code:
          '====================================================================
          '
          '   EnterMov.bas example for PowerBASIC for Windows
          '   Copyright (c) 2005 PowerBASIC, Inc.
          '   All Rights Reserved.
          '
          '   EnterMov.bas - a PB/WIN sample data input form.
          '   Shows a way to move between TextBox input fields with the Enter key.
          '   Since the system triggers a %WM_COMMAND/%IDOK on Enter key press,
          '   we can use this combined with a few API calls to move focus to next
          '   control in tab order. See also Win32.hlp or MSDN for more API info.
          '
          '====================================================================
          
          '##########  ####################################################
          '   This program has been constructed from sample programs
          '   as a skeleton program.   Called  WarrensDDTSkeleton.BAS
          '        EnterMov.bas
          '        Menu.bas
          
          '############################################################
          
          
          #COMPILE EXE
          #DIM ALL
          
          '####  Variables from 'EnterMov'   #####################################
          
          %USEMACROS = 1
          #INCLUDE "WIN32API.INC"
          
          %IDC_TEXT1    = 141
          %IDC_TEXT2    = 142
          %IDC_TEXT3    = 143
          %IDC_TEXT4    = 144
          %IDC_TEXT5    = 145
          %IDC_TEXT6    = 146
          
          '######  END   Variables from 'EnterMov'  ##################################
          
          '####  Variables from 'Menu'   #####################################
          %IDOK       = 1
          %IDCANCEL   = 2
          %IDQUIT   = 3
          %IDTEXT     = 100
          %BN_CLICKED = 0
          %BS_DEFAULT = 1
          %MF_ENABLED = 0
          %WM_COMMAND = &H111
          
          %ID_OPEN    = 401
          %ID_EXIT    = 402
          %ID_OPTION1 = 403
          %ID_OPTION2 = 404
          %ID_HELP    = 405
          %ID_ABOUT   = 406
          
          '######  END   Variables from 'Menu'  ##################################
          
          '######  EX  'Menu'  ##################################
          
          GLOBAL UserName AS STRING
          
          CALLBACK FUNCTION OkButton () AS LONG
          
              IF CBMSG = %WM_COMMAND AND CBCTLMSG = %BN_CLICKED THEN
                  CONTROL GET TEXT CBHNDL, %IDTEXT TO UserName
                  DIALOG END CBHNDL, 1
                  FUNCTION = 1
              END IF
          
          END FUNCTION
          
          CALLBACK FUNCTION CancelButton () AS LONG
          
              IF CBMSG = %WM_COMMAND AND CBCTLMSG = %BN_CLICKED THEN
                  DIALOG END CBHNDL, 0
                  FUNCTION = 1
              END IF
          
          END FUNCTION
          
          CALLBACK FUNCTION QuitButton () AS LONG
          
              IF CBMSG = %WM_COMMAND AND CBCTLMSG = %BN_CLICKED THEN
                  DIALOG END CBHNDL, 0
                  FUNCTION = 1
              END IF
          
          END FUNCTION
          
          '#########  This function EX Menu is duplicated in 'EnterMov.Bas' and
          '#########  so is REM'd out.
          
          'CALLBACK FUNCTION DlgProc () AS LONG
          
          '    IF CBMSG = %WM_COMMAND THEN
          '        IF CBCTL => %ID_OPEN AND CBCTL <= %ID_ABOUT THEN
          '            MSGBOX "WM_COMMAND received from a menu item!"
          '            FUNCTION = 1
          '        END IF
          '    END IF
          
          'END FUNCTION
          
          '######  END  'Menu'  ##################################
          
          
          '====================================================================
          FUNCTION PBMAIN() AS LONG
          '--------------------------------------------------------------------
            ' Main program entrance
            '------------------------------------------------------------------
            LOCAL hDlg AS DWORD
          
          '#### For MENU  ##################################################
          '    LOCAL hDlg    AS DWORD
              LOCAL Result  AS LONG
              LOCAL hMenu   AS DWORD
              LOCAL hPopup1 AS DWORD
              LOCAL hPopup2 AS DWORD
          '#### END MENU  ##################################################
          
          
            DIALOG NEW 0, "Solve the 3 Sides and 3 Angles of a Triangle - Press Enter or Shift + Enter",,, 291, 204, _
                          %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg
          
            '------------------------------------------------------------------
          '########  EX 'EnterMov  ####################
          
            '###  5 = Left   7 = Down from top    30 = Length of label   10 = depth of label
            CONTROL ADD LABEL, hDlg, -1, "Length of Side A",       5,  7,  80, 20
            CONTROL ADD TEXTBOX, hDlg, %IDC_TEXT1, "", 110,  5, 30, 13
          
            CONTROL ADD LABEL, hDlg, -1, "Length of Side B",    5, 27,  80, 20
            CONTROL ADD TEXTBOX, hDlg, %IDC_TEXT2, "", 110, 25, 30, 13
          
            CONTROL ADD LABEL, hDlg, -1, "Length of Side C",      5, 47, 80, 20
            CONTROL ADD TEXTBOX, hDlg, %IDC_TEXT3, "", 110, 45, 30, 13
          
            CONTROL ADD LABEL, hDlg, -1, "Angle opposite Side A in format of D.mmss",     5, 67, 80, 20
            CONTROL ADD TEXTBOX, hDlg, %IDC_TEXT4, "", 110, 70, 50, 13
          
            CONTROL ADD LABEL, hDlg, -1, "Angle opposite Side B in format of D.mmss",     5, 97, 80, 20
            CONTROL ADD TEXTBOX, hDlg, %IDC_TEXT5, "", 110, 100, 50, 13
          
            CONTROL ADD LABEL, hDlg, -1, "Angle opposite Side C in format of D.mmss",     5, 127, 80, 20
            CONTROL ADD TEXTBOX, hDlg, %IDC_TEXT6, "", 110, 130, 50, 13
          
            CONTROL ADD BUTTON, hDlg, %IDQUIT,     "QUIT",       230, 160, 50, 14
            CONTROL ADD BUTTON, hDlg, %IDOK,     "Ok",       170, 160, 50, 14
            CONTROL ADD BUTTON, hDlg, %IDCANCEL, "&Cancel", 110, 160, 50, 14
          
          '#######  EX  EnterMov  #############################################
          
          '#######  EX  MENU  #############################################
          
              ' Create a top-level menu:
              MENU NEW BAR TO hMenu
          
              ' Add a top-level menu item with a popup menu:
              MENU NEW POPUP TO hPopup1
              MENU ADD POPUP, hMenu, "&File", hPopup1, %MF_ENABLED
              MENU ADD STRING, hPopup1, "&Open", %ID_OPEN, %MF_ENABLED
              MENU ADD STRING, hPopup1, "&Exit", %ID_EXIT, %MF_ENABLED
              MENU ADD STRING, hPopup1, "-",      0, 0
          
              ' Now we can add another item to the menu that will bring up a sub-menu.
              ' First we obtain a new popup menu handle to distinuish it from the first popup menu:
              MENU NEW POPUP TO hPopup2
          
              ' Now add a new menu item to the first menu.
              ' This item will bring up the sub-menu when selected:
              MENU ADD POPUP, hPopup1, "&More Options", hPopup2, %MF_ENABLED
          
              ' Now we will define the sub menu:
              MENU ADD STRING, hPopup2, "Option &1", %ID_OPTION1, %MF_ENABLED
              MENU ADD STRING, hPopup2, "Option &2", %ID_OPTION2, %MF_ENABLED
          
              ' Finally, we'll add a second top-level menu and popup.
              ' For this popup, we can reuse the first popup variable:
              MENU NEW POPUP TO hPopup1
              MENU ADD POPUP,  hMenu, "&Help", hPopup1, %MF_ENABLED
              MENU ADD STRING, hPopup1, "&Help", %ID_HELP, %MF_ENABLED
              MENU ADD STRING, hPopup1, "-",      0, 0
              MENU ADD STRING, hPopup1, "&About", %ID_ABOUT, %MF_ENABLED
          
             MENU NEW POPUP TO hPopup1
             MENU ADD POPUP,  hMenu, "QUIT", hPopup1, %MF_ENABLED
          
              MENU ATTACH hMenu, hDlg
          
          '######   END Menu  ###########################################
          
            '------------------------------------------------------------------
            DIALOG SHOW MODAL hDlg, CALL DlgProc
          
          END FUNCTION
          
          
          '====================================================================
          CALLBACK FUNCTION DlgProc() AS LONG
          '--------------------------------------------------------------------
            ' Callback procedure for the main dialog
            '------------------------------------------------------------------
            LOCAL c AS LONG, sBuf, sText AS STRING
          
            SELECT CASE AS LONG CBMSG
            '------------------------------------------------------------------
            CASE %WM_INITDIALOG
                ' %WM_INITDIALOG is sent right before the dialog is shown.
                ' A good place to initiate variables and controls, etc.
          
            '------------------------------------------------------------------
            CASE %WM_COMMAND                ' <- a control is calling
                SELECT CASE AS LONG CBCTL   ' <- look at control's id
                '--------------------------------------------------------------
                CASE %IDOK                  ' <- Ok or Enter key was pressed
                    IF CBCTLMSG = %BN_CLICKED THEN
                        SELECT CASE GetDlgCtrlId(GetFocus) 'Which control has focus?
                        CASE %IDC_TEXT1 TO %IDC_TEXT4      'If a textbox, move focus
                            IF (GetKeyState(%VK_SHIFT) AND &H8000) = 0 THEN
                                SetFocus GetNextDlgTabItem(CBHNDL, GetFocus, 0)
                            ELSE 'Shift + Enter = move to previous control
                                SetFocus GetNextDlgTabItem(CBHNDL, GetFocus, 1)
                            END IF
          
                        CASE %IDOK  ' If Ok button has focus
                            ' In a real code, this is a good place to store the result,
                            ' but in this demo we just show it in a MSGBOX.
                            FOR c = %IDC_TEXT1 TO %IDC_TEXT4
                                CONTROL GET TEXT CBHNDL, c TO sBuf
                                sText = sText + sBuf + $CRLF
                            NEXT
                            MSGBOX sText, %MB_TASKMODAL, "TextBox contents"
                            ' DIALOG END CBHNDL, 1  '<- if we want to exit here
          
                        CASE %IDCANCEL  ' If Cancel button has focus
                            DIALOG END CBHNDL, 0   '<- End prog
          
                        END SELECT
                  END IF
          
                '--------------------------------------------------------------
                CASE %IDCANCEL  ' <- Cancel or Esc key was pressed
                    IF CBCTLMSG = %BN_CLICKED THEN
                        DIALOG END CBHNDL, 0   '<- End prog
                    END IF
                '--------------------------------------------------------------
                END SELECT
          
            END SELECT
          
          END FUNCTION
          Warren Sugden

          Comment


            #6
            Do you mean:
            Code:
                          Case %IDOK  ' If Ok button has focus
                              Control Get Text CbHndl, %IDC_TEXT1 To SideA$
                              Control Get Text CbHndl, %IDC_TEXT2 To SideB$
                              Control Get Text CbHndl, %IDC_TEXT3 To SideC$
                              Control Get Text CbHndl, %IDC_TEXT4 To AngleA$
                              ' DIALOG END CBHNDL, 1  '<- if we want to exit here
            Regards,
            Peter

            "Simplicity is a prerequisite for reliability"

            Comment


              #7
              beginner on EnterMove

              Peter

              I take it you are suggesting those 4 lines of code should replace the 'For/next' routine and the Msg. I think I can see how those 4 lines would store the values of %IDC_text1 etc. into the variables Sidea$ etc.

              If I place the maths formulae in a separate procedure say CalculateTriangle$() what is the syntax of the code to call that routine from say the line immediately following the 4 lines you suggest. Is that the correct way to do it ????.

              I would enter 3 of the 6 possible variables - sides and/or angle - Call CalculateTriangle$(), do the calculations to produce values for the other 3 variables and then instal those 3 new values in their appropriate text boxes.

              Does that sound right ???/

              Warren
              Warren Sugden

              Comment


                #8
                Yes,

                You could pass the strings to the sub:
                Code:
                Sub CalculateTriangle(SideA$, SideB$, SideC$, AngleA$)
                On return you can pass the results in SideA$...SideC$
                The Sub would look something like this:
                Code:
                Sub CalculateTriangle(SA As String, SB As String, SC As String, Angle As String)
                  ... do something comlicated and assign result to SA, SB, SC 
                End Sub
                Regards,
                Peter

                "Simplicity is a prerequisite for reliability"

                Comment


                  #9
                  another way to look at it

                  Warren,

                  Below are four Sdk style programs of gradually increasing complexity that may be of help to you at some point. Hopefully dimensions and areas of squares will serve you as well as triangles for learning purposes.

                  The first program is a standard Sdk style Api program that puts a few text boxes and a button on the Form, and prints the area in a text box when you fill in a length and width and click the button...

                  Code:
                  #Compile Exe
                  #Include "Win32api.inc"
                  %IDC_LABEL1             =   1500
                  %IDC_LABEL2             =   1505
                  %IDC_TEXT1              =   1510
                  %IDC_TEXT2              =   1515
                  %IDC_TEXT3              =   1520
                  %IDC_BUTTON             =   1525
                  Global hText1           As Dword    'Window handle of Length text box
                  Global hText2           As Dword    'Window handle of Width text box
                  Global hText3           As Dword    'Window handle of results/Area text box
                  Global hBtn             As Dword    'Window handle of button on form
                  Global g_hInst          As Dword    'Global Instance Handle
                  
                  
                  Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                    Select Case As Long wMsg
                      Case %WM_CREATE
                        Local hLabel As Dword
                        hLabel=CreateWindowEx(0,"static","Length",%WS_CHILD Or %WS_VISIBLE,10,10,80,25,hWnd,%IDC_LABEL1,g_hInst,Byval 0)
                        hText1=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,10,80,25,hWnd,%IDC_TEXT1,g_hInst,Byval 0)
                        hLabel=CreateWindowEx(0,"static","Width",%WS_CHILD Or %WS_VISIBLE,10,60,80,25,hWnd,%IDC_LABEL2,g_hInst,Byval 0)
                        hText2=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,60,80,25,hWnd,%IDC_TEXT2,g_hInst,Byval 0)
                        hBtn=CreateWindowEx(0,"Button","Calculate",%WS_CHILD Or %WS_VISIBLE,80,120,150,25,hWnd,%IDC_BUTTON,g_hInst,Byval 0)
                        hText3=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,80,200,150,25,hWnd,%IDC_TEXT3,g_hInst,Byval 0)
                        SetFocus(hText1)
                        fnWndProc=0
                        Exit Function
                      Case %WM_COMMAND
                        Local dblLength, dblWidth, dblArea As Double
                        Local szBuffer As Asciiz*64
                        If Lowrd(wParam)=%IDC_BUTTON And Hiwrd(wParam)=%BN_CLICKED Then
                           GetWindowText(hText1,szBuffer,64)
                           dblLength=Val(szBuffer)
                           GetWindowText(hText2,szBuffer,64)
                           dblWidth=Val(szBuffer)
                           szBuffer="Area = " & Format$(dblLength*dblWidth,"######0.00")
                           SetWindowText(hText3,szBuffer)
                           fnWndProc=0
                           Exit Function
                        End If
                      Case %WM_DESTROY
                        Call PostQuitMessage(0)
                        fnWndProc=0
                        Exit Function
                    End Select
                  
                    fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
                  End Function
                  
                  
                  Function WinMain(ByVal hIns As Long,ByVal hPrev As Long,ByVal lpCL As Asciiz Ptr,ByVal iShow As Long) As Long
                    Local winclass As WndClassEx
                    Local szAppName As Asciiz*16
                    Local Msg As tagMsg
                    Local hWnd As Dword
                  
                    szAppName="Basic_Stuff"
                    g_hInst=hIns
                    winclass.cbSize=SizeOf(winclass)
                    winclass.style=%CS_HREDRAW Or %CS_VREDRAW
                    winclass.lpfnWndProc=CodePtr(fnWndProc)
                    winclass.cbClsExtra=0
                    winclass.cbWndExtra=0
                    winclass.hInstance=hIns
                    winclass.hIcon=LoadIcon(%NULL, ByVal %IDI_APPLICATION)
                    winclass.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW)
                    winclass.hbrBackground=%COLOR_BTNFACE+1
                    winclass.lpszMenuName=%NULL
                    winclass.lpszClassName=VarPtr(szAppName)
                    Call RegisterClassEx(winclass)
                    hWnd=CreateWindow(szAppName,"Pretty Basic Sdk Stuff",%WS_OVERLAPPEDWINDOW,200,100,325,300,0,0,hIns,ByVal 0)
                    Call ShowWindow(hWnd,iShow)
                    While GetMessage(Msg,%NULL,0,0)
                      TranslateMessage Msg
                      DispatchMessage Msg
                    Wend
                  
                    Function=msg.wParam
                  End Function
                  As you'll note if you examine the code, the critical ingredient for obtaining data out of a text box in this style of program is to create a text buffer of a suitable number of bytes to extract a string of text into using the GetWindowText() Win Api function, i.e.,

                  Local szBuffer As Asciiz*16
                  GetWindowText(hWnd,szBuffer,16)

                  If a number such as 25.5 was in the text box, it can be loaded into a Single or Double like you are already familiar...

                  Local dblLength As Double
                  dblLength=Val(szBuffer)

                  In the next version of the above program, I have it modularized so that each Window's message the program handles is in a seperate message handler, as you are familiar with from VB...

                  Code:
                  #Compile Exe
                  #Include "Win32api.inc"
                  %IDC_LABEL1   =   1500
                  %IDC_LABEL2   =   1505
                  %IDC_TEXT1    =   1510
                  %IDC_TEXT2    =   1515
                  %IDC_TEXT3    =   1520
                  %IDC_BUTTON   =   1525
                  Global hText1           As Dword    'Window handle of Length text box
                  Global hText2           As Dword    'Window handle of Width text box
                  Global hText3           As Dword    'Window handle of results/Area text box
                  Global hBtn             As Dword    'Window handle of button on form
                  Global g_hInst          As Dword    'Global Instance Handle
                  
                  Type WndEventArgs
                    wParam                As Long     'Package parameters to Window Procedure in TYPE
                    lParam                As Long
                    hWnd                  As Dword
                    hInst                 As Dword
                  End Type
                  
                  
                  Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long
                    Local lpCreateStruct As CREATESTRUCT Ptr
                    Local hWnd As Dword
                  
                    Wea.hInst=g_hInst
                    hWnd=CreateWindowEx(0,"static","Length",%WS_CHILD Or %WS_VISIBLE,10,10,80,25,Wea.hWnd,%IDC_LABEL1,Wea.hInst,Byval 0)
                    hText1=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,10,80,25,Wea.hWnd,%IDC_TEXT1,Wea.hInst,Byval 0)
                    SetFocus(hText1)
                    hWnd=CreateWindowEx(0,"static","Width",%WS_CHILD Or %WS_VISIBLE,10,60,80,25,Wea.hWnd,%IDC_LABEL2,Wea.hInst,Byval 0)
                    hText2=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,60,80,25,Wea.hWnd,%IDC_TEXT2,Wea.hInst,Byval 0)
                    hBtn=CreateWindowEx(0,"Button","Calculate",%WS_CHILD Or %WS_VISIBLE,80,120,150,25,Wea.hWnd,%IDC_BUTTON,Wea.hInst,Byval 0)
                    hText3=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,80,200,150,25,Wea.hWnd,%IDC_TEXT3,Wea.hInst,Byval 0)
                    SetFocus(hText1)
                  
                    fnWndProc_OnCreate=0
                  End Function
                  
                  
                  Function fnWndProc_OnCommand(Wea As WndEventArgs) As Long
                    Local dblLength, dblWidth, dblArea As Double
                    Local szBuffer As Asciiz*64
                  
                    If Lowrd(wea.wParam)=%IDC_BUTTON And Hiwrd(Wea.wParam)=%BN_CLICKED Then
                       GetWindowText(hText1,szBuffer,64)
                       dblLength=Val(szBuffer)
                       GetWindowText(hText2,szBuffer,64)
                       dblWidth=Val(szBuffer)
                       szBuffer="Area = " & Format$(dblLength*dblWidth,"######0.00")
                       SetWindowText(hText3,szBuffer)
                    End If
                  
                    fnWndProc_OnCommand=0
                  End Function
                  
                  
                  Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long
                    Call PostQuitMessage(0)
                    fnWndProc_OnDestroy=0
                  End Function
                  
                  
                  Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                    Static Wea As WndEventArgs
                  
                    Select Case As Long wMsg
                      Case %WM_CREATE
                        Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                        fnWndProc=fnWndProc_OnCreate(Wea)
                        Exit Function
                      Case %WM_COMMAND
                        Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                        fnWndProc=fnWndProc_OnCommand(Wea)
                        Exit Function
                      Case %WM_DESTROY
                        Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                        fnWndProc=fnWndProc_OnDestroy(Wea)
                        Exit Function
                    End Select
                  
                    fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
                  End Function
                  
                  Function WinMain(ByVal hIns As Long,ByVal hPrev As Long,ByVal lpCL As Asciiz Ptr,ByVal iShow As Long) As Long
                    Local winclass As WndClassEx
                    Local szAppName As Asciiz*16
                    Local Msg As tagMsg
                    Local hWnd As Dword
                  
                    szAppName="Basic Stuff"
                    g_hInst=hIns
                    winclass.cbSize=SizeOf(winclass)
                    winclass.style=%CS_HREDRAW Or %CS_VREDRAW
                    winclass.lpfnWndProc=CodePtr(fnWndProc)
                    winclass.cbClsExtra=0
                    winclass.cbWndExtra=0
                    winclass.hInstance=hIns
                    winclass.hIcon=LoadIcon(%NULL, ByVal %IDI_APPLICATION)
                    winclass.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW)
                    winclass.hbrBackground=%COLOR_BTNFACE+1
                    winclass.lpszMenuName=%NULL
                    winclass.lpszClassName=VarPtr(szAppName)
                    Call RegisterClassEx(winclass)
                    hWnd=CreateWindow(szAppName,"Pretty Basic Sdk Stuff",%WS_OVERLAPPEDWINDOW,200,100,325,300,0,0,hIns,ByVal 0)
                    Call ShowWindow(hWnd,iShow)
                    While GetMessage(Msg,%NULL,0,0)
                      TranslateMessage Msg
                      DispatchMessage Msg
                    Wend
                  
                    Function=msg.wParam
                  End Function
                  In the above program, to move between the length and width field you need to use your mouse. In the next version of the program I have performed a technique named window subclassing so as to allow the use of the [ENTER] key to set the focus from the first text box to the second and finally to the button. So to get the area all you have to do is keep hitting the [ENTER] key...

                  Code:
                  #Compile Exe
                  #Include "Win32api.inc"
                  %IDC_LABEL1   =   1500
                  %IDC_LABEL2   =   1505
                  %IDC_TEXT1    =   1510
                  %IDC_TEXT2    =   1515
                  %IDC_TEXT3    =   1520
                  %IDC_BUTTON   =   1525
                  Global fnOldEditProc    As Long     'Address of Window Procedure in User32.dll of text box
                  Global fnOldButtonProc  As Long     'Address of Window Procedure in User32.dll of button
                  Global hText1           As Dword    'Window handle of Length text box
                  Global hText2           As Dword    'Window handle of Width text box
                  Global hText3           As Dword    'Window handle of results/Area text box
                  Global hBtn             As Dword    'Window handle of button on form
                  
                  Type WndEventArgs
                    wParam                As Long     'Package parameters to Window Procedure in TYPE
                    lParam                As Long
                    hWnd                  As Dword
                    hInst                 As Dword
                  End Type
                  
                  Function fnNewEditProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                    If wMsg=%WM_CHAR Then
                       Select Case hWnd
                         Case hText1    'Length text box
                           If wParam=13 Or wParam=9 Then
                              Call SetFocus(hText2)
                           End If
                         Case hText2
                           If wParam=13 Or wParam=9 Then
                              Call SetFocus(hBtn)
                           End If
                       End Select
                    End If
                  
                    fnNewEditProc=CallWindowProc(fnOldEditProc,hWnd,wMsg,wParam,lParam)
                  End Function
                  
                  
                  Function fnNewButtonProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                    Local hParent As Dword
                    Local iParam As Long
                  
                    If wMsg=%WM_CHAR And wParam=13 Then
                       iParam=MakLng(%IDC_BUTTON,%BN_CLICKED)
                       hParent=GetParent(hWnd)
                       SendMessage(hParent,%WM_COMMAND,iParam,hWnd)
                    End If
                  
                    fnNewButtonProc=CallWindowProc(fnOldButtonProc,hWnd,wMsg,wParam,lParam)
                  End Function
                  
                  
                  Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long
                    Local lpCreateStruct As CREATESTRUCT Ptr
                    Local hWnd As Dword
                  
                    lpCreateStruct=Wea.lParam   'Can use GetModuleHandle() here instead
                    [email protected]
                    hWnd=CreateWindowEx(0,"static","Length",%WS_CHILD Or %WS_VISIBLE,10,10,80,25,Wea.hWnd,%IDC_LABEL1,Wea.hInst,Byval 0)
                    hText1=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,10,80,25,Wea.hWnd,%IDC_TEXT1,Wea.hInst,Byval 0)
                    fnOldEditProc=SetWindowLong(hText1,%GWL_WNDPROC,CodePtr(fnNewEditProc))
                    SetFocus(hWnd)
                    hWnd=CreateWindowEx(0,"static","Width",%WS_CHILD Or %WS_VISIBLE,10,60,80,25,Wea.hWnd,%IDC_LABEL2,Wea.hInst,Byval 0)
                    hText2=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,60,80,25,Wea.hWnd,%IDC_TEXT2,Wea.hInst,Byval 0)
                    fnOldEditProc=SetWindowLong(hText2,%GWL_WNDPROC,CodePtr(fnNewEditProc))
                    hBtn=CreateWindowEx(0,"Button","Calculate",%WS_CHILD Or %WS_VISIBLE,80,120,150,25,Wea.hWnd,%IDC_BUTTON,Wea.hInst,Byval 0)
                    fnOldButtonProc=SetWindowLong(hBtn,%GWL_WNDPROC,CodePtr(fnNewButtonProc))
                    hText3=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,80,200,150,25,Wea.hWnd,%IDC_TEXT3,Wea.hInst,Byval 0)
                    SetFocus(hText1)
                  
                    fnWndProc_OnCreate=0
                  End Function
                  
                  
                  Function fnWndProc_OnCommand(Wea As WndEventArgs) As Long
                    Local dblLength, dblWidth, dblArea As Double
                    Local szBuffer As Asciiz*64
                  
                    If Lowrd(wea.wParam)=%IDC_BUTTON And Hiwrd(Wea.wParam)=%BN_CLICKED Then
                       GetWindowText(hText1,szBuffer,64)
                       dblLength=Val(szBuffer)
                       GetWindowText(hText2,szBuffer,64)
                       dblWidth=Val(szBuffer)
                       szBuffer="Area = " & Format$(dblLength*dblWidth,"######0.00")
                       SetWindowText(hText3,szBuffer)
                    End If
                  
                    fnWndProc_OnCommand=0
                  End Function
                  
                  
                  Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long
                    Call PostQuitMessage(0)
                    fnWndProc_OnDestroy=0
                  End Function
                  
                  
                  Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                    Static Wea As WndEventArgs
                  
                    Select Case As Long wMsg
                      Case %WM_CREATE
                        Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                        fnWndProc=fnWndProc_OnCreate(Wea)
                        Exit Function
                      Case %WM_COMMAND
                        Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                        fnWndProc=fnWndProc_OnCommand(Wea)
                        Exit Function
                      Case %WM_DESTROY
                        Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                        fnWndProc=fnWndProc_OnDestroy(Wea)
                        Exit Function
                    End Select
                  
                    fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
                  End Function
                  
                  Function WinMain(ByVal hIns As Long,ByVal hPrev As Long,ByVal lpCL As Asciiz Ptr,ByVal iShow As Long) As Long
                    Local winclass As WndClassEx
                    Local szAppName As Asciiz*16
                    Local Msg As tagMsg
                    Local hWnd As Dword
                  
                    szAppName="Basic Stuff"
                    winclass.cbSize=SizeOf(winclass)
                    winclass.style=%CS_HREDRAW Or %CS_VREDRAW
                    winclass.lpfnWndProc=CodePtr(fnWndProc)
                    winclass.cbClsExtra=0
                    winclass.cbWndExtra=0
                    winclass.hInstance=hIns
                    winclass.hIcon=LoadIcon(%NULL, ByVal %IDI_APPLICATION)
                    winclass.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW)
                    winclass.hbrBackground=%COLOR_BTNFACE+1
                    winclass.lpszMenuName=%NULL
                    winclass.lpszClassName=VarPtr(szAppName)
                    Call RegisterClassEx(winclass)
                    hWnd=CreateWindow(szAppName,"Pretty Basic Sdk Stuff",%WS_OVERLAPPEDWINDOW,200,100,325,300,0,0,hIns,ByVal 0)
                    Call ShowWindow(hWnd,iShow)
                    While GetMessage(Msg,%NULL,0,0)
                      TranslateMessage Msg
                      DispatchMessage Msg
                    Wend
                  
                    Function=msg.wParam
                  End Function
                  Finally, here is the last version of the program with all global variables removed...

                  Code:
                  #Compile Exe
                  #Include "Win32api.inc"
                  %IDC_LABEL1   =   1500
                  %IDC_LABEL2   =   1505
                  %IDC_TEXT1    =   1510
                  %IDC_TEXT2    =   1515
                  %IDC_TEXT3    =   1520
                  %IDC_BUTTON   =   1525
                  Global fnOldEditProc    As Long
                  Global fnOldButtonProc  As Long
                  
                  Type WndEventArgs
                    wParam                As Long          'Package parameters to Window Procedure in TYPE
                    lParam                As Long
                    hWnd                  As Dword
                    hInst                 As Dword
                  End Type
                  
                  Function fnNewEditProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                    If wMsg=%WM_CHAR Then
                       Select Case GetDlgCtrlID(hWnd)
                         Case %IDC_TEXT1
                           If wParam=13 Or wParam=9 Then
                              Call SetFocus(GetDlgItem(GetParent(hWnd),%IDC_TEXT2))
                           End If
                         Case %IDC_TEXT2
                           If wParam=13 Or wParam=9 Then
                              Call SetFocus(GetDlgItem(GetParent(hWnd),%IDC_BUTTON))
                           End If
                       End Select
                    End If
                  
                    fnNewEditProc=CallWindowProc(fnOldEditProc,hWnd,wMsg,wParam,lParam)
                  End Function
                  
                  
                  Function fnNewButtonProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                    If wMsg=%WM_CHAR And wParam=13 Then
                       SendMessage(GetParent(hWnd),%WM_COMMAND,MakDwd(%IDC_BUTTON,%BN_CLICKED),GetDlgItem(hWnd,%IDC_BUTTON))
                    End If
                  
                    fnNewButtonProc=CallWindowProc(fnOldButtonProc,hWnd,wMsg,wParam,lParam)
                  End Function
                  
                  
                  Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long
                    Local lpCreateStruct As CREATESTRUCT Ptr
                    Local hWnd As Dword
                  
                    lpCreateStruct=Wea.lParam   'Can use GetModuleHandle() here instead
                    [email protected]
                    hWnd=CreateWindowEx(0,"static","Length",%WS_CHILD Or %WS_VISIBLE,10,10,80,25,Wea.hWnd,%IDC_LABEL1,Wea.hInst,Byval 0)
                    hWnd=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,10,80,25,Wea.hWnd,%IDC_TEXT1,Wea.hInst,Byval 0)
                    SetFocus(hWnd)
                    fnOldEditProc=SetWindowLong(hWnd,%GWL_WNDPROC,CodePtr(fnNewEditProc))
                    hWnd=CreateWindowEx(0,"static","Width",%WS_CHILD Or %WS_VISIBLE,10,60,80,25,Wea.hWnd,%IDC_LABEL2,Wea.hInst,Byval 0)
                    hWnd=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,60,80,25,Wea.hWnd,%IDC_TEXT2,Wea.hInst,Byval 0)
                    fnOldEditProc=SetWindowLong(hWnd,%GWL_WNDPROC,CodePtr(fnNewEditProc))
                    hWnd=CreateWindowEx(0,"Button","Calculate",%WS_CHILD Or %WS_VISIBLE,80,120,150,25,Wea.hWnd,%IDC_BUTTON,Wea.hInst,Byval 0)
                    fnOldButtonProc=SetWindowLong(hWnd,%GWL_WNDPROC,CodePtr(fnNewButtonProc))
                    hWnd=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,80,200,150,25,Wea.hWnd,%IDC_TEXT3,Wea.hInst,Byval 0)
                  
                    fnWndProc_OnCreate=0
                  End Function
                  
                  
                  Function fnWndProc_OnCommand(Wea As WndEventArgs) As Long
                    Local dblLength, dblWidth, dblArea As Double
                    Local szBuffer As Asciiz*64
                  
                    If Lowrd(wea.wParam)=%IDC_BUTTON And Hiwrd(Wea.wParam)=%BN_CLICKED Then
                       GetWindowText(GetDlgItem(Wea.hWnd,%IDC_TEXT1),szBuffer,64)
                       dblLength=Val(szBuffer)
                       GetWindowText(GetDlgItem(Wea.hWnd,%IDC_TEXT2),szBuffer,64)
                       dblWidth=Val(szBuffer)
                       szBuffer="Area = " & Format$(dblLength*dblWidth,"######0.00")
                       SetWindowText(GetDlgItem(Wea.hWnd,%IDC_TEXT3),szBuffer)
                    End If
                  
                    fnWndProc_OnCommand=0
                  End Function
                  
                  
                  Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long
                    Call PostQuitMessage(0)
                    fnWndProc_OnDestroy=0
                  End Function
                  
                  
                  Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                    Static Wea As WndEventArgs
                  
                    Select Case As Long wMsg
                      Case %WM_CREATE
                        Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                        fnWndProc=fnWndProc_OnCreate(Wea)
                        Exit Function
                      Case %WM_COMMAND
                        Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                        fnWndProc=fnWndProc_OnCommand(Wea)
                        Exit Function
                      Case %WM_DESTROY
                        Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                        fnWndProc=fnWndProc_OnDestroy(Wea)
                        Exit Function
                    End Select
                  
                    fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
                  End Function
                  
                  Function WinMain(ByVal hIns As Long,ByVal hPrev As Long,ByVal lpCL As Asciiz Ptr,ByVal iShow As Long) As Long
                    Local winclass As WndClassEx
                    Local szAppName As Asciiz*16
                    Local Msg As tagMsg
                    Local hWnd As Dword
                  
                    szAppName="Basic Stuff"
                    winclass.cbSize=SizeOf(winclass)
                    winclass.style=%CS_HREDRAW Or %CS_VREDRAW
                    winclass.lpfnWndProc=CodePtr(fnWndProc)
                    winclass.cbClsExtra=0
                    winclass.cbWndExtra=0
                    winclass.hInstance=hIns
                    winclass.hIcon=LoadIcon(%NULL, ByVal %IDI_APPLICATION)
                    winclass.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW)
                    winclass.hbrBackground=%COLOR_BTNFACE+1
                    winclass.lpszMenuName=%NULL
                    winclass.lpszClassName=VarPtr(szAppName)
                    Call RegisterClassEx(winclass)
                    hWnd=CreateWindow(szAppName,"Form1",1040384,200,100,325,300,0,0,hIns,ByVal 0)
                    Call ShowWindow(hWnd,iShow)
                    While GetMessage(Msg,%NULL,0,0)
                      TranslateMessage Msg
                      DispatchMessage Msg
                    Wend
                  
                    Function=msg.wParam
                  End Function
                  It might be interesting to note how I created the WM_COMMAND message in the above two examples so as to simulate a button click by just hitting the [ENTER] key when the button has the focus.
                  Fred
                  "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                  Comment


                    #10
                    beginner on entermov.bas

                    Peter

                    I had tried that while I was waiting for your reply, but now I find I,m getting a 'Failure' at the following line, which seems to suggest that it is not proper Basic.

                    s# = (VAL(SideA$) + VAL(SideB$) + VAL(SideC$) )/2


                    I have created a SUB at the end of the program as follows and made a CALL CalculateTriangle (SideA$,SideB$.....) on the line immediately following the 4 extra lines you suggested.

                    SUB CalculateTriangle (sidea$,sideB$,SideC$,AngleA$,angleB$,AngleC$)

                    s# = (VAL(SideA$) + VAL(SideB$) + VAL(SideC$) )/2
                    k1# = (s# - VAL(SideA$)) * (s# - VAL(SideB$)) * (s# - VAL(SideAC))
                    k =SQR(k1#/s#)

                    Radian# = 180/3.141592654

                    e1# = SIN(VAL(angleB$)/ Radian#
                    e2# = SQR(1 - e1# * e1#)

                    Angle_BAcute# = ATAN(e1#/ e2#) * Radian#
                    Angle_BObtuse# = ATAN(e1#/ -e2#) * Radian#

                    END SUB

                    There must besomething fundamentally wrong with my programming.

                    Can you make any suggestions.

                    Thank you
                    Warren
                    '**************************************************

                    Fred

                    Thanks for all that code, but it will take me a while to absorb it all and work out what it all means. While I've used PB-DOS and VB5 for some years now, I'm completely new to PB-WIN and finding it hard going.

                    I'll probably get back to you for some explanation here and there.

                    warren
                    Warren Sugden

                    Comment


                      #11
                      Beginner on EnterMov.bas

                      Fred Harris

                      I have managed to get all 4 programs up and running, but I'm at a loss to grasp and understand the code. The PB reference book doesn't offer much in the way of explanation of the processes and really only gives a broad outline.

                      Can you recommend a text book which can give more detailed explanation of the object, function and purpose of each piece of code.

                      I note your comments on GetWindowText() and have got a broad idea of what is going on. I ran the debugger to trace through the program step by step but I'm confused as to what is happening.

                      Thank you for your help.

                      Warren Sugden
                      Warren Sugden

                      Comment


                        #12
                        I had tried that while I was waiting for your reply, but now I find I,m getting a 'Failure' at the following line, which seems to suggest that it is not proper Basic.

                        s# = (VAL(SideA$) + VAL(SideB$) + VAL(SideC$) )/2
                        The line compiles just fine here... Can you give exact error text/position?
                        Regards,
                        Peter

                        "Simplicity is a prerequisite for reliability"

                        Comment


                          #13
                          Yes Warren, there is a whole lot going on there so don't feel at all bad if its not at all clear. I realize at this time you are concentrating on the 'built in' native PowerBASIC commands in your transition to Windows programming with PowerBASIC. My intent in providing the code was to show a more 'generalized' way of doing what you want using the low level Windows Application Programming Interface instead of the PowerBASIC statements. Indeed, it might be advantageous to proceed slowly with both techniques.

                          Most folks here - including myself, recommend Charles Petzold's books - "Programming Windows 95" or "Programming Windows 98" to learn how to use the internal Windows functions that are part of the operating system to program Windows. The main problem there is that the examples are all in C. I know this is hard to believe, but that doesn't matter much. His books aren't C tutorials. You can glean much from them.

                          Also, Ed Turner is actually writting or already has written a book on Api programming with PowerBASIC. Here is a hopefully useful link...

                          User to user discussions of third-party addons and user-recommended links to related web sites. Advertisements are permitted only in this forum, for products designed to work with and enhance PowerBASIC compilers.


                          also another...

                          User to user discussions about the PB/Win (formerly PB/DLL) product line. Discussion topics include PowerBASIC Forms, PowerGEN and PowerTree for Windows.


                          I've written a tutorial also on the subject that explains things in considerable detail. Here are links for that...

                          PB



                          Also, at Jose Roca's new web site...



                          If you can get through the first one or two, you'll be off to a good start!
                          Fred
                          "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                          Comment


                            #14
                            Beginner on EnterMov.bas

                            Fred Harris

                            Thanks for those useful tips.

                            i've already printed out Ted Turners chapt 1 (he's got 5 chapters written) and it is exactly what I was looking for, although I can't say I fully understand it all, but at least it allows one to get a better handle on what is going on. I can see the similarities in his code to yours. It seems to me that I could use your code as a template for similar types of programs. I presume you have no objection ???.

                            I'm now going to your tutorials.

                            Warren Sugden
                            Warren Sugden

                            Comment


                              #15
                              Beginner on EnterMov.bas

                              Peter

                              It's OK now !!

                              I had to enter the following line of code.

                              DIM s#,k1#,k#,radian#,e1#,e2#,Angle_BAcute#,Angle_BObtuse#

                              Even so, I'm sure I'll be back with more questions !!!

                              Warren
                              Warren Sugden

                              Comment


                                #16
                                VB Style In PowerBASIC

                                Here is a further development of the program whiich might pull some pieces together for you in terms of your VB experience. If you were coding this in VB you would have a button on your form with a caption of "Calculate" or something llike that. When you double clicked on that button in 'Design View' of VB a code editing window would open for you, and if the 'name' of the button was cmdCalculate, the procedure you would see in your VB code editor would be cmdCalculate_Click(). I've done that exact thing for you here in this next version of the program. In addition, I added a 'Clear' button to clear the textboxes, and associated with that you will find a cmdClear_Click() procedure. Also worthwhile are techniques to limit input to textboxes in terms of acceptable inputs or characters. Since the previous programs already had all the controls subclassed, I added code to the text box's subclass procedure to filter out all keystrokes but the numbers, backspace, and decimal point. Finally, code was added to facilitate rapid data entry in terms of eliminating the necessity of any mouse interaction with the program. By continually hitting the [ENTER] key the program will continually cycle through all the text boxes and buttons. Feel free to use any of this code in yoiur work.

                                Code:
                                #Compile Exe
                                #Include "Win32api.inc"
                                %VK_PERIOD      =     46
                                %IDC_LABEL1     =   1500
                                %IDC_LABEL2     =   1505
                                %IDC_LENGTH     =   1510
                                %IDC_WIDTH      =   1515
                                %IDC_AREA       =   1520
                                %IDC_CALCULATE  =   1525
                                %IDC_CLEAR      =   1530
                                
                                Global fnOldEditProc    As Long
                                Global fnOldButtonProc  As Long
                                
                                Type WndEventArgs
                                  wParam                As Long          'Package parameters to Window Procedure in TYPE
                                  lParam                As Long
                                  hWnd                  As Dword
                                  hInst                 As Dword
                                End Type
                                
                                
                                Function fnNewEditProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                                  If wMsg=%WM_CHAR Then
                                     Select Case Lowrd(wParam)          'This is known as a subclass procedure.  If you look down two procedures
                                       Case %VK_BACK      'backspace    'below this in fnWndProc_OnCreate(), on the fifth line down after the
                                         'backspace is OK               'variable declarations you'll see a call to the Api function SetWindowLong().
                                       Case %VK_TAB, %VK_RETURN         'This call immediately follows the CreateWindow() call that creates the 
                                         Select Case GetDlgCtrlID(hWnd) '%IDC_LENGTH edit control.  The hCtrl first parameter is the window handle  
                                           Case %IDC_LENGTH             'of this text box.  The 2nd parameter - %GWL_WNDPROC, tells Windows that a 
                                             Call SetFocus(GetDlgItem(GetParent(hWnd),%IDC_WIDTH))     'new window procedure for the specified 
                                           Case %IDC_WIDTH                                             'window (the text box) is going to be specified.  
                                             Call SetFocus(GetDlgItem(GetParent(hWnd),%IDC_CALCULATE)) 'The third parameter is the virtual address
                                         End Select                                                    'of this new window procedure.  The PowerBASIC
                                       Case %VK_PERIOD 'Period/Decimal Point  'CodePtr function will return the dynamic address of this procedure -
                                         'Decimal Point                       'fnNewEditProc to the operating system.  Note that this procedure finally
                                       Case %VK_0 To %VK_9                    'calls the original window procedure - fnOldEditProc, for default message
                                         'A number key was pressed            'processing
                                       Case Else      'If any other key is pressed other than one of those listed above,
                                         wParam=0     'it will be contained in wParam and it will be collected here in
                                     End Select       'the 'Else' clause.  Here it will be 'eaten' rather than passed on
                                  End If              'to the original text box window procedure in User32.dll.  Therefore,
                                                      'it won't show up in the text box
                                  fnNewEditProc=CallWindowProc(fnOldEditProc,hWnd,wMsg,wParam,lParam)
                                End Function
                                
                                '***************************************************************************************************************
                                'fnNewButtonProc is a subclass window procedure for the both buttons on the form/dialog.  The only two global   
                                'variables in this program are fnOldEditProc and fnOldButtonProc, and these two 'variables' aren't really
                                'variables in the usual sense, but they are rather addresses of functions.  The SetWindowLong Api function as
                                'described immediately above is used in fnWndProc_OnCreate() immediately below to reset the window procedures
                                'of the text boxes and the buttons so that all the messages for those controls will become available in this
                                'application for examination here.  In the case of buttons, when a button on a form/dialog is mouse clicked,
                                'the button will send a %WM_COMMAND message to the parent of the button, which is the main program window.  That
                                'message will contain both the control id of the button and a %BN_CLICKED notification code.  However, while a
                                'button has the input focus, the pressing of a key such as the [ENTER] key or any other key for that matter will
                                'not cause any messages to be sent to the main program window indicating that a character key has been received
                                'by the button.  They will be received by the button's internal window procedure in User32.dll, but that window
                                'procedure is not present in this application.  The SetWindowLong() call in conjunction with the parameter
                                'settings as seen below in fnWndProc_OnCreate() will specify a procedure in this application that is to be called
                                'in place of the internal default window procedure as specified by windows for these controls.  In that way we 
                                'can respond to a press of the [ENTER] key while the 'Calculate' button has the focus by calculating the area of
                                'the rectangle and displaying it in the %IDC_AREA text box.  Note that the processing we do here in fnNewButtonProc
                                'is rather devious in that instead of calculating the area of the rectangle directly, we concoct a phony WM_COMMAND
                                'message - which ordinarily is sent to a parent window in response to a button click, and send that message.  In
                                'this procedure we first check that a character message has been received by the button, then we check that it is
                                'the [ENTER] key, and finally we determine which of the two buttons received the keypress.  If the 'Calculate'
                                'button, we use the Api function SendMessage() to send a button click to the main window so that the code in
                                'cmdCalculate_Click() can calculate the area and display it in the text box just as if the cmdCalculate button was
                                'pressed.  The first parameter to SendMessage() is the window handle of the window that is to receive the message.
                                'In this case we need to use the GetParent() function because the hWnd parameter received in this subclass function
                                'is the handle of the button, not the handle of the main window that is the target of the message to be 
                                'SendMessag()'ed.  The second parameter is the Window's message to be sent, and we want to send a %WM_COMMAND message
                                'because that is the message a parent of a button receives when a button is pressed.  The third parameter is the
                                'wParam parameter of a window procedure, and associated with a WM_COMMAND button click the low order 16 bits of
                                'the 32 bit value is the control id of the button, and the high order 16 bits is the %BN_CLICKED notification
                                'message.  The fourth lParam parameter needs to be the handle of the button.  I see I made things unnecessarily
                                'complicated here by using the GetDlgItem() function to retrieve the hWnd of the button as I could have just
                                'used the hWnd in the first parameter of fnNewButtonProc.  I'll let the top one go and change the 'Clear' button's
                                'code below to simplify the call.  
                                '***************************************************************************************************************
                                Function fnNewButtonProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                                  If wMsg=%WM_CHAR And wParam=%VK_RETURN And GetDlgCtrlID(hWnd) = %IDC_CALCULATE Then
                                     SendMessage(GetParent(hWnd),%WM_COMMAND,MakDwd(%IDC_CALCULATE,%BN_CLICKED),GetDlgItem(hWnd,%IDC_CALCULATE))
                                  End If
                                  If wMsg=%WM_CHAR And wParam=%VK_RETURN And GetDlgCtrlID(hWnd) = %IDC_CLEAR Then
                                     SendMessage(GetParent(hWnd),%WM_COMMAND,MakDwd(%IDC_CLEAR,%BN_CLICKED),hWnd)
                                  End If
                                
                                  fnNewButtonProc=CallWindowProc(fnOldButtonProc,hWnd,wMsg,wParam,lParam)
                                End Function
                                
                                
                                Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long
                                  Local lpCreateStruct As CREATESTRUCT Ptr
                                  Local hCtrl As Dword
                                
                                  lpCreateStruct=Wea.lParam   'Can use GetModuleHandle() here instead
                                  [email protected]
                                  hCtrl=CreateWindowEx(0,"static","Length",%WS_CHILD Or %WS_VISIBLE,10,10,80,25,Wea.hWnd,%IDC_LABEL1,Wea.hInst,Byval 0)
                                  hCtrl=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,10,80,25,Wea.hWnd,%IDC_LENGTH,Wea.hInst,Byval 0)
                                  fnOldEditProc=SetWindowLong(hCtrl,%GWL_WNDPROC,CodePtr(fnNewEditProc))
                                  hCtrl=CreateWindowEx(0,"static","Width",%WS_CHILD Or %WS_VISIBLE,10,60,80,25,Wea.hWnd,%IDC_LABEL2,Wea.hInst,Byval 0)
                                  hCtrl=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,120,60,80,25,Wea.hWnd,%IDC_WIDTH,Wea.hInst,Byval 0)
                                  fnOldEditProc=SetWindowLong(hCtrl,%GWL_WNDPROC,CodePtr(fnNewEditProc))
                                  hCtrl=CreateWindowEx(0,"Button","Calculate",%WS_CHILD Or %WS_VISIBLE,80,120,150,25,Wea.hWnd,%IDC_CALCULATE,Wea.hInst,Byval 0)
                                  fnOldButtonProc=SetWindowLong(hCtrl,%GWL_WNDPROC,CodePtr(fnNewButtonProc))
                                  hCtrl=CreateWindowEx(%WS_EX_CLIENTEDGE,"Edit","",%WS_CHILD Or %WS_VISIBLE,80,180,150,25,Wea.hWnd,%IDC_AREA,Wea.hInst,Byval 0)
                                  hCtrl=CreateWindowEx(0,"Button","Clear",%WS_CHILD Or %WS_VISIBLE,125,225,60,25,Wea.hWnd,%IDC_CLEAR,Wea.hInst,Byval 0)
                                  fnOldButtonProc=SetWindowLong(hCtrl,%GWL_WNDPROC,CodePtr(fnNewButtonProc))
                                  SetFocus(GetDlgItem(wea.hWnd,%IDC_LENGTH))
                                
                                  fnWndProc_OnCreate=0
                                End Function
                                
                                
                                Sub cmdCalculate_Click(Wea As WndEventArgs)
                                  Local dblLength, dblWidth, dblArea As Double
                                  Local szBuffer As Asciiz*64
                                
                                  GetWindowText(GetDlgItem(Wea.hWnd,%IDC_LENGTH),szBuffer,64)
                                  dblLength=Val(szBuffer)
                                  GetWindowText(GetDlgItem(Wea.hWnd,%IDC_WIDTH),szBuffer,64)
                                  dblWidth=Val(szBuffer)
                                  szBuffer="Area = " & Format$(dblLength*dblWidth,"######0.00")
                                  SetWindowText(GetDlgItem(Wea.hWnd,%IDC_AREA),szBuffer)
                                  SetFocus(GetDlgItem(Wea.hWnd,%IDC_CLEAR))
                                End Sub
                                
                                
                                Sub cmdClear_Click(Wea As WndEventArgs)
                                  Local hEdit As Dword
                                
                                  hEdit=GetDlgItem(Wea.hWnd,%IDC_LENGTH)
                                  SetWindowText(hEdit,"")
                                  SetFocus(hEdit)
                                  hEdit=GetDlgItem(Wea.hWnd,%IDC_WIDTH)
                                  SetWindowText(hEdit,"")
                                  hEdit=GetDlgItem(Wea.hWnd,%IDC_AREA)
                                  SetWindowText(hEdit,"")
                                End Sub
                                
                                
                                Function fnWndProc_OnCommand(Wea As WndEventArgs) As Long
                                  Select Case As Long Lowrd(wea.wParam)
                                    Case %IDC_CALCULATE
                                      If Hiwrd(Wea.wParam)=%BN_CLICKED Then
                                         Call cmdCalculate_Click(Wea)
                                      End If
                                    Case %IDC_CLEAR
                                      If Hiwrd(Wea.wParam)=%BN_CLICKED Then
                                         Call cmdClear_Click(Wea)
                                      End If
                                  End Select
                                
                                  fnWndProc_OnCommand=0
                                End Function
                                
                                
                                Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long
                                  Call PostQuitMessage(0)
                                  fnWndProc_OnDestroy=0
                                End Function
                                
                                
                                Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
                                  Local Wea As WndEventArgs
                                
                                  Select Case As Long wMsg
                                    Case %WM_CREATE
                                      Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                                      fnWndProc=fnWndProc_OnCreate(Wea)
                                      Exit Function
                                    Case %WM_COMMAND
                                      Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                                      fnWndProc=fnWndProc_OnCommand(Wea)
                                      Exit Function
                                    Case %WM_DESTROY
                                      Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
                                      fnWndProc=fnWndProc_OnDestroy(Wea)
                                      Exit Function
                                  End Select
                                
                                  fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
                                End Function
                                
                                
                                Function WinMain(ByVal hIns As Long,ByVal hPrev As Long,ByVal lpCL As Asciiz Ptr,ByVal iShow As Long) As Long
                                  Local winclass As WndClassEx
                                  Local szAppName As Asciiz*16
                                  Local Msg As tagMsg
                                  Local hWnd As Dword
                                
                                  szAppName="Basic Stuff"
                                  winclass.cbSize=SizeOf(winclass)
                                  winclass.style=%CS_HREDRAW Or %CS_VREDRAW
                                  winclass.lpfnWndProc=CodePtr(fnWndProc)
                                  winclass.cbClsExtra=0
                                  winclass.cbWndExtra=0
                                  winclass.hInstance=hIns
                                  winclass.hIcon=LoadIcon(%NULL, ByVal %IDI_APPLICATION)
                                  winclass.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW)
                                  winclass.hbrBackground=%COLOR_BTNFACE+1
                                  winclass.lpszMenuName=%NULL
                                  winclass.lpszClassName=VarPtr(szAppName)
                                  Call RegisterClassEx(winclass)
                                  hWnd=CreateWindow(szAppName,"Basic Form",%WS_OVERLAPPEDWINDOW,200,100,325,300,0,0,hIns,ByVal 0)
                                  Call ShowWindow(hWnd,iShow)
                                  While GetMessage(Msg,%NULL,0,0)
                                    Call TranslateMessage(Msg)
                                    Call DispatchMessage(Msg)
                                  Wend
                                
                                  Function=msg.wParam
                                End Function
                                Had to re-edit this Sunday, as I found a mistake. Also adding comments. FJH
                                Last edited by Fred Harris; 16 Dec 2007, 03:38 PM. Reason: Found Mistake in Subclass procedure for Edit Controls
                                Fred
                                "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                                Comment


                                  #17
                                  Beginner on EnterMov

                                  Fred Harris

                                  Although I have had some difficulty understanding the last part of your Tutorial 1, I have now moved onto Tutorial 2, and have run the 1st version of Form2.

                                  I have run the Form 2 program in Debug mode step by step starting at the first line of WINMain which is the entry point.

                                  Firstly there are some variables which are set up, then to 'RegisterClassEx' which is a routine that tells Windows something but presumably has no impact on my understanding of what follows.

                                  Next comes hMainWnd=CreateWindowEx(0,szClassName,..........etc) which again I presumes simply creates the variable 'hMainWnd' but does nothing else to this point. Presumable, the purpose is to save having to type out the whole of 'CreateWindowEx........etc" in the next step.

                                  Next comes 'CALL ShowWindow(hMainWnd,iShow)' which includes the variable hMainWnd which presumably runs and part of that process is to Call WinProc with wmsg initially set to 36. Where did 36 come from ????.

                                  WinProc loops through several times with changing values of wmsg until wmsg = 1 which initiates %WM_Create. But what is the purpose and function of these other numbers and where do they come from ????.

                                  The routine where wmsg = %WM_Create opens up a whole new can of worms for me, but I'd like some explanation of what is going on up to this point.

                                  Hoping for a response.

                                  Warren Sugden
                                  Warren Sugden

                                  Comment


                                    #18
                                    Firstly there are some variables which are set up, then to 'RegisterClassEx' which is a routine
                                    that tells Windows something but presumably has no impact on my understanding of what follows.
                                    Everything in Windows is a window. A textbox on a form/dialog is a window. So is the 'window'
                                    that contains a textbox also a window. A label is a window. A combo box is a window. Everything
                                    is a window and every window is a member or described by (in a general sense) a WINDOW CLASS.

                                    During the WinMain() function a program typically registers a window class for what will be the
                                    main application window. One of the members of the structure/type variable of TYPE WNDCLASSEX
                                    is the name that Windows will use to identify this specific application class (lpszClassName).

                                    When you call the CreateWindowEx() function you are telling Windows that you wish to create a
                                    specific window that will be of a general type described by the 2nd parameter of that call, which
                                    is the string that identifies the Window Class. For example, if you fill out the members of
                                    a WNDCLASSES variable and specify a class name for the lpszClass name parameter of "Borg", if
                                    you want to create a specific instance of this class, that is 'birth' it, bring it into 'being',
                                    instantiate it, you do that by using the CreateWindowEx() function and specifying "Borg" for the
                                    second parameter, i.e.,

                                    hBorg = CreateWindowEx(0,"Borg", ......)

                                    If this function call succeeds hBorg will contain a non-null value and Windows will set up quite a
                                    bit of internal machinery that will allow this window to exist under Windows. However, it will at
                                    this point not appear on your screen. However, interestingly enough, before the the above call
                                    completes and some non-zero value is assigned to the value hBorg, Windows will have already sent
                                    several messages to the Window Procedure of this new window. Because, to begin with, if "Borg" is
                                    not a class already 'Registered' with Windows, it will nor know what a "Borg" is and the CreateWindowEx()
                                    call will fail. If the class was satisfactorily registered (made known to Windows), it will know
                                    which function in your program will be receiving its barrage of messages that Windows will be
                                    firing off in response to any user activity relating to the window. If in the registration process
                                    a suitable Window Procedure wasn't found by Windows, that too would have caused the class not to
                                    register.

                                    So the concept of the Window Procedure is inextricably bound up with the concept of the registration
                                    of a Window Class and the creation of any specific window based on a Window Class.

                                    During that CreateWindowEx() call and before it returns and assigns a value to hBorg, the Window Procedure
                                    will have received a %WM_CREATE message (among others). It is not unusual in Windows Api programming
                                    to initialize other windows during that WM_CREATE message. I believe this message corresponds to
                                    Visual Basic's Form_Load() event. If a main program window is to be decorated by other windows such
                                    as labels, text boxes, list boxes, etc., CreateWindow() calls can occur during the processing of
                                    the main window's WM_CREATE message to initialize these windows. For example, the Window Class name
                                    for a text box is "edit", and for a label is "static". These are predefined classes you can use courtesy
                                    of the Microsoft Company. So, if you have these CreateWindowEx() calls for these pre-defined window
                                    controls occurring durring the processing of you Main Application Window's WM_CREATE message, these
                                    pre-defined windows will generate WM_CREATE messages of their own but you won't receive them in any
                                    procedure in your program; they will occur in internal Windows code in various system dlls.

                                    So, at the point of the CreateWindowEx() call that creates a main program window, quite a lot happens
                                    although none of it is visible. Also, if nothing in WinMain() is done after the successful CreateWindowEx()
                                    call, no windows will become visible and the program won't run.

                                    This is a point at which I believe a heavy previous background in Advanced level DOS programming is really
                                    benificial in understanding the Windows programming model, in that either the operating system or the
                                    program itself must drop into some kind of loop where all external sources of program input are monitored
                                    so that a running program is constantly kept informed of program inputs, that is keystrokes, mouse movements,
                                    mouse clicks, COM port activity, etc. That is what occurs in the While - Wend loop at the bottom of
                                    WinMain(). After a ShowWindow() call that makes a program's main Window visible, every time any system event
                                    occurs that pertains to the given window, that window will receive a message from Windows (the OS) containing
                                    a packet of information about the message.

                                    It is my opinion that you won't make much sense of it at all using a step through debugger. In my DOS
                                    programming days and carried on into Windows I never made much use of debuggers. Others I know swear
                                    by them, so do as you please. But for understanding the messaging system of Windows my recommendation
                                    is to open up output log files and print debug output to them. I may or may not receive flack on this
                                    recommendation, but its what I do for better or worse.
                                    Fred
                                    "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                                    Comment


                                      #19
                                      WinProc loops through several times with changing values of wmsg until wmsg = 1 which initiates %WM_Create. But what is the purpose and function of these other numbers and where do they come from ????.
                                      The changing of the value of wMsg is caused by Windows sending the Window Procedure a different message every time something of interest to the program happens. You ought to open Win32Api.inc and search for %WM_CREATE and you'll see its equal to 1. Here's a bunch of them. These are messages. Its how Windows communicates with a program. Its absolutely fundamental...

                                      Code:
                                      ' Window Messages
                                      %WM_NULL     = &H0
                                      %WM_CREATE   = &H1
                                      %WM_DESTROY  = &H2
                                      %WM_MOVE     = &H3
                                      %WM_SIZE     = &H5
                                      
                                      %WM_ACTIVATE = &H6
                                      '
                                      ' WM_ACTIVATE state values
                                      
                                      %WA_INACTIVE    = 0
                                      %WA_ACTIVE      = 1
                                      %WA_CLICKACTIVE = 2
                                      
                                      %WM_SETFOCUS         = &H7
                                      %WM_KILLFOCUS        = &H8
                                      %WM_ENABLE           = &HA
                                      %WM_SETREDRAW        = &HB
                                      %WM_SETTEXT          = &HC
                                      %WM_GETTEXT          = &HD
                                      %WM_GETTEXTLENGTH    = &HE
                                      %WM_PAINT            = &HF
                                      %WM_CLOSE            = &H10
                                      Fred
                                      "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                                      Comment

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