How to remove scrollbars in console windows C++ - c++

I have been checking out some Rogue like games (Larn, Rogue, etc) that are written in C and C++, and I have noticed that they do not have the scrollbars to the right of the console window.
How can I accomplish this same feature?

To remove the scrollbar, simply set the screen buffer height to be the same size as the height of the window:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
// get handle to the console window
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
// retrieve screen buffer info
CONSOLE_SCREEN_BUFFER_INFO scrBufferInfo;
GetConsoleScreenBufferInfo(hOut, &scrBufferInfo);
// current window size
short winWidth = scrBufferInfo.srWindow.Right - scrBufferInfo.srWindow.Left + 1;
short winHeight = scrBufferInfo.srWindow.Bottom - scrBufferInfo.srWindow.Top + 1;
// current screen buffer size
short scrBufferWidth = scrBufferInfo.dwSize.X;
short scrBufferHeight = scrBufferInfo.dwSize.Y;
// to remove the scrollbar, make sure the window height matches the screen buffer height
COORD newSize;
newSize.X = scrBufferWidth;
newSize.Y = winHeight;
// set the new screen buffer dimensions
int Status = SetConsoleScreenBufferSize(hOut, newSize);
if (Status == 0)
{
cout << "SetConsoleScreenBufferSize() failed! Reason : " << GetLastError() << endl;
exit(Status);
}
// print the current screen buffer dimensions
GetConsoleScreenBufferInfo(hOut, &scrBufferInfo);
cout << "Screen Buffer Size : " << scrBufferInfo.dwSize.X << " x " << scrBufferInfo.dwSize.Y << endl;
return 0;
}

You need to make the console screen buffer the same size as the console window. Get the window size with GetConsoleScreenBufferInfo, srWindow member. Set the buffer size with SetConsoleScreenBufferSize().

Using #include <winuser.h>, you can simply do
ShowScrollBar(GetConsoleWindow(), SB_VERT, 0);
You can specify which scroll bar to hide using different parameters.

To remove scrollbars from the console, we can make the console screen buffer the same size as the console window. This can be done as follows:
#include <Windows.h>
#include <iostream>
int main() {
CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
// Get console handle and get screen buffer information from that handle.
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &screenBufferInfo);
// Get rid of the scrollbar by setting the screen buffer size the same as
// the console window size.
COORD new_screen_buffer_size;
// screenBufferInfo.srWindow allows us to obtain the width and height info
// of the visible console in character cells.
// That visible portion is what we want to set the screen buffer to, so that
// no scroll bars are needed to view the entire buffer.
new_screen_buffer_size.X = screenBufferInfo.srWindow.Right -
screenBufferInfo.srWindow.Left + 1; // Columns
new_screen_buffer_size.Y = screenBufferInfo.srWindow.Bottom -
screenBufferInfo.srWindow.Top + 1; // Rows
// Set new buffer size
SetConsoleScreenBufferSize(hConsole, new_screen_buffer_size);
std::cout << "There are no scrollbars in this console!" << std::endl;
return 0;
}

Related

X11 - XCB: Window information not up-to-date?

I'm using XCB to create my x11 window and, somewhere in the code, I want to move it.
I make a little test to print the window position (0, 0), then move it, and print the position again (200, 100).
Saddly, I have always x:10 and y:10.
Here the code:
// g++ -o test test_xcb.cpp -lX11 -lxcb
#include <xcb/xcb.h>
#include <iostream>
using namespace std;
void print_window_xywh(xcb_connection_t *conn, xcb_drawable_t win)
{
auto geo = xcb_get_geometry_reply(
conn, xcb_get_geometry(conn, win), nullptr);
cout << "Window( " << win << ") - x: " << geo->x
<< " - y: " << geo->y
<< " - w: " << geo->width
<< " - h: " << geo->height << endl;
}
int main(void) {
xcb_connection_t *c;
xcb_screen_t *screen;
xcb_window_t win;
/* Open the connection to the X server */
c = xcb_connect (NULL, NULL);
/* Get the first screen */
screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
/* Ask for our window's Id */
win = xcb_generate_id(c);
/* Create the window */
xcb_create_window (c, /* Connection */
XCB_COPY_FROM_PARENT, /* depth (same as root)*/
win, /* window Id */
screen->root, /* parent window */
10, 10, /* x, y */
150, 150, /* width, height */
10, /* border_width */
XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
screen->root_visual, /* visual */
0, NULL); /* masks, not used yet */
/* Map the window on the screen */
xcb_map_window (c, win);
/* Make sure commands are sent, so window is shown */
xcb_flush (c);
// Print the position and size of the window
print_window_xywh(c, win);
// Move the window
const static uint32_t values[] = { 200, 100 };
xcb_configure_window(c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
// Print again, should be 200 for x and 100 for y
print_window_xywh(c, win);
return 0;
}
Did I miss something? Thank you.
The short version: You are ignoring the interaction with the window manager.
The long version:
First, the position that GetGeometry gives you is relative to the parent window. With a reparenting window manager, the WM will add a frame window around your window to draw window decorations to (titlebar, close button, ...). If you want the position of your window on screen, you should use use xcb_translate_coordinates(c, win, screen->root, 0, 0). The reply to this request will give you the position of 0,0 of your window translated to the root window.
However, in your example that will still not work. This is because of how the window manager works. It basically forbids your program from moving its window (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT). Due to this, when you try to move your window, the X11 server only sends this request as an event to the window manager. The window manager then needs some time to handle this request. Since you are immediately checking the window position again, the request will not yet have been handled.

Wrong SDL origin axis in 1080x1920 resolution

I am facing an issue with the SDL library and different resolution than 1920x1080.
I want to copy display an image of dimension 1080x608 at the center of a screen of resolution 1080x1920 (portrait).
I have only one plugged monitor screen.
I used the following command to switch screen from 1920x1080 to 1080x1920 :
xrandr --output DP-1 --mode 1920x1080 --rotate left --primary
I am using the following code to initialize the SDL renderer :
/**
* initialize everything so we are ready to display
*/
int SdlHandler::initialize(
unsigned int positionX,
unsigned int positionY,
unsigned int width,
unsigned int height,
bool showWindow,
std::string name) {
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
return -1;
}
// Size if the window
this->width = width;
this->height = height;
this->positionX = positionX;
this->positionY = positionY;
// Create the SDL window
// 0 and 0 are the position in X and Y
unsigned int flags = SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS;
if (showWindow) {
flags |= SDL_WINDOW_SHOWN;
} else {
flags |= SDL_WINDOW_HIDDEN;
}
this->window = SDL_CreateWindow(name.c_str(), this->positionX, this->positionY, this->width, this->height, flags);
// If there had been a problem, leave
if (!this->window) {
return -1;
}
// Create a new renderer
this->renderer = SDL_CreateRenderer(this->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
// If there is an error creating it, just leave
if (!this->renderer) {
return -1;
}
// Setup the best for the SDL render quality
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
return 0;
}
Then, i call the SDL_RenderCopy function to display the image. I pass it the created renderer created with theSDL_CreateRenderer on the above code :
// Create a window at 0,0 of dimension 1080x1920
this->initialize(0, 0, 1080, 1920, true, SDL_BASE_DISPLAY_WINDOW);
// Create the SDL Rectangle that will contain the image, at the center of the window
SDL_Rect *howToDraw = new SDL_Rect();
howToDraw->x = this->positionX + floor((this->width - this->imageWidth) / 2);
howToDraw->y = this->positionY + floor((this->height - this->imageHeight) / 2);
howToDraw->w = this->imageWidth;
howToDraw->h = this->imageHeight;
SDL_RenderCopy(this->renderer, this->texture, NULL, howToDraw);
But the axis seems to be at the wrong position, igot the following result :
 EDIT AND SOLUTION
This was a bug related to Compton, the window manager, everything is working good without Compton ...
Since you are rotating your display using xrandr, we can consider this is a post processing step that will rotate everything after each framebuffer is rendered.
Because this post processing step takes a 1920x1080 image resolution as input, you should use the SDL at this resolution.
What if you change your code for:
// Create a window at 0,0 of dimension 1920x1080
this->initialize(0, 0, 1920, 1080, true, SDL_BASE_DISPLAY_WINDOW);
EDIT: I also understand that you want your image to start at the center of the window, but your are placing the middle of the image at the center of the window.
You should also try the following:
howToDraw->x = this->positionX + this->imageWidth / 2;

Get the updated screen resolution in SDL2

With SDL2, I manage to get the resolutions and positions of my displays just fine using SDL_GetCurrentDisplayMode() and SDL_GetDisplayBounds(), however when I change the resolution externally (in this case with the Windows 7 control panel) or the respective position of the displays and call these two functions again I get the same old values, not the new resolutions and positions. That is until I restart my program of course.
I suppose SDL doesn't update those. What do I need to do to get updated values without restarting the program?
AFAIK it is not possible with SDL to get the updated resolutions (anybody please correct me if I am wrong).
A way you could approach this though, is use your OS's API. In your case you were saying that you are using Windows. So you could go ahead and use the Windows API to retrieve updated resolution information. This obviously is not portable to other OS's - so you would have to do this for every OS you want to support.
I have added a minimal example at the bottom of my answer, that shows how you can retrieve the resolution of the primary display in C++. If you want to do more elaborate handling of multiple monitors and their relative positions etc., you should take a look at this question.
#include "wtypes.h"
#include <SDL.h>
#include <iostream>
using namespace std;
void GetDesktopResolution(int& w, int& h)
{
RECT r;
GetWindowRect(GetDesktopWindow(), &r);
w = r.right;
h = r.bottom;
}
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow("SDL", 0, 0, 640, 480, SDL_WINDOW_RESIZABLE);
bool running = true;
while(running) {
SDL_Event game_event;
if(SDL_PollEvent(&game_event)) {
switch(game_event.type) {
case SDL_QUIT:
running = false;
break;
}
}
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
cout << "SDL" << current.w << "," << current.h << '\n';
int w, h;
GetDesktopResolution(w, h);
cout << "winapi" << w << "," << h << '\n';
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

Dev C++ Console Window Properties

I am using Dev C++ v5.6.1 IDE on Windows7.
I have written a C code which has hundreds of line that are displayed as output on screen.
The buffer size of Console Windows is small and I cannot view the initial printf statements.
I tried it changing from "properties" option, but it didn't help.
Where Can I find the option to increase the console window buffer size.
As you're using Windows, a simple way you can do this is by changing the console window size with the batch command: mode con: cols=150 lines=50. cols adjusts width, lines adjusts height.You may choose to call this with system to set the console size. This is considered bad, more about that here.
// This is considered bad, you shouldn't use system calls.
system("mode con: cols=150 lines=50");
A safer way to do this, is changing the buffer and size using functions defined in <windows.h>.
Here is a small example illustrating this:
#include <stdio.h>
#include <windows.h>
int main(void)
{
SMALL_RECT rect;
COORD coord;
coord.X = 150; // Defining our X and
coord.Y = 50; // Y size for buffer.
rect.Top = 0;
rect.Left = 0;
rect.Bottom = coord.Y-1; // height for window
rect.Right = coord.X-1; // width for window
HANDLE hwnd = GetStdHandle(STD_OUTPUT_HANDLE); // get handle
SetConsoleScreenBufferSize(hwnd, coord); // set buffer size
SetConsoleWindowInfo(hwnd, TRUE, &rect); // set window size
printf("Resize window");
return 0;
}
Keep in mind that the function SetConsoleWindowInfo fails if the specified window rectangle extends beyond the boundaries of the console screen buffer. More about that here.

How would I find the height of the task bar?

In my windows application, I am trying to find the height of the task bar. While I can hard program this into my program, I would like to find it programmatically to support past, present (win7) and future windows versions.
So, how would I do this?
You get it from GetMonitorInfo(), MONITORINFOEX.rcWork member.
Get the HMONITOR that you need to call this function from, say, MonitorFromRect(), passing your window rectangle. Or MonitorFromPoint() or EnumDisplayMonitors(), depends where you want to display your window. (0,0) is always the upper left corner of the primary monitor.
Ask Windows about it using the ABM_GETTASKBAR message and specifying the hwnd for the taskbar.
By searching Google for "height of taskbar c++", I got the following result:
Here's how to get the height of the Windows task bar using the windows functions FindWindow and GetWindowRect.
int MyClass::getTaskBarHeight()
{
RECT rect;
HWND taskBar = FindWindow(L"Shell_traywnd", NULL);
if(taskBar && GetWindowRect(taskBar, &rect)) {
return rect.bottom - rect.top;
}
}
Getting the width (should the task bar be on the left or right of the
screen) can be done using:
rect-right - rect.left
You may want to check if the width is greater than the height. If the width is greater, this means the bar is at the top or bottom. Otherwise, it is on the left/right side of the screen.
Probably, you want not only Taksbar, but all other 'bars' on the screen?
All you actually need is SystemParametersInfo(SPI_GETWORKAREA)
SystemParametersInfo, passing SPI_GETWORKAREA as a parameter
Retrieves the size of the work area on the primary display monitor.
The work area is the portion of the screen not obscured by the system
taskbar or by application desktop toolbars. The pvParam parameter must
point to a RECT structure that receives the coordinates of the work
area, expressed in virtual screen coordinates.
There are numerous methods depending on your needs. I used EnumDisplayMonitors() as I needed to test every display to see if it had a taskbar. A method of doing this is:
Use EnumDisplayMonitors() to get a list of all the monitors.
MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
Inside the callback will give you a handle to a display.
Warning this function will enumerate virtual displays as well: Using the handle to the display, use GetMonitorInfo() with the handle to the display.
This will return the name of the display along with two RECT structures one of the display position and resolution, the other RECT will be the work-area. You will need to do two checks (One for the X, one for the Y) to see if there is a taskbar on the monitor and the height or width of the taskbar.
For example first we check the Y axis:
if(monitor->rcMonitor.top == monitor->rcWork.top &&
monitor->rcMonitor.bottom == monitor->rcWork.bottom)
{
std::cout << "There is no taskbar on the Y axis" << std::endl;
}
else
{
std::cout << "There is a taskbar on the Y axis" << std::endl;
int height = monitor->rcMonitor.bottom - monitor->rcMonitor.top;
int hieghtOfTaskbar = height - (monitor.rcWork.bottom - monitor.rcWork.top);
std::cout << "The height of the taskbar is: " << heightOfTaskbar << std::endl;
}
Then we check the X axis:
if(monitor->rcMonitor.right == monitor->rcWork.right &&
monitor->rcMonitor.left == monitor->rcWork.left )
{
std::cout << "There is no taskbar on the X axis" << std::endl;
}
else
{
std::cout << "There is a taskbar on the X axis" << std::endl;
int width = monitor->rcMonitor.left - monitor->rcMonitor.right;
int widthOfTaskbar = height - (monitor.rcWork.left - monitor.rcWork.right);
std::cout << "The width of the taskbar is: " << heightOfTaskbar << std::endl;
}
The height or width, depending on position, of the taskbar will usually be the height or the width of the monitor respectively, though this may not always be the case.