c++cwinapiclipboardc++builder

Move Console Text to the Clipboard Programmatically in C or C++


Given that there is pre-existing text on a Windows 11 console, how can all of the text be copied to the clipboard using C or C++?

That is, I want to do the programmatic equivalent of dragging with a mouse across all of the text to select it and then pressing Ctrl-C so that it's captured into the clipboard.


Solution

  • Here is the solution as requested. This code is tested in MS Visual Studio and Windows OS 10 by me just now.

    Please note that this is non-portable Windows code because OP has asked for a solution specifically related to the Windows OS and has tagged winapi.

    This program prints a string to the console window, then captures/scrapes the text from the screen/console window via windows API ReadConsoleOutputCharacter().

    The text data is then copied to the windows clipboard buffer.

    #include <windows.h>
    #include <stdio.h>
    #include <conio.h>
    
    /*-------------------------------------------------------------------------
    
      copy_to_clipboard()
    
      Adapted from https://stackoverflow.com/a/1264179/3130521
      Credits: Judge Maygarden
    *--------------------------------------------------------------------------*/
    BOOL copy_to_clipboard(char *pBuff)
    {
        size_t size = strlen(pBuff)+1;
        if(size > 1)
        {
            HGLOBAL hMem =  GlobalAlloc(GMEM_MOVEABLE, size);
            memcpy(GlobalLock(hMem), pBuff, size);
            GlobalUnlock(hMem);
            OpenClipboard(0);
            EmptyClipboard();
            SetClipboardData(CF_TEXT, hMem);
            CloseClipboard();
            return TRUE;
        }
        return FALSE;
    }
    
    int main() 
    {
        /* Get the handle to the console window*/
        HANDLE hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_SCREEN_BUFFER_INFO CSBI;
        int win_w,win_h,size;
        char *tbuff;
        DWORD num_chars_read;
        COORD   dwReadCoord={0,0}; /* Read from screen top, left (0,0) */
    
        if(hConOut == INVALID_HANDLE_VALUE)
        {
            printf("STDOUT not available.\n");
            return 0;
        }
    
        /* Put some text to the screen */
        printf("This text should match the contents of the clipboard buffer on completion.\n");
    
        /* Get console window dims, potential text size, allocate buffer to that size */
        GetConsoleScreenBufferInfo( hConOut, &CSBI );
        win_w=CSBI.srWindow.Right - CSBI.srWindow.Left+1;
        win_h=CSBI.srWindow.Bottom - CSBI.srWindow.Top+1;
        size = win_w*win_h;
        tbuff = malloc(size+1);
        if(!tbuff)
        {
            printf("malloc() failed!\n");
            return 0;
        }
    
        /* Capture the text from the console window*/
        if(!ReadConsoleOutputCharacter( hConOut, tbuff, size,dwReadCoord, &num_chars_read))
        {
            free(tbuff);
            printf("ReadConsoleOutputCharacter() failed!\n");
            return 0;
        }
    
        /* Strip trailing whitepace (there should be a lot!)*/
        while(num_chars_read && tbuff[num_chars_read-1] == ' ')
            tbuff[--num_chars_read] = '\0';
    
        /* Copy text to the clipboard*/
        if(!copy_to_clipboard(tbuff))
        {
            free(tbuff);
            printf("copy_to_clipboard() failed!\n");
            return 0;
        }
    
        free(tbuff);  /* Always free() */
    
        /* Notify user done */
        printf("All done. Success. Open notepad and paste from clipboard.\n");
        _getch(); /* wait key press */
    
        return 0;
    }