Announcement

Collapse
No announcement yet.

Writing to the Console Screen

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

  • Writing to the Console Screen

    I found the following functions in the WIN32API and would
    like help in understanding them.
    .
    DECLARE FUNCTION WriteConsole LIB "KERNEL32.DLL" ALIAS "WriteConsoleA" (BYVAL hConsoleOutput AS DWORD, lpBuffer AS ASCIIZ, BYVAL nNumberOfCharsToWrite AS LONG, lpNumberOfCharsWritten AS LONG, BYVAL lpReserved AS LONG) AS LONG
    DECLARE FUNCTION WriteConsoleInput LIB "KERNEL32.DLL" ALIAS "WriteConsoleInputA" (BYVAL hConsoleInput AS DWORD, lpBuffer AS INPUT_RECORD, BYVAL nLength AS DWORD, lpNumberOfEventsWritten AS LONG) AS LONG
    DECLARE FUNCTION WriteConsoleOutput LIB "KERNEL32.DLL" ALIAS "WriteConsoleOutputA" (BYVAL hConsoleOutput AS DWORD, BYVAL lpBuffer AS DWORD, BYVAL dwBufferSize AS DWORD, BYVAL dwBufferCoord AS DWORD, lpWriteRegion AS SMALL_RECT) AS LONG
    DECLARE FUNCTION WriteConsoleOutputAttribute LIB "KERNEL32.DLL" ALIAS "WriteConsoleOutputAttribute" (BYVAL hConsoleOutput AS DWORD, lpdwAttribute AS DWORD, BYVAL nLength AS LONG, BYVAL dwWriteCoord AS DWORD, lpNumberOfAttrsWritten AS LONG) AS LONG
    DECLARE FUNCTION WriteConsoleOutputCharacter LIB "KERNEL32.DLL" ALIAS "WriteConsoleOutputCharacterA" (BYVAL hConsoleOutput AS DWORD, szCharacter AS ASCIIZ, BYVAL nLength AS LONG, BYVAL dwWriteCoord AS DWORD, lpNumberOfCharsWritten AS LONG) AS LONG
    .
    Can I use these functions to display text to the console screen?
    If so, is there anything special I need to do to use tehm?
    Do these functions have draw backs or limitations I should know about?


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

  • #2
    I found this routine that works with PBCC20 but won't compile
    with the new version 2.1. Any suggestions on how to fix it?
    .
    Code:
    'Functions to use API screen print routines...
    'Save as "FPrint.inc" and use #INCLUDE "FPrint.inc" in main program...
    
    TYPE fpCOORD
        x AS INTEGER
        y AS INTEGER
    END TYPE
    
    DECLARE FUNCTION WriteConsoleOutputCharacter _
    LIB "KERNEL32.DLL" ALIAS "WriteConsoleOutputCharacterA"_
    (BYVAL hConsoleOutput AS LONG,_
    lpCharacter AS ASCIIZ,_
    BYVAL nLength AS LONG,_
    dwWriteCoord AS fpCOORD,_
    lpNumberOfCharsWritten AS LONG)_
    AS LONG
    DECLARE FUNCTION FillConsoleOutputAttribute _
    LIB "KERNEL32.DLL" ALIAS "FillConsoleOutputAttribute" _
    (BYVAL hConsoleOutput AS LONG,_
    BYVAL wAttribute AS LONG,_
    BYVAL nLength AS LONG,_
    dwWriteCoord AS fpCOORD, _
    lpNumberOfAttrsWritten AS LONG) _
    AS LONG
    
    UNION WINDOW_SIZE
       wDw AS DWORD
       wCo AS fpCOORD
    END UNION
    
    FUNCTION FPrint (BYVAL row&, BYVAL col&, BYVAL tAtrib&, BYVAL txt$) AS LONG
        LOCAL posn AS WINDOW_SIZE, _
        buff AS ASCIIZ * 81,_
        hand AS LONG,_
        tLen AS LONG, _
        nos AS LONG
        posn.wCo.x = col& - 1
        posn.wCo.y = row& - 1
        buff = txt$
        tLen = LEN(txt$)
        hand = GETSTDOUT
    
        IF tAtrib&=0 THEN tAtrib& = 15
        CALL WriteConsoleOutputCharacter (hand, buff, tLen, BYVAL posn.wDw, nos)
        CALL FillConsoleOutputAttribute (hand, tAtrib&, tLen, BYVAL posn.wDw, nos)
    END FUNCTION
    '------------------------------------------------------------------------
    ------------------


    [This message has been edited by Martin Francom (edited December 15, 2001).]

    Comment


    • #3
      This is very closely equivalent to:
      Code:
      LOCATE col&,row&
      COLOR fore&, bk&, LEN(txt$)
      PRINT txt$ ' or use STDOUT
      I hope that helps!

      PS: For API info, see WIN32.HLP or www.msdn.microsoft.com

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

      Comment


      • #4
        Gee Lance, Thanks... That was helpful. One learns something new
        every day!
        .
        But you didnot answer my question as to why the above routine will
        not compile using version 2.1 when it does compile with version 2.0
        .
        Seriously, I was using the above routine in a PBCC20 program because
        of problems that were occuring with the PB's PRINT statement. In the
        past it would cause very slow printing if in a standard screen size.
        Have the print problems of PBCC20 been solved with version 2.1 ??
        Does one still need to use non-standard screen sizes to get fast
        print speeds? (When using WIN95-98 OS)


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

        Comment


        • #5
          Marty --

          It's not PB/CC that has a problem with slow PRINTing on Windows 9x/ME systems, it's Windows itself. If you use the API to write your own functions that emulate PRINT they are unlikely to be faster. Unless you're a better programmer than PowerBASIC R&D.

          If you want to leave out some functionality -- scrolling, line wrapping, or any of the other "natural" features that PRINT provides -- then sure, you can probably create a faster function using the API.

          You're a Console Tools user, doesn't ConsolePoke (which does not scroll, etc.) do what you want?

          -- Eric


          ------------------
          Perfect Sync Development Tools
          Perfect Sync Web Site
          Contact Us: mailto:[email protected][email protected]</A>

          [This message has been edited by Eric Pearson (edited December 16, 2001).]
          "Not my circus, not my monkeys."

          Comment


          • #6
            But you did not answer my question as to why the above routine will
            not compile using version 2.1 when it does compile with version 2.0
            You asked for help in understanding them. I gave you an anology of the API's functionality.

            The following code, which is a <U>direct</U> copy of <U>your</U> code but with a PBMAIN wrapper and some minor whitespace formatting changes, compiles and runs perfectly for me under Win2K.

            What error does you code give you when you compile?
            Code:
            'Functions to use API screen print routines...
            TYPE fpCOORD
                x AS INTEGER
                y AS INTEGER
            END TYPE
             
            DECLARE FUNCTION WriteConsoleOutputCharacter _
              LIB "KERNEL32.DLL" ALIAS "WriteConsoleOutputCharacterA"_
              (BYVAL hConsoleOutput AS LONG,_
              lpCharacter AS ASCIIZ,_
              BYVAL nLength AS LONG,_
              dwWriteCoord AS fpCOORD,_
              lpNumberOfCharsWritten AS LONG)_
              AS LONG
             
            DECLARE FUNCTION FillConsoleOutputAttribute _
              LIB "KERNEL32.DLL" ALIAS "FillConsoleOutputAttribute" _
              (BYVAL hConsoleOutput AS LONG,_
              BYVAL wAttribute AS LONG,_
              BYVAL nLength AS LONG,_
              dwWriteCoord AS fpCOORD, _
              lpNumberOfAttrsWritten AS LONG) _
              AS LONG
             
            UNION WINDOW_SIZE
               wDw AS DWORD
               wCo AS fpCOORD
            END UNION
             
            FUNCTION FPrint (BYVAL row&, BYVAL col&, BYVAL tAtrib&, BYVAL txt$) AS LONG
                LOCAL posn AS WINDOW_SIZE, _
                buff AS ASCIIZ * 81,_
                hand AS LONG,_
                tLen AS LONG, _
                nos AS LONG
                posn.wCo.x = col& - 1
                posn.wCo.y = row& - 1
                buff = txt$
                tLen = LEN(txt$)
                hand = GETSTDOUT
             
                IF tAtrib&=0 THEN tAtrib& = 15
                CALL WriteConsoleOutputCharacter (hand, buff, tLen, BYVAL posn.wDw, nos)
                CALL FillConsoleOutputAttribute (hand, tAtrib&, tLen, BYVAL posn.wDw, nos)
            END FUNCTION
             
            FUNCTION PBMAIN
                fprint 10,20, 15 * 16 + 4, "Hello!"
                WAITKEY$
            END FUNCTION
            Have the print problems of PBCC20 been solved with version 2.1 ??
            Does one still need to use non-standard screen sizes to get fast
            print speeds? (When using WIN95-98 OS)
            As Eric noted, the problem is Windows, not PowerBASIC. As such PB/CC does not employ any of the "tricks" available to work around the 16-bit subsystem of Win9x's Console API's - doing so may cause some programmers more headache. Rather, it is the programmers responsibility to choose an appropriate method that is viable for their specific task. For example, I use PRINT exclusively, but use the PAGE/PCOPY technique so I can maintain a standard 80x25 console screen so as not to cause problems with SHELLed applications, etc.

            YMMV.


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

            Comment


            • #7

              I believe ReadConsoleOutput and WriteConsoleOutput is Better
              than using ReadConsoleOutputCharacter and WriteConsoleOutputCharacter
              for doing screen work. ReadConsoleOut and WriteConsoleOutput will
              also capture and display the attribute. By changeing the parameters
              they can block copy and display any area of the screen, from full
              Screen down to 1 character if needed.

              Semen has several examples which I've learned from and I have one
              that do the block copying of an area. A search on WriteConsoleOutput
              should find them.

              PCOPY is as good as any for storing screens, but ReadConsoleOutput
              can store gobs of them.

              I haven't seen any problems with those particular APIs, I use
              them all the time. I just finished adding a feature that writes
              premade screens or parts to DATA and I use WriteConsoleOutput
              to display it in PBCC programs and POKE$ in DOS programs.

              I'm sure if you learned how they worked, you would be happy with
              their results.


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


              [This message has been edited by Jerry Fielden (edited December 16, 2001).]

              Comment


              • #8
                Lance,
                ..I think even in WIN95/98 printing to a standard window 25x80 that
                the print speed can be significantly increased by using the WIN32API
                ConsoleOutput routines. Try the following program. I get 5 to 6
                seconds to print the screen using PB's Print command and less than
                1/18th of a second to print the same screen using WIN32API calls.
                Try the following code:
                .
                Code:
                #COMPILE EXE
                #REGISTER NONE
                #INCLUDE "WIN32API.INC"
                FUNCTION PBMAIN()
                t&=TIMER
                'PCOPY 1,2
                FOR row& = 1 TO 24
                  FOR col&= 1 TO 80
                    tmp$= CHR$(row& + 64)
                    'col = 2 * row - 1 :
                    tAtrib&=row& + 15
                    bg&= tAtrib&\16  : fg& = tAtrib& MOD 16
                    LOCATE row&, col& : COLOR fg&, bg&
                    PRINT Tmp$;
                  NEXT
                NEXT
                'PAGE 2,1
                t2&= TIMER-t&
                COLOR 0, 15
                LOCATE 25, 60: PRINT STR$(t2&);
                st$=WAITKEY$
                COLOR 0,0: CLS
                
                AllocConsole
                hOut& = GetStdHandle(%STD_OUTPUT_HANDLE)
                t&=TIMER
                FOR row& = 0 TO 23
                   FOR col&= 1 TO 80
                     tmp$= CHR$(row& + 64)
                     'col = 2 * row - 1
                     'col = 0 ':row =0
                     tAtrib&=row& + 15
                     WriteConsoleOutputCharacter hOut&, BYCOPY Tmp$, LEN(Tmp$), MAKDWD(col&, row&), 0
                     FillConsoleOutputAttribute hOut&, tAtrib&, LEN(Tmp$), MAKDWD(col&, row&), 0   
                   NEXT
                NEXT
                t2&=TIMER-t&
                COLOR 0,15
                LOCATE 25, 60: PRINT STR$(t2&);
                st$=WAITKEY$
                END FUNCTION
                .

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




                [This message has been edited by Martin Francom (edited December 16, 2001).]

                Comment


                • #9
                  Marty --

                  That's true, but like I said, your program doesn't do everything that PRINT does.

                  Remember, PowerBASIC R&D is very talented, but even they have to use the Windows API to print to the console. Unless Bob and Co. have been taking lessons from Harry Potter, that's how PRINT must work. In the end, IMO it is unlikely that anybody can use PowerBASIC to write a PRINT replacement that does everything PowerBASIC's own PRINT statement does, and is faster than PRINT.

                  -- Eric


                  ------------------
                  Perfect Sync Development Tools
                  Perfect Sync Web Site
                  Contact Us: mailto:[email protected][email protected]</A>



                  [This message has been edited by Eric Pearson (edited December 16, 2001).]
                  "Not my circus, not my monkeys."

                  Comment


                  • #10
                    Eric,
                    ..I certainly agree that the PB development team is very talented.
                    All I am saying is that for my particular need using the WIN32API
                    to print to the console s better suited to the needs of my particular
                    program. All I want to do is to write to the console screen as fast
                    as possible at the location I specify with the color attribute I
                    specify. And do it as simply as possible. I am sure the standard PB
                    Print statement is a better choice for other programs. But for what
                    I need the WIN32API is a better choice.
                    ..If this purpose I am now using the following FastPrint routine.
                    .
                    Code:
                    SUB FastPrint (BYVAL row&, BYVAL col&, BYVAL tAtrib&, BYVAL text$)
                      ' WIN32API ConsoleOutput starts at Row=0 Col=0
                      row&=row&-1 : col&=col&-1    
                      ' If tAtrib& set to < 0 then use current screen color attribute
                      IF tAtrib& < 0 THEN tAtrib& = SCREENATTR(row&, col&)
                      AllocConsole
                      hOut& = GetStdHandle(%STD_OUTPUT_HANDLE)
                      WriteConsoleOutputCharacter hOut&, BYCOPY Text$, LEN(Text$), MAKDWD(col&, row&), 0
                      FillConsoleOutputAttribute hOut&, tAtrib&, LEN(Text$), MAKDWD(col&, row&), 0
                    END SUB
                    ------------------

                    Comment


                    • #11
                      But Marty, you did not answer <U>my</U> question:

                      "What error does you code give you when you compile?"



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

                      Comment


                      • #12
                        Lance,
                        ..It was a typo error. But I am glad I asked the question, because
                        Jerry Fieldon pointed me in the right direction. And, I was able to
                        get the information needed to inprove the routine and condense it
                        to a 6 line routine.
                        ..So far it seems to be working for me. I will let you know if I
                        run into any problems with this method.

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

                        Comment


                        • #13
                          I'm posting this in both threads. When I worked for the dental software company a few years ago, we came up with the eleventh comandment:

                          Thou shalt not PRINT

                          This was true even in the DOS days. We found that DOS printing checked for a CTRL-C after EVERY character printed. Now PowerBasic developers have to be way better than that, I would hope. If I were coding PRINT, at the low level I would CTRL-C check at the begining of the operation.

                          PRINT does wonderful things as far as conversion, formating, line control, background filling, etc. But please remember that everything done for you has a cost to you, even if the price is free.

                          ------------------
                          ATB

                          Charles Kincaid

                          Comment


                          • #14
                            this may be of some help: http://www.powerbasic.com/support/pb...ad.php?t=22853

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

                            Comment


                            • #15

                              Martin, your FastPrint routine works great. I was wondering if
                              it would be safe to move

                              > AllocConsole
                              > hOut& = GetStdHandle(%STD_OUTPUT_HANDLE)

                              out of the subroutine -- just execute these two statements once
                              in the main module -- making hOut& a global variable or passing
                              it as a parameter. (Not being familiar with the API I don't know
                              just what these statements accomplish).

                              In running your sample code, I usually find that the time it takes
                              to run the "fastprint" part comes out negative! So it appears
                              you have invented a primitive time machine! It gets done before
                              it starts.




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

                              Comment


                              • #16
                                .

                                [This message has been edited by Mark Hunter (edited September 30, 2006).]
                                Politically incorrect signatures about immigration patriots are forbidden. Searching “immigration patriots” is forbidden. Thinking about searching ... well, don’t even think about it.

                                Comment


                                • #17
                                  Actually even conagent is able to work with crazy speed and to update a screen hundreds times per second.
                                  There is one magic word, which should remember former DOS developers - "buffer".
                                  How typically PB/CC (DOS) programs works ?
                                  Many Prints to prepare a screen, then Inkey.
                                  Instead of separate calls of API functions (PB/CC Print) it's necessary to store data in memory buffer and to output whole screen (WriteConsoleOutput) before ("inside") Inkey$.
                                  Remember the speed of PB/CC 2.0 PCopy. Exactly with such speed works described method.


                                  ------------------
                                  E-MAIL: [email protected]

                                  Comment


                                  • #18
                                    David,
                                    ..Time machine..hummmm. Try changing the timer to milliseconds.
                                    .
                                    ..I found that since a PBCC program is running in a console window
                                    already, you do not need to use the 'AllocConsole' command. I also
                                    have replaced 'hOut& = GetStdHandle(%STD_OUTPUT_HANDLE)' with PB's
                                    equivalent 'hOut& = GETSTDOUT'
                                    ..So now the routine is simply:
                                    .
                                    Code:
                                    SUB FastPrint (BYVAL row&, BYVAL col&, BYVAL tAtrib&, BYVAL text$)
                                      ' WIN32API ConsoleOutput starts at Row=0 Col=0
                                      row&=row&-1 : col&=col&-1
                                      ' If tAtrib& set to < 0 then use current screen color attribute
                                      IF tAtrib& < 0 THEN tAtrib& = SCREENATTR(row&, col&)
                                      hOut& = GETSTDOUT
                                      WriteConsoleOutputCharacter hOut&, BYCOPY Text$, LEN(Text$), MAKDWD(col&, row&), 0
                                      FillConsoleOutputAttribute hOut&, tAtrib&, LEN(Text$), MAKDWD(col&, row&), 0
                                    END SUB


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

                                    Comment


                                    • #19
                                      Originally posted by David Schmidt:
                                      In running your sample code, I usually find that the time it takes
                                      to run the "fastprint" part comes out negative! So it appears
                                      you have invented a primitive time machine! It gets done before
                                      it starts.
                                      What were you using to test this? TIMER? If so, then chances are the RTC was part way through a value update when the time was read, resulting in a slightly incorrect value when compared to the previous (or next) reading. This behavior can be seen in plain DOS apps too. Basically, the RTC would need to offer some form of "synchronization" for the read operation to be perfect 100% of the time. TIMER is more useful for approximate timing operations.

                                      For this sort of adhoc benchmarking, using GetTickCount() or the QueryPerformanceCounter()/QueryPerformanceFrequency() API's offer more accurate timing results especially for very short periods of time.


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

                                      Comment


                                      • #20
                                        Martin, is there any reason why hOut& = GETSTDOUT needs to be done every call? Why not make hOut& a global & set it up at program start? Or does Windows change it whenever it feels like it?


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

                                        Comment

                                        Working...
                                        X