Announcement

Collapse
No announcement yet.

Beginner on EnterMov.BAS

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

  • Fred Harris
    replied
    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

    Leave a comment:


  • Fred Harris
    replied
    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.

    Leave a comment:


  • Warren Sugden
    replied
    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

    Leave a comment:


  • Fred Harris
    replied
    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

    Leave a comment:


  • Warren Sugden
    replied
    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

    Leave a comment:


  • Warren Sugden
    replied
    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

    Leave a comment:


  • Fred Harris
    replied
    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!

    Leave a comment:


  • Peter Lameijn
    replied
    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?

    Leave a comment:


  • Warren Sugden
    replied
    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

    Leave a comment:


  • Warren Sugden
    replied
    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

    Leave a comment:


  • Fred Harris
    replied
    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.

    Leave a comment:


  • Peter Lameijn
    replied
    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

    Leave a comment:


  • Warren Sugden
    replied
    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

    Leave a comment:


  • Peter Lameijn
    replied
    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

    Leave a comment:


  • Warren Sugden
    replied
    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

    Leave a comment:


  • Peter Lameijn
    replied
    Include this in your post:

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

    Leave a comment:


  • Warren Sugden
    replied
    Beginner in EnterMove.bas

    Peter

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

    Warren

    Leave a comment:


  • Peter Lameijn
    replied
    Just put the code between tags [ c o d e ] and [ / c o d e ] (tags without the spaces)

    Leave a comment:


  • Warren Sugden
    started a topic Beginner on EnterMov.BAS

    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.
Working...
X
😀
🥰
🤢
😎
😡
👍
👎