0

I am asking if there is any way, and how to print text like the Windows installation "We're setting things up for you" to the middle of the screen? If I can, can I make it so only the text gets displayed and the text background should be your desktop.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Mark6712
  • 25
  • 6
  • 1
    See https://stackoverflow.com/questions/29091028/windows-api-write-to-screen-as-on-screen-display – mkrieger1 Apr 26 '21 at 19:32
  • `the text background should be your desktop` what does this mean? You want to print the desktop image into console as text? – phuclv Apr 27 '21 at 00:45
  • @phuclv That means only the text should be displayed, no console, nothing, Only a big text in the middle of the screen – Mark6712 Apr 27 '21 at 05:54
  • 1
    If one of the answers was helpful then mark it as accepted. If you have a different solution then post (and accept) your own answer. Don't change the question title to "(SOLVED)". That helps nobody who reads your question in the future. – Blastfurnace May 01 '21 at 19:17
  • you [accept an answer](https://stackoverflow.com/help/accepted-answer) by clicking the green check mark on it. Editing the question isn't the way this site works. Please take 1 minute reading the [tour] to know how it works – phuclv May 01 '21 at 23:11

2 Answers2

0

The classic way to deal with the console in Windows is via the Console API. To get the console size you can use GetConsoleScreenBufferInfo(). Here's a very simple example that draws a string at the center of the screen

#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstdint>
#include <windows.h>

int main(void)
{
    auto stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
    std::string str;

    CONSOLE_SCREEN_BUFFER_INFO oldcsbi{};
    COORD coord{};
    while (1)
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        GetConsoleScreenBufferInfo(stdout_handle, &csbi);
        if (csbi.srWindow.Bottom != oldcsbi.srWindow.Bottom || csbi.srWindow.Right != oldcsbi.srWindow.Right)
        {
            std::fill(str.begin(), str.end(), ' ');
            SetConsoleCursorPosition(stdout_handle, coord);
            std::cout << str; // clear the old text
            
            oldcsbi = csbi;
            std::ostringstream s;

            s << "Console size: " << csbi.srWindow.Right << 'x' << csbi.srWindow.Bottom;
            str = s.str();
            coord.X = (short)((csbi.srWindow.Right - str.size()) / 2);
            coord.Y = (short)(csbi.srWindow.Bottom/2);
            SetConsoleCursorPosition(stdout_handle, coord);
            std::cout << str; // draw the new text
        }
        Sleep(1000);
    }
}

console resize example

The above code gets the console size periodically and redraws the screen if the size has been changed. It loops indefinitely until you press Ctrl+C or close the program

For more information about the Console API see Using the Console


But of course polling the size like that isn't very good because it makes the output not very smooth and also eats up CPU cycles. The real solution is to listen to the resize events and do the necessary things in that callback function

There's a mode called ENABLE_WINDOW_INPUT which passes the resize events to the console where you can read by the blocking ReadConsoleInput() or PeekConsoleInput() APIs. You can see an example in Reading Input Buffer Events. Just run it and resize the window, the resize events will be printed out

Unfortunately in that mode only the console buffer size change event is fired through the WINDOW_BUFFER_SIZE_RECORD and there's no console screen size change event, so if you change the number of rows then most of the time no events are generated. That means you'll need to go to a lower level and listen to the Console Winevent named EVENT_CONSOLE_LAYOUT:

HWINEVENTHOOK eventHook = SetWinEventHook(EVENT_CONSOLE_LAYOUT, EVENT_CONSOLE_LAYOUT,
                                        NULL, EventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
...
MSG msg;
while (GetMessage(&msg, g_hWindow, EVENT_CONSOLE_LAYOUT, EVENT_CONSOLE_LAYOUT)) {
    DispatchMessage(&msg);

You can find more details in


The easier and even better way is to use ncurses and handle something similar to SIGWINCH. There were many Windows ports for ncurses in the past, and given Windows 10 console supports ANSI sequences it's even easier to write an ncurses port. In fact nowadays it's recommended to use ANSI sequences for terminal interaction instead of the ole Console API for portability

phuclv
  • 37,963
  • 15
  • 156
  • 475
-1
<Window x:Class="YourApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="600" Width="800" WindowStyle="None" AllowsTransparency="True" Background="Transparent"  Topmost="True">
    
    <StackPanel>
        <TextBlock Text="Your Text Here"/>
    </StackPanel>
</Window>

Please note that this will work only until some other application declares itself TopMost. Suggestion by Window “on desktop”

Ajay Srinivas
  • 595
  • 5
  • 16