Announcement

Collapse
No announcement yet.

Strange Behaviour using wvsprintf

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

  • Strange Behaviour using wvsprintf

    I´ve decided to review Petzold´s book (5th Edition) to get deeper
    into the inner workings of PowerBASIC and the Windows API by
    understanding every line in the examples.
    I´m right at the second example (shown below) of the book and it
    has proven very rewarding and certainly very tough for me because
    I don´t know a bit of C++ programming.
    Nevertheles, I´m trying to make every example work like C++ but
    using PB and whatever the Windows API can offer.

    I learned that there is a va_list array used in C to pass data to
    some printf functions. I found a way around it in PB using the
    wsprintf function provided in the Win32API.INC file. But it didn´t
    resemble quite well the workings in the example.
    I then found that there is a function (wvsprintf) not declared in
    the Win32API.INC file that accepts a va_list array instead of
    optional parameters and I decided to give a try. It worked fine.
    Or so it seems.

    After I ran the PB code and tweaked a little I discovered that
    for some reason the program didn't run (does nothing) when I
    changed the scope of one variable from static to local. It
    concerns me because maybe there is an improper handling of memory
    or arrays that may crash a bigger program.

    Any ideas of what is going wrong?

    The C code is:

    Code:
    SCRNSIZE.C
    
    /*-----------------------------------------------------
       SCRNSIZE.C -- Displays screen size in a message box
                     (c) Charles Petzold, 1998
      -----------------------------------------------------*/
    
    #include <windows.h>
    #include <tchar.h>     
    #include <stdio.h>     
    
    int CDECL MessageBoxPrintf (TCHAR * szCaption, TCHAR * szFormat, ...)
    {
         TCHAR   szBuffer [1024] ;
         va_list pArgList ;
    
              // The va_start macro (defined in STDARG.H) is usually equivalent to:
              // pArgList = (char *) &szFormat + sizeof (szFormat) ;
    
         va_start (pArgList, szFormat) ;
    
              // The last argument to wvsprintf points to the arguments
    
         _vsntprintf (szBuffer, sizeof (szBuffer) / sizeof (TCHAR), 
                      szFormat, pArgList) ;
    
              // The va_end macro just zeroes out pArgList for no good reason
    
         va_end (pArgList) ;
    
         return MessageBox (NULL, szBuffer, szCaption, 0) ;
    }
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        PSTR szCmdLine, int iCmdShow) 
    {
         int cxScreen, cyScreen ;
    
         cxScreen = GetSystemMetrics (SM_CXSCREEN) ;
         cyScreen = GetSystemMetrics (SM_CYSCREEN) ;
         MessageBoxPrintf (TEXT ("ScrnSize"), 
                           TEXT ("The screen is %i pixels wide by %i pixels high."),
                           cxScreen, cyScreen) ;
         return 0 ;
    }
    The Powerbasic code I´m using to try to resemble the above example:

    Code:
    #DIM ALL
    
    %SM_CXSCREEN = 0
    %SM_CYSCREEN = 1
    %MB_OK       = &H00000000&
    
    DECLARE FUNCTION GetSystemMetrics LIB "USER32.DLL" ALIAS "GetSystemMetrics" _
                     (BYVAL nIndex AS LONG) AS LONG
    
    
    ' New function declared:
    
    DECLARE FUNCTION wvsprintf CDECL LIB "USER32.DLL" ALIAS "wvsprintfA" _
                     (lpOutput AS ASCIIZ, lpFormat AS ASCIIZ, Arguments AS ANY) AS LONG
    
    
    ' From the Win32 Help:
    ' Arguments points to an array of 32-bit values that
    ' are used as insert values in the formatted message.
                                                                                                                      
    
    FUNCTION PBMAIN
        
        STATIC va_list() AS DWORD
        DIM    va_list(2)
        STATIC pArgument AS DWORD PTR
        STATIC cxScreen AS LONG
        STATIC cyScreen AS LONG
        STATIC lpOutput AS ASCIIZ * 100
        LOCAL  lpFormat AS ASCIIZ * 100  :' Changing the scope to STATIC makes the program not to run
        STATIC Texto AS STRING
    
    
         cxScreen = GetSystemMetrics (%SM_CXSCREEN)
         cyScreen = GetSystemMetrics (%SM_CYSCREEN)
        
        va_list(1)= cxScreen
        va_list(2)= cyScreen
    
        pArgument=VARPTR(va_list(1))
    
        lpFormat$="The screen is %lu pixels wide by %lu pixels high."
        
        wvsprintf (lpOutput , BYREF lpFormat, BYVAL pArgument )
        
        Texto$="Passing Arrays"
        MSGBOX lpOutput$,%MB_OK,Texto$
            
    END FUNCTION

    ------------------




    [This message has been edited by Pedro Ramirez (edited April 11, 2004).]

  • #2
    Code:
    LOCAL  lpFormat AS ASCIIZ * 100  :' Changing the scope to STATIC makes the program not to run
    ..
    lpFormat$="The screen is %lu pixels wide by %lu pixels high."
    Compiler should not be recognizing lpformat (ASCIIZ) as lpformat$ (dynamic string). Best guess is you are passing VARPTR of a null lpformat string, which wsprintf does not like.

    #DIM ALL should prevent.

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

    Comment


    • #3
      Nope!

      #DIM ALL is already there (first line).
      Nevertheles I erased the $ sign from lpFormat and Texto$ but problem
      persist.

      ------------------

      Comment


      • #4
        I'm not sure if you've solved your problem, but it pays to remember that DIM VA_LIST(2) will yield 3 elements: 0, 1, 2. In the code above, only the 2nd and 3rd elements are initialized with valid data.

        ------------------
        Lance
        PowerBASIC Support
        mailto:[email protected][email protected]</A>
        Lance
        mailto:[email protected]

        Comment


        • #5
          wvsprintf uses the default STDCALL calling convention.
          wsprintf uses the CDECL calling convention.

          ------------------
          Tom Hanlin
          PowerBASIC Staff

          Comment


          • #6
            My version of ScreenSize.C

            Code:
            '-----------------------------------------------------
            ' SCRNSIZE.C -- Displays screen size in a message box
            ' (c) Charles Petzold, 1998
            ' Chapter 2
            '-----------------------------------------------------*/
            ' JK-IDE
            ' PowerBASIC 10.3
            ' José Roca Headers III
            '-----------------------------------------------------
            
            #COMPILE EXE = "ScreenSize.exe"
            #DIM ALL
            #INCLUDE "windows.inc"
            
            %UNICODE = 1
            
            #If %Def(%UNICODE)
            Macro TCHAR = WStringz
            #Else
            Macro TCHAR = Asciiz
            #EndIf
            
            
            '***********************************************************************************************
            
            FUNCTION PBMAIN () AS LONG
            '***********************************************************************************************
            ' main
            '***********************************************************************************************
            
              DIM va_list() AS DWORD
              DIM va_list(2)
              DIM pArgument AS DWORD PTR
              DIM cxScreen AS LONG, cyScreen AS LONG
            
                cxScreen = GetSystemMetrics (%SM_CXSCREEN)
                cyScreen = GetSystemMetrics (%SM_CYSCREEN)
            
                va_list(1)= cxScreen
                va_list(2)= cyScreen
            
                pArgument = VARPTR(va_list(1))
            
                MessageBoxPrintf ("ScrnSize", "The screen is %i pixels wide by %i pixels high.", pArgument)
            
            END FUNCTION
            
            '-----------------------------------------------------
            
            Function MessageBoxPrintf(szCaption AS TCHAR, szFormat AS TCHAR, ByVAL pArgList as LONG PTR) AS INTEGER
            
              Local szBuffer AS TCHAR * 1024
            
            #If %Def(%UNICODE)
              wvsprintfW (szBuffer, szformat, byval pArgList)
              MessageBoxPrintf = MessageBoxW(%NULL, szBuffer, szCaption, 0)
            #ELSE
              wvsprintfA (szBuffer, szformat, byval pArgList)
              MessageBoxPrintf = MessageBox(%NULL, szBuffer, szCaption, 0)
            #ENDIF
            
            END FUNCTION

            Comment


            • #7
              Enquiring minds want to know:
              What is the purpose of declaring variables in PBMain() as STATIC. You can't leave and re-enter the function.

              Come to that, what's wrong with:
              Code:
              #COMPILE EXE = "ScrenSize.exe"
              #DIM ALL
              %UNICODE = 1
              #INCLUDE "windows.inc"
              FUNCTION PBMAIN() AS LONG
                LOCAL cxScreen AS LONG, cyScreen AS LONG
                cxScreen = GetSystemMetrics (%SM_CXSCREEN)
                cyScreen = GetSystemMetrics (%SM_CYSCREEN)
                ? USING$("The screen is # pixels wide by # pixels high.",cxScreen,cyScreen),,"Screen Size"
              END FUNCTION

              Comment


              • #8
                [QUOTE=Stuart McLachlan;n810859]Enquiring minds want to know:
                What is the purpose of declaring variables in PBMain() as STATIC. You can't leave and re-enter the function.

                No idea. More experience users may be able to answer.

                Edit: Works with straigh DIM, so I've updated to code. Clearly STATIC is not neccassry and an error on my part.

                Comment


                • #9
                  Never hurts to know the API method, but since PBWin 8 (2007) we've had DESKTOP GET SIZE and DESKTOP GET CLIENT (the later leaves out system tray size).

                  Cheers,
                  Dale

                  Comment


                  • #10
                    My updated version of ScreenSize.C

                    Found out that #If %Def(%UNICODE) in my previous version works differently
                    than I coded for, and the previous version only compiled for UNICODE

                    Now can compile for both UNICODE and ASCII strings

                    Code:
                    '******************************************************************************
                    '
                    ' DESCRIPTION: Displays screen size in a message box.
                    '              Translation/adaptation of the ScrnSize.C program
                    '              (c) Charles Petzold Programming Windows 5th Ed 1998 - Chapter 2
                    '
                    ' Editor: JK-IDE
                    '         José Roca Headers III
                    '         PowerBASIC PBWin 10.03
                    '******************************************************************************
                    
                    #COMPILE EXE = "ScreenSize.exe"
                    #DIM ALL
                    #INCLUDE "windows.inc"
                    
                    %UNICODE = 1     'comment out for ASCII
                    
                    #IF %DEF(%UNICODE)
                      %ISUNICODE = 1
                    #ELSE
                      %ISUNICODE = 0
                    #ENDIF
                    
                    #If %ISUNICODE
                      Macro TCHAR = WStringz
                    #Else
                      Macro TCHAR = Asciiz
                    #EndIf
                    
                    '***********************************************************************************************
                    
                    FUNCTION PBMAIN () AS LONG
                    '***********************************************************************************************
                    ' main
                    '***********************************************************************************************
                    
                      DIM va_list() AS DWORD
                      DIM va_list(2)
                      DIM pArgument AS LONG PTR
                    
                        va_list(1) = GetSystemMetrics (%SM_CXSCREEN)
                        va_list(2) = GetSystemMetrics (%SM_CYSCREEN)
                    
                        pArgument = VARPTR(va_list(1))
                    
                        MessageBoxPrintf ("ScrnSize", "The screen is %i pixels wide by %i pixels high.", pArgument)
                    
                    END FUNCTION
                    
                    '***********************************************************************************************
                    
                    Function MessageBoxPrintf(stCaption AS TCHAR, stFormat AS TCHAR, ByVAL pArgList as LONG PTR) AS INTEGER
                    
                      Local stBuffer AS TCHAR * 1024
                    
                    #If %ISUNICODE
                      wvsprintfW (stBuffer, stformat, byval pArgList)
                      MessageBoxPrintf = MessageBoxW(%NULL, stBuffer, stCaption, 0)
                    #ELSE
                      wvsprintfA (stBuffer, stformat, byval pArgList)
                      MessageBoxPrintf = MessageBox(%NULL, stBuffer, stCaption, 0)
                    #ENDIF
                    
                    END FUNCTION

                    Comment


                    • #11
                      Pedro,

                      Jose Roca translations:
                      I could not find an example of wvsprintf.
                      No idea if same revision of book or if he may have skipped it.
                      There are over a hundred subfolders with a PowerBASIC example in each!
                      Studying these would be way easier, but appreciate what you are doing.
                      https://forum.powerbasic.com/forum/j...old-s-examples

                      Also, don't know if you joined Jose Roca forums.
                      Here is just 1-link about C/C++ with Visual BASIC and PowerBASIC.
                      http://www.jose.it-berater.org/smffo...hp?board=380.0
                      Last edited by Mike Doty; 28 Sep 2021, 07:28 PM.

                      Comment


                      • #12
                        I could not find an example of wvsprintf.
                        I think I know why.

                        When I consulted the Microsoft documentation at https://docs.microsoft.com/en-us/win...ser-wvsprintfa my sight was immediately drawn to the box with the boldface type which starts out "Warning Do Not Use. "

                        I'll bet those who might have created examples - for example, our own Mr. Roca - got scared off, too.

                        On a very much related track, what are you trying to accomplish? Maybe there is "a better way" using the tools provided by PowerBasic rather than using some relatively obscure Windows function.

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

                        Comment


                        • #13
                          could not find an example of wvsprintf
                          This thread is from 2004 by Pedro Ramirez that wanted to convert C/CC++ to PowerBASIC.
                          There is no mention of the Jose Roca translations (see post #11.)

                          On a very much related track, what are you trying to accomplish? Maybe there is "a better way" using the tools provided by PowerBasic rather than using some relatively obscure Windows function."
                          See post #1 where Pedro wanted to learn every line of code.

                          Comment


                          • #14
                            I think I shall pass on expounding further due to thread age and the fact Mr. Ramirez' last activity was October 2015.

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

                            Comment

                            Working...
                            X