'Specific' Double buffering with this code? - c++

For this code I am trying to implement double buffering so that it does not blink when updating the std::cout on my console window in windows 10. What is the best way to implement this into my current code? I am looking at some Microsoft documentation but I can't figure out a way to merge it so to speak?
void ClearScreen()
{
HANDLE hStdOut;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD count;
DWORD cellCount;
COORD homeCoords = { 0, 0 };
homeCoords.X = 0;
homeCoords.Y = 0;
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut == INVALID_HANDLE_VALUE) return;
/* Get the number of cells in the current buffer */
if (!GetConsoleScreenBufferInfo(hStdOut, &csbi)) return;
cellCount = csbi.dwSize.X * csbi.dwSize.Y;
/* Fill the entire buffer with spaces */
if (!FillConsoleOutputCharacter(
hStdOut,
(TCHAR) ' ',
cellCount,
homeCoords,
&count
)) return;
/* Fill the entire buffer with the current colors and attributes */
if (!FillConsoleOutputAttribute(
hStdOut,
csbi.wAttributes,
cellCount,
homeCoords,
&count
)) return;
/* Move the cursor home */
SetConsoleCursorPosition(hStdOut, homeCoords);
}

The basic idea is to call CreateConsoleScreenBuffer to create an off-screen buffer. Then clear/fill it as needed by passing the handle to that screen buffer when you do your calls to FillConsoleOutputCharacter, FillConsoleOutputAttribute, etc. When it's ready for the user to view, call SetConsoleActiveScreenBuffer to make it the active buffer for the console.
Note that in most cases you won't want to create a new screen buffer every time you clear the screen--rather you'll probably want to create two screen buffers when you start your program, and alternate between the two as you write and display output.

Related

Windows setFocus, target window does not capture keyboard input

i'm coding a wrapper for a CMD window (and potentially any shell), which purpose is to keep a shell instance always opened out of a screen's border. Moving the mouse to the border of the screen would cause the window moving down. (the window is a topmost window).
The point is to have a terminal always accessible as process (not taking space in the taskbar) and which hides when not being used.
One useful feature would be to force the focus on that window, so that, once it starts moving in your screen you can directly start typing without clicking on it to give it focus.
I'm coding all of that in c++ within visual studio with sfml support (that program itself has many sfml graphic windows, and that prompt is the only non-graphic one). Sfml in the code relative to that wrapper is only used to get mouse coordinates, in the form of sf::Mouse::getPosition().x/y.
When i run the program from within visual studio, whether in debug or in release mode, it all works fine. I can focus some other window, do stuff there, and as soon as i move the mouse in the position which makes the prompt window move in the screen, if i start typing without clicking on the actual page, the prompt will actually start capturing keyboard input as intended.
However, if i run the program as a stand-alone executable, this behaviour is no longer achieved. It appears the prompt does get focus indeed, since the "typing cursor" is there, but the window does not capture the actual keyboard input, which is weird.
Relevant code is as follows:
//create terminal window beg
STARTUPINFO prompt_startupinfo;
PROCESS_INFORMATION prompt_processinfo;
HWND prompt_window;
Win::spawn_prompt(&prompt_startupinfo, &prompt_processinfo, &prompt_window);
//always on bottom
SetWindowPos(prompt_window, HWND_TOP, 0, -PROMPT_HEIGHT + 2, Screen::get_width(), PROMPT_HEIGHT, SWP_SHOWWINDOW);
SetWindowLong(prompt_window, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
SetWindowLong(prompt_window, GWL_STYLE, WS_POPUP | WS_VISIBLE);
//create terminal window end
bool outside = false;
bool exiting = false;
while (IsWindow(prompt_window))
{
//Console move beg
int my = sf::Mouse::getPosition().y;
int mx = sf::Mouse::getPosition().x;
RECT rect;
GetWindowRect(prompt_window, &rect);
int wy = rect.bottom;
if ((my <= wy + 1) and not exiting)
{
if ((not outside) or (mx < 32))
{
if (wy < PROMPT_HEIGHT)
{
wy += WINDOW_SPEED * 4;
outside = false;
if (wy > PROMPT_HEIGHT)
{
wy = PROMPT_HEIGHT;
}
}
SetForegroundWindow(prompt_window);
}
}
else if (wy > 0)
{
wy -= WINDOW_SPEED * 4;
exiting = true;
if (wy <= 0)
{
wy = 0;
outside = true;
exiting = false;
}
}
SetWindowPos(prompt_window, 0, 0, wy - PROMPT_HEIGHT, 0, 0, SWP_NOSIZE);
//Console move end
Sleep(1000 / 60);
}
As a quick note, when running from within visual studio, the desired behaviour is achieved by just having the SetForegroundWindow(prompt_window); call, no even need for SetFocus(prompt_window);
Just for the sake of completion here is the Win::spawn_prompt function:
HWND Win::find_main_window(unsigned long process_id)
{
handle_data data;
data.process_id = process_id;
data.best_handle = 0;
EnumWindows(enum_windows_callback, (LPARAM)&data);
return data.best_handle;
}
BOOL CALLBACK Win::enum_windows_callback(HWND handle, LPARAM lParam)
{
handle_data& data = *(handle_data*)lParam;
unsigned long process_id = 0;
GetWindowThreadProcessId(handle, &process_id);
if (data.process_id != process_id || !is_main_window(handle))
{
return TRUE;
}
data.best_handle = handle;
return FALSE;
}
BOOL Win::is_main_window(HWND handle)
{
return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle);
}
bool Win::spawn_prompt(STARTUPINFO* prompt_startupinfo, PROCESS_INFORMATION* prompt_processinfo, HWND* prompt_window)
{
// additional information
STARTUPINFO si;
PROCESS_INFORMATION pi;
pi.hProcess;
// set the size of the structures
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// start the program up
CreateProcess(L"C:\\Windows\\System32\\cmd.exe", // the path
L"", // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
);
Sleep(1000);
HWND pw = Win::find_main_window(pi.dwProcessId);
*prompt_startupinfo = si;
*prompt_processinfo = pi;
*prompt_window = pw;
return false;
}
Ok i solved the problem.
Since that "set focus" event should have been triggered only when user's mouse was in a certain position, the most immediate workaround i could think of was simulating a click in that position.
Thanks for the hints #Daniel Sęk,
I'd still appreciate a more clean and less workaround-ish solution, so any further hint would be appreciated.
EDIT:
despite the window being topmost, sometimes the currently focused window still sits over the cmd window, and if that focused window is at the coordinates where i simulate the click, it captures that click making mentioned solution not always reliable.

In Windows, Does SetCurrentConsoleFontEx change console's font size?

Other guys recommend the SetCurrentConsoleFontEx function but I don't know how to apply it to my project.
I want to change the font size of only some texts, not all texts.
Does SetCurrentConsoleFontEx() change the console's font size?
Or are there other ways to change it?
If there is, please show me the console function and a simple example.
Here is an example of using SetCurrentConsoleFontEx to change the console's font size. This affects the entire console window -- so like Joachim Pileborg already said, if you want mixed font sizes in a single console window, this won't help you.
#define _WIN32_WINNT 0x500
#include <Windows.h>
// PrintChars sends ASCII characters to console output
// for demonstration purposes.
// depends only on Win32 API
static void PrintChars() {
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD num_written;
static const char* cr_lf = "\r\n";
for(char c=' '; c<'\x7f'; ++c) {
WriteFile(hStdout, &c, 1, &num_written, NULL);
if(c % 16 == 15) WriteFile(hStdout, cr_lf, 2, &num_written, NULL);
}
WriteFile(hStdout, cr_lf, 2, &num_written, NULL);
}
// WaitEnter blocks execution until the user
// presses the enter key.
// depends only on Win32 API
static void WaitEnter() {
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
char buffer;
DWORD num_read;
do {
num_read = 0;
ReadFile(hStdin, &buffer, 1, &num_read, NULL);
} while(num_read && buffer != '\n');
}
int main() {
// Display some example characters
PrintChars();
// Wait for the user to see how the current font looks
WaitEnter();
// Get a handle to the current console screen buffer
HANDLE hcsb = CreateFileA("CONOUT$", GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
CONSOLE_FONT_INFOEX cfi = {sizeof(cfi)};
// Populate cfi with the screen buffer's current font info
GetCurrentConsoleFontEx(hcsb, FALSE, &cfi);
// Modify the font size in cfi
cfi.dwFontSize.X *= 2;
cfi.dwFontSize.Y *= 2;
// Use cfi to set the screen buffer's new font
SetCurrentConsoleFontEx(hcsb, FALSE, &cfi);
// Wait for the user to see the difference before exiting
WaitEnter();
CloseHandle(hcsb);
}

Allegro 5 & C++ - Creating a fullscreen console?

All right, here's my main goal: get a fullscreen, non-windowed console program (that looks like the DOS operating system when you open it). I've defined ALLEGRO_USE_CONSOLE and all that stuff. Here's my full code to look at:
#define _WIN32_WINNT 0x0500
#define ALLEGRO_USE_CONSOLE
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <string>
#include <time.h>
#include "include/allegro.h"
using namespace std;
void SetColor(unsigned short hColor) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), hColor);
}
void Dots() {
int i = 1;
while (i <= 3) {
cout << ".";
Sleep(750);
i++;
}
}
void ClearConsoleScreen() {
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD count;
DWORD cellCount;
COORD homeCoords = { 0, 0 };
if (hStdOut == INVALID_HANDLE_VALUE) return;
/* Get the number of cells in the current buffer */
if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return;
cellCount = csbi.dwSize.X *csbi.dwSize.Y;
/* Fill the entire buffer with spaces */
if (!FillConsoleOutputCharacter(
hStdOut,
(TCHAR) ' ',
cellCount,
homeCoords,
&count
)
) return;
/* Fill the entire buffer with the current colors and attributes */
if (!FillConsoleOutputAttribute(
hStdOut,
csbi.wAttributes,
cellCount,
homeCoords,
&count
)
) return;
/* Move the cursor home */
SetConsoleCursorPosition( hStdOut, homeCoords );
}
int main() {
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_DISPLAY_MODE disp_data;
al_init(); // I'm not checking the return value for simplicity.
al_get_display_mode(al_get_num_display_modes() - 1, &disp_data);
al_set_new_display_flags(ALLEGRO_FULLSCREEN);
display = al_create_display(disp_data.width, disp_data.height);
al_rest(3);
al_destroy_display(display);
}
So what exactly do I need to do to be able to make the console full screen (non-windowed & borderless) AND be able to use cout and such? I'm running Win7 as well.
ALLEGRO_USE_CONSOLE just tells Allegro that you're planning on running the program with with a console window; you still have to set the subsystem to "console" in your linker options. Allegro has nothing to do with creating the console window.
Now, if you just want to make the console fullscreen on windows, there's SetConsoleDisplayMode but that has nothing to do with Allegro. You can't use Allegro's drawing API because there's no Direct3D or OpenGL context to use.
Edit: It seems the above function no longer works on modern versions of windows...
Using a console is extremely platform specific, which is part of the reason why allegro_native_dialog exists. But there's no way to put that into a fullscreen mode.
If you want cross-platform functionality, you could create your own emulated console using Allegro's drawing API, but it would be a large undertaking.
Generally people who want a console application don't care exactly how it looks, only that the right data comes out for the data that you put in.

Win32 C++ console clearing screen without blinking

I've seen some console games where the screen refreshes/clears itself without the annoying blinking. I've tried numerous solutions, here's what I got as of now:
while(true)
{
if(screenChanged) //if something needs to be drawn on new position
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
}
///printf all the time graphics on their right position with SetConsoleCursorPosition
Sleep(33.3f);
}
Still, I'm getting some minimal blinking. Anyone have any ideas?
The reason this is happening is because the display refreshes between the time you clear the console screen and actually draw to it. Usually this can happen so fast that you never see it but once in a while you do it at the right time and you experience flickering.
One great option is to create an offscreen buffer the same size and width as the console screen, do all of your text output and updating there, then send the entire buffer to the console screen using WriteConsoleOutput. Make sure you take into account that the screen buffer has to hold both text and attribute information, the same format as the console.
BOOL WINAPI WriteConsoleOutput(
_In_ HANDLE hConsoleOutput,
_In_ const CHAR_INFO *lpBuffer,
_In_ COORD dwBufferSize,
_In_ COORD dwBufferCoord,
_Inout_ PSMALL_RECT lpWriteRegion
);
You want to do the equivalent of double buffering. Using CreateConsoleScreenBuffer and SetConsoleActiveScreenBuffer api calls, you can modify an offscreen buffer, then switch buffers, like we used to in the bad old days :) Here's an article that explains how: http://msdn.microsoft.com/en-us/library/windows/desktop/ms685032%28v=vs.85%29.aspx
You looking for double buffering

Clear Screen Command in C++

I want to clear the screen after user enters some numbers in C++. I'm programming in console application mode.
so how to do it? My OS is win7 and My IDE is CodeBlocks and the Compiler is MingW...
It depends of your OS,
If you use linux:
system("clear");
If you use windows:
system("cls");
but this make your application lees portable, it's preferable to do
cout << string(50, '\n');
this line will print lines to seem like the terminal was 'cleared'.
A good article about that problem:
http://www.cplusplus.com/articles/4z18T05o/
You can use the clrscr() defined in conio.h.
Ways to clear screen the output screen.
you can try system methods E.g. system("CLS");
link the conio.h in your compiler. I forgot how to do that. if you will use clear screen repeatedly put this function.
enter code here
void clrscr()
{
system("cls");
}
That's what Microsoft has to say about clearing a console:
#include <windows.h>
void cls( HANDLE hConsole )
{
COORD coordScreen = { 0, 0 }; // home for the cursor
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
// Get the number of character cells in the current buffer.
if( !GetConsoleScreenBufferInfo( hConsole, &csbi ))
{
return;
}
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
// Fill the entire screen with blanks.
if( !FillConsoleOutputCharacter( hConsole, // Handle to console screen buffer
(TCHAR) ' ', // Character to write to the buffer
dwConSize, // Number of cells to write
coordScreen, // Coordinates of first cell
&cCharsWritten ))// Receive number of characters written
{
return;
}
// Get the current text attribute.
if( !GetConsoleScreenBufferInfo( hConsole, &csbi ))
{
return;
}
// Set the buffer's attributes accordingly.
if( !FillConsoleOutputAttribute( hConsole, // Handle to console screen buffer
csbi.wAttributes, // Character attributes to use
dwConSize, // Number of cells to set attribute
coordScreen, // Coordinates of first cell
&cCharsWritten )) // Receive number of characters written
{
return;
}
// Put the cursor at its home coordinates.
SetConsoleCursorPosition( hConsole, coordScreen );
}
int main()
{
HANDLE hStdout;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
cls(hStdout);
return 0;
}
system("cls");
Brilliant. So what happens if I replace the Windows cls with my own malicious cls? You've just given me control, thanks! This is what's called a back door, and you left it wide open by using an insecure technique.
Source: http://www.daniweb.com/software-development/cpp/threads/76934/how-do-i-clear-my-screen-in-c.
One method is to output '\f' (corresponding to the ASCII form feed character, code 12, which is used by line printers to eject a page, and recognized by some common terminals and emulators as a clear screen).
That won't work on Windows.
#ifdef _WIN32
/* windows hack */
#else
std::cout << '\f' std::flush;
#endif