Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do a C# Windows Console application that "respects" previous console content?

Like Vim: When it starts it takes you to another "buffer". When vim closes, the user sees the previous content of the command prompt.

Does anybody know how to do this using C#?

Thanks

Edit: The user would no longer see the output of the application. Hope that explains it better.

like image 413
robertoprs Avatar asked Feb 21 '13 08:02

robertoprs


1 Answers

I figured this out by looking at the Vim source code the relevant bits can be found in os_win32.c in the mch_init function, I've copied and pasted the relevant bit here

    /* Obtain handles for the standard Console I/O devices */
    if (read_cmd_fd == 0)
    g_hConIn =  GetStdHandle(STD_INPUT_HANDLE);
    else
    create_conin();
    g_hConOut = GetStdHandle(STD_OUTPUT_HANDLE);

#ifdef FEAT_RESTORE_ORIG_SCREEN
    /* Save the initial console buffer for later restoration */
    SaveConsoleBuffer(&g_cbOrig);
    g_attrCurrent = g_attrDefault = g_cbOrig.Info.wAttributes;
#else
    /* Get current text attributes */
    GetConsoleScreenBufferInfo(g_hConOut, &csbi);
    g_attrCurrent = g_attrDefault = csbi.wAttributes;
#endif
    if (cterm_normal_fg_color == 0)
    cterm_normal_fg_color = (g_attrCurrent & 0xf) + 1;
    if (cterm_normal_bg_color == 0)
    cterm_normal_bg_color = ((g_attrCurrent >> 4) & 0xf) + 1;

    /* set termcap codes to current text attributes */
    update_tcap(g_attrCurrent);

    GetConsoleCursorInfo(g_hConOut, &g_cci);
    GetConsoleMode(g_hConIn,  &g_cmodein);
    GetConsoleMode(g_hConOut, &g_cmodeout);

#ifdef FEAT_TITLE
    SaveConsoleTitleAndIcon();
    /*
     * Set both the small and big icons of the console window to Vim's icon.
     * Note that Vim presently only has one size of icon (32x32), but it
     * automatically gets scaled down to 16x16 when setting the small icon.
     */
    if (g_fCanChangeIcon)
    SetConsoleIcon(g_hWnd, g_hVimIcon, g_hVimIcon);
#endif

So it simply saves the console information (including the title and icon) and then restores it again on exit.

Unfortunately the Console class doesn't provide access to the contents of the screen buffer, so to do this you are going to need to P/Invoke into the relevant Win32 functions.

Alternatively the Win32 console actually supports multiple screen buffers which might be an easier way to implement this - rather than copy the existing screen buffer simply create a new one with the CreateConsoleScreenBuffer and set that buffer to be the one currently shown using SetConsoleActiveScreenBuffer. Again the Console class unfortunately doesn't support multiple screen buffers so you will need P/Invoke to do this. Also the Console class always writes to the screen buffer that was active at the point the application was launched, so if you swap out the active screen buffer the Console class will still be writing to the old screen buffer (which is no longer visible) - to get around this you would need to P/Invoke all of your console access, see Working with Console Screen Buffers in .NET .

like image 70
Justin Avatar answered Oct 20 '22 00:10

Justin