CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 16
  1. #1
    Join Date
    Jan 2009
    Location
    England
    Posts
    57

    [RESOLVED] Issues copying and pasting text into a console screen buffer

    I have spent 3 days trying to get two new functions - GetText() and PutText() to function correctly with no success. Would someone be kind enough to look over my code and see why they do not work. I must have missed something?

    Code:
    #include <windows.h>
    #include <iostream>
    
    
    using namespace std;
    
    
    int GetText(int left, int top, int right, int bottom, char *buf);
    int PutText(int left, int top, int right, int bottom, char *buf);
    
    
    int main()
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    
    
        int width = csbi.dwSize.X;
        int height = csbi.dwSize.Y;
    
    
        char *pchScreenBuffer;
    
    
        // Dynamically allocate a screen buffer - Used by GetText() and PutText()
        // We need width * height * 2, as we need space for the character and
        // it's attribute.
        if(!(pchScreenBuffer = new char[width * height * 2])) {
            MessageBox(NULL, "Error creating a dynamic screen buffer.",
                       "Error", MB_ICONERROR | MB_OK | MB_TASKMODAL);
            exit(1);
        }
    
    
        // Put some text on the screen to copy
        std::cout << "Hello, this is some text that I am going to copy"
                  << " \nand then place back on the screen.  Will need to"
                  << " \ntest the code to make sure it is working as I"
                  << " \nhave designed it.  So far I have not managed to"
                  << " \nget these two functions to work correctly?" << std::endl;
    
    
        // Let's test the functions
        GetText(0, 0, 5, 3, pchScreenBuffer);
        PutText(0, 0, 5, 3, pchScreenBuffer);
    
    
        delete[] pchScreenBuffer;  // Free dynamic memory
    
    
        return 0;
    }
    
    
    //-----------------------------------------------------------------------------
    // Function/Method: GetText(int left, int top, int right, int bottom, char *buf)
    // Description:     Copies a specified portion of the screen and saves it to a
    //                  screen buffer.
    // Return:          If GetText() is successful then EXIT_SUCCESS is returned,
    //                  otherwise EXIT_FAILURE is returned.
    //-----------------------------------------------------------------------------
    int GetText(int left, int top, int right, int bottom, char *buf)
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    
    
        int width = csbi.dwSize.X;
        int height = csbi.dwSize.Y;
    
    
        SMALL_RECT sRect;  // Structure to hold area to copy from
    
    
        // Create a local buffer that is big enough to hold each character and it's
        // attribute from every cell on the screen.
        CHAR_INFO lpBuffer[width][height];
    
    
        // Screen buffer is 0 based in a console.  If we don't error check for
        // this, then we end up copying +1 row and column than we require.
        //left = (left > 0 ? left : left - 1);
        //top = (top > 0 ? top : top - 1);
    
    
        // Initialize structure with requested area to copy
        sRect = (SMALL_RECT) { left, top, right, bottom };
    
    
        // Now read character and colour attribute data from a rectangular block of
        // character cells in a console screen buffer. The ReadConsoleOutput()
        // function writes the data to a rectangular block at a specified location
        // in the destination buffer.
        if(!ReadConsoleOutput(
           GetStdHandle(STD_OUTPUT_HANDLE),    // handle to a console screen buffer
           (PCHAR_INFO) lpBuffer,              // address of buffer that receives data
           (COORD) {width, height},            // column-row size of destination buffer
           (COORD) {0, 0},                     // upper-left cell to write to
           &sRect))                            // address of rectangle to read from
        {
            MessageBox(NULL, "Error reading from console screen buffer.",
                       "Error", MB_ICONERROR | MB_OK | MB_TASKMODAL);
    
    
            return EXIT_FAILURE;
        }
    
    
        lstrcpy(buf, "");  // Initialize screen buffer
    
    
        // Copy local lpBuffer data into buf
        int index = 0;
    
    
        for(int col = 0; col <= bottom - top; col++) {
            for(int row = 0; row <= right - left; row++) {
                buf[index] = lpBuffer[col][row].Char.AsciiChar;
                buf[index+1] = lpBuffer[col][row].Attributes;
                index++;
            }
        }
    
    
        return EXIT_SUCCESS;
    }
    
    
    //-----------------------------------------------------------------------------
    // Function/Method:  PutText(int left, int top, int right, int bottom, char *buf)
    // Description:      Pastes previously saved screen data back to the screen
    // Return:           If PutText() is successful then EXIT_SUCCESS is returned,
    //                   otherwise EXIT_FAILURE is returned.
    //-----------------------------------------------------------------------------
    int PutText(int left, int top, int right, int bottom, char *buf)
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    
    
        int width = csbi.dwSize.X;
        int height = csbi.dwSize.Y;
    
    
        SMALL_RECT sRect;  // Structure to hold area to paste back to
    
    
        // Create a local buffer that is big enough to hold each character and it's
        // attribute from every cell on the screen.
        CHAR_INFO lpBuffer[width][height];
        memset(lpBuffer, 0, sizeof(lpBuffer));  // Initialize lpBuffer
    
    
        // Screen buffer is 0 based in a console.  If we don't error check for
        // this, then we end up copying +1 row and column than we require.
        //left = (left > 0 ? left : left - 1);
        //top = (top > 0 ? top : top - 1);
    
    
        // Initialize structure with requested area we will paste back to
        sRect = (SMALL_RECT) { left, top, right, bottom };
    
    
        // Copy previously saved screen data into local buffer lpBuffer
        int index = 0;
    
    
        for(int col = 0; col <= bottom - top; col++) {
            for(int row = 0; row <= right - left; row++) {
                lpBuffer[col][row].Char.AsciiChar = buf[index];
                lpBuffer[col][row].Attributes = buf[index+1];
                index++;
            }
        }
    
    
        // Now write the screen data back to the screen
        if(!WriteConsoleOutput(
           GetStdHandle(STD_OUTPUT_HANDLE),     // handle to a console screen buffer
           (CHAR_INFO *) lpBuffer,              // contains the data to be written
           (COORD) {width, height},             // column-row size of source buffer
           (COORD) {0, 0},                      // upper-left cell to write from
           &sRect))                             // address of rectangle to write to
        {
            MessageBox(NULL, "Error writing to console screen buffer.",
                       "Error", MB_ICONERROR|MB_OK|MB_TASKMODAL);
    
    
            return EXIT_FAILURE;
        }
    
    
        return EXIT_SUCCESS;
    }
    What the mind can conceive it can achieve.

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: Issues copying and pasting text into a console screen buffer

    Define "do not work".
    Victor Nijegorodov

  3. #3
    Join Date
    Jan 2009
    Location
    England
    Posts
    57

    Re: Issues copying and pasting text into a console screen buffer

    I am getting Hello placed back on the screen but in different colours and a background colour with that text. GetText() is copying the screen and does not produce any errors. The same is for PutText(), no errors but as I said not all the text I copied is displayed and what is placed back is as I described?

    I am no expert, and would be grateful for an expert to tell me what I have missed or done wrong?
    What the mind can conceive it can achieve.

  4. #4
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: Issues copying and pasting text into a console screen buffer

    Quote Originally Posted by Gerald Bates View Post
    Code:
        int width = csbi.dwSize.X;
        int height = csbi.dwSize.Y;
       // Create a local buffer that is big enough to hold each character and it's
        // attribute from every cell on the screen.
        CHAR_INFO lpBuffer[width][height];
    What could it mean?
    What compiler are you using?
    Victor Nijegorodov

  5. #5
    Join Date
    Jan 2009
    Location
    England
    Posts
    57

    Re: Issues copying and pasting text into a console screen buffer

    I am using Codeblocks 13.12 and GNU GCC compiler.
    What the mind can conceive it can achieve.

  6. #6
    Join Date
    Jan 2009
    Location
    England
    Posts
    57

    Re: Issues copying and pasting text into a console screen buffer

    CHAR_INFO lpBuffer[width][height];

    I take this to be a local variable that creates an array of structures of type CHAR_INFO. So each lpBuffer[x][x] location stores the character and it's attribute? I am staring at this line trying to work out what I have done wrong?
    What the mind can conceive it can achieve.

  7. #7
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Issues copying and pasting text into a console screen buffer

    Quote Originally Posted by Gerald Bates View Post
    I am staring at this line trying to work out what I have done wrong?
    Rather than staring at the line of code, step through the code in a debugger and see the actual values. When you debug, does GetText() put the data in the buffer? Will PutText() write to the screen? If not, can you hardcode a string in PutText() to get it to write to a screen. Spending time debugging (or learning to debug) is going to help you solve this problem the quickest.

  8. #8
    Join Date
    Jan 2009
    Location
    England
    Posts
    57

    Re: Issues copying and pasting text into a console screen buffer

    Indeed, I could not agree more. I have very little experience of debugging but I am going to give it a go. Have made significant changes to the code as I think I understand what VictorN was hinting at. Will post my changes as I think I have nearly worked out the issues.
    What the mind can conceive it can achieve.

  9. #9
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Issues copying and pasting text into a console screen buffer

    Code:
    buf[index] = lpBuffer[col][row].Char.AsciiChar;
    buf[index+1] = lpBuffer[col][row].Attributes;
    index++;
    Code:
    lpBuffer[col][row].Char.AsciiChar = buf[index];
    lpBuffer[col][row].Attributes = buf[index+1];
    index++;
    Are you sure index should be just incremented by 1 here and not 2?
    Last edited by 2kaud; March 13th, 2014 at 03:50 PM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  10. #10
    Join Date
    Jan 2009
    Location
    England
    Posts
    57

    Re: Issues copying and pasting text into a console screen buffer

    I have been working on this code since 9 am this morning and run it through the debugger many times. It has dawned on me that memory is contiguous and that's how the computer views it. This had led me to stop thinking in a 2 dimensional fashion and thus I have improved the code and got to the stage where my code now runs almost properly.

    The only issue I have at present is that I am debugging my new code using GDB, and I am unable to see the screen buffer array I pass into GetText(). I get an error - Not available in current context! I now know that I am NOT copying correctly as I am pasting blank spaces back to the screen. This appears to be a pointer issue.

    The debugger indeed proved that I was stomping all over the attribute value in my array so I have increment my index variable by 2 in both functions. So close in getting this working.
    What the mind can conceive it can achieve.

  11. #11
    Join Date
    Jan 2009
    Location
    England
    Posts
    57

    Re: Issues copying and pasting text into a console screen buffer

    After making changes, I now get a segmentation fault reported from the debugger. I have nailed this down to the char *buf[] within a loop in GetText(). I have miss-understood how to increment the pointer. When I change the code I get a cannot convert from char** to char*. After looking this up, I am told to use a string instead of char * and the article further talks about c_str(). I know nothing about this and do not understand how it applies to my code?

    I have noticed that I only get one character - "H" from the word Hello, I never copy anything else into char *buf[] that I pass into GetText(). Is there a way to increment through the array CHAR_INFO *buf[] ?

    Could someone point me in the right direction as to why I get a segmentation fault with this code? I have highlighted the line that causes the issue?

    Code:
    #include <windows.h>
    #include <iostream>
    
    
    using namespace std;
    
    
    int GetText(int left, int top, int right, int bottom, CHAR_INFO *buf[]);
    int PutText(int left, int top, int right, int bottom, CHAR_INFO *buf[]);
    
    
    int main()
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    
    
        int width = csbi.dwSize.X;
        int height = csbi.dwSize.Y;
    
    
        CHAR_INFO *pchScreenBuffer[width * height * 2];
    
    
        // Put some text on the screen to copy
        std::cout << "Hello, this is some text that I am going to copy"
                  << " \nand then place back on the screen.  Will need to"
                  << " \ntest the code to make sure it is working as I"
                  << " \nhave designed it.  So far I have not managed to"
                  << " \nget these two functions to work correctly?"
                  << std::endl;
    
    
        // Let's test the functions
        GetText(0, 0, 4, 2, pchScreenBuffer);
        //PutText(0, 0, 4, 2, pchScreenBuffer);
    
    
        return 0;
    }
    
    
    //-----------------------------------------------------------------------------
    // Function/Method: GetText(int left, int top, int right, int bottom, 
    //                          CHAR_INFO *buf[])
    // Description:     Copies a specified portion of the screen and saves it to a
    //                  screen buffer.
    // Return:          If GetText() is successful then EXIT_SUCCESS is returned,
    //                  otherwise EXIT_FAILURE is returned.
    //-----------------------------------------------------------------------------
    int GetText(int left, int top, int right, int bottom, CHAR_INFO *buf[])
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    
    
        int width = csbi.dwSize.X;
        int height = csbi.dwSize.Y;
    
    
        SMALL_RECT sRect;  // Structure to hold screen area to copy from
    
    
        // Initialize structure with requested screen area to copy from
        sRect = (SMALL_RECT) { left, top, right, bottom };
    
    
        // Create a local buffer that is big enough to hold each character and it's
        // attribute from every cell on the screen.
        CHAR_INFO lpBuffer[width * height * 2];
        memset(lpBuffer, 0, sizeof(lpBuffer));  // Initialize lpBuffer
    
    
        // ReadConsoleOutput() needs to know the column-row size of destination
        // buffer - lpBuffer.
        COORD lpBufferSize;
        lpBufferSize.X = csbi.dwSize.X;  // Column - horizontal coordinate
        lpBufferSize.Y = csbi.dwSize.Y;  // Row - vertical coordinate
    
    
        // Now read character and colour attribute data from a rectangular block of
        // character cells in a console screen buffer. The ReadConsoleOutput()
        // function writes the data to a rectangular block at a specified location
        // in the destination buffer.
        if(!ReadConsoleOutput(
           GetStdHandle(STD_OUTPUT_HANDLE),  // handle to a console screen buffer
           (PCHAR_INFO) lpBuffer,            // address of buffer that receives data
           (COORD) lpBufferSize,             // column-row size of destination buffer
           (COORD) {0, 0},                   // upper-left cell to write to
           &sRect))                          // address of rectangle to read from
        {
            MessageBox(NULL, "Error reading from console screen buffer.",
                       "Error", MB_ICONERROR | MB_OK | MB_TASKMODAL);
    
    
            return EXIT_FAILURE;
        }
    
    
        //lstrcpy(buf, "");  // Initialize screen buffer
    
    
        // Copy local lpBuffer data into buf as we will loose lpBuffer
        // screen data when GetText() finishes.
        for(int index = 0; index <= (width * height * 2); index += 2) {
            buf[index]->Char.AsciiChar = lpBuffer[index].Char.AsciiChar;
            buf[++index]->Attributes = lpBuffer[++index].Attributes;
        }
    
    
        return EXIT_SUCCESS;
    }
    What the mind can conceive it can achieve.

  12. #12
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Issues copying and pasting text into a console screen buffer

    Code:
    buf[++index]->Attributes = lpBuffer[++index].Attributes;
    try
    Code:
    buf[index+1]->Attributes = lpBuffer[index+1].Attributes;
    You are incrementing index as part of the assignment and also again as part of the loop.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  13. #13
    Join Date
    Jan 2009
    Location
    England
    Posts
    57

    Re: Issues copying and pasting text into a console screen buffer

    Thanks 2kaud, I have corrected the code but still getting a segmentation fault. Will run this through the debugger and see what is going on again!
    What the mind can conceive it can achieve.

  14. #14
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Issues copying and pasting text into a console screen buffer

    Code:
    for(int index = 0; index <= (width * height * 2); index += 2) {
    Are you sure this should be <= and not just < ?

    PS

    as buf is now of type CHAR_INFO, you don't need the *2 when allocating memory. Also you don't need index+1 in the loop. I haven't realised you had changed the type of the array in my earlier posting.

    Code:
    CHAR_INFO *pchScreenBuffer[width * height];
    Code:
    CHAR_INFO lpBuffer[width * height];
    Code:
    for(int index = 0; index < (width * height); index++) {
            buf[index]->Char.AsciiChar = lpBuffer[index].Char.AsciiChar;
            buf[index]->Attributes = lpBuffer[index].Attributes;
        }
    you only need to increment index by 1 as buf and lpBuffer are type CHAR_INFO.

    you could replace the for loop with
    Code:
    memcpy(buf, lpBuffer, sizeof(CHAR_INFO) * width * height);
    Last edited by 2kaud; March 15th, 2014 at 08:02 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  15. #15
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Issues copying and pasting text into a console screen buffer

    Why are you copying the buffer in GetText? Why not just read the data into the buffer address provided as the last argument to the GetText() function? Something like this
    Code:
    #include <windows.h>
    #include <iostream>
    using namespace std;
    
    int GetText(int left, int top, int right, int bottom, CHAR_INFO *const buf);
    int PutText(int left, int top, int right, int bottom, const CHAR_INFO *const buf);
    
    int main()
    {
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    
    	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    
    CHAR_INFO	*pchScreenBuffer = new CHAR_INFO[csbi.dwSize.X * csbi.dwSize.Y];
    
        // Put some text on the screen to copy
        std::cout << "Hello, this is some text that I am going to copy"
                  << " \nand then place back on the screen.  Will need to"
                  << " \ntest the code to make sure it is working as I"
                  << " \nhave designed it.  So far I have not managed to"
                  << " \nget these two functions to work correctly?"
                  << std::endl;
    
    	// Let's test the functions
    	GetText(0, 0, 4, 2, pchScreenBuffer);
    	PutText(10, 20, 14, 22, pchScreenBuffer);
    
    	delete [] pchScreenBuffer;
    
    	return 0;
    }
    
    int GetText(int left, int top, int right, int bottom, CHAR_INFO *const buf)
    {
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    
    	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    
    SMALL_RECT	sRect = { left, top, right, bottom };  // Structure to hold screen area to copy from
    
    const COORD	lpBufferSize = {csbi.dwSize.X, csbi.dwSize.Y};
    const COORD	readPos = {0, 0};
    
        if (!ReadConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE), buf, lpBufferSize, readPos, &sRect))                          // address of rectangle to read from
        {
            MessageBox(NULL, "Error reading from console screen buffer.", "Error", MB_ICONERROR | MB_OK | MB_TASKMODAL);
            return EXIT_FAILURE;
        }
    
        return EXIT_SUCCESS;
    }
    
    int PutText(int left, int top, int right, int bottom, const CHAR_INFO *const buf)
    {
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    
    	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    
    SMALL_RECT	sRect = { left, top, right, bottom };  // Structure to hold screen area to copy from
    
    const COORD	lpBufferSize = {csbi.dwSize.X, csbi.dwSize.Y};
    const COORD	writePos = {0, 0};
    
        if (!WriteConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE), buf, lpBufferSize, writePos, &sRect))                          // address of rectangle to read from
        {
            MessageBox(NULL, "Error writing to console screen buffer.", "Error", MB_ICONERROR | MB_OK | MB_TASKMODAL);
            return EXIT_FAILURE;
        }
    
        return EXIT_SUCCESS;
    }
    Last edited by 2kaud; March 15th, 2014 at 08:15 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured