Find image on screen - c++

I wonder how to solve this problem. I want to check every X seconds if the screen contains an image (for example a red dot) and if so return True. I am very familiar with Python, and there are some easy solutions there. But I haven't found a similar solution yet.
What I basically want to do is:
Take a screenshot
Locate image X on the screenshot
Return bool
Looked into OpenCV and would be possible to solve it that way, but might be a bit overextending. I was thinking about getPixel to loop over all the pixels in the screen. But it's extremely slow.
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
HWND runelite = GetForegroundWindow();
HMONITOR monitor = MonitorFromWindow(runelite, MONITOR_DEFAULTTONEAREST);
MONITORINFO info;
info.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(monitor, &info);
int monitor_width = info.rcMonitor.right - info.rcMonitor.left;
int monitor_height = info.rcMonitor.bottom - info.rcMonitor.top;
int r, g, b;
HDC screenshot = GetDC(NULL);
for (int i = 0; i < monitor_height; i++) {
for (int j = 0; j < monitor_width; j++) {
DWORD color = GetPixel(screenshot, j, i);
cout << "Scanning -> X: " << j << " Y: " << i << endl;
r = GetRValue(color);
g = GetGValue(color);
b = GetBValue(color);
if (r == 0 && g == 0 && b == 0) {
cout << "Button found by color!" << endl;
goto end;
}
}
}
end:
ReleaseDC(NULL, screenshot);
return 0;
}

you could greatly increase the speed if you copy your HDCs content to another bitmap and get a pointer to the image data and loop over this.
create a memory bitmap
HDC memDC = CreateCompatibleDC ( hDC );
HBITMAP memBM = CreateCompatibleBitmap ( hDC, nWidth, nHeight );
SelectObject ( memDC, memBM );
then bitblt the screen data to that bitmap via BitBlt and get the bitmap data with GetDIBits.
please also note, that GetDC(NULL) does not make a screenshot, but gets you access to windows live main HDC. drawing to it directly draws on the desktop.
Thatswhy every GetPixel on it does take quite long.

Related

How can I make GetPixel function work on google chrome?

I'm sorry if a similar post exists but I couldn't find it.
I have been learning to use the windows.h library for 2 days. I have problems with the GetPixel function returns 0 on google chrome but returns the good values on applications installed on my computer.
Here is my code:
#include <windows.h>
#include <iostream>
#include <tchar.h>
void handleGame(HWND& _window) {
LPCWSTR windowClass = L"Chrome_WidgetWin_1";
LPCWSTR windowName = L"Stack Overflow - Where Developers Learn, Share, & Build Careers - Google Chrome";
_window = FindWindow(windowClass, windowName);
while (_window == NULL) {
std::cout << "failed" << std::endl;
_window = FindWindow(windowClass, windowName);
Sleep(1000);
}
}
int main() {
HWND window = NULL;
while (true)
{
handleGame(window);
if (GetAsyncKeyState(VK_NUMPAD1)) {
HDC hdc = GetDC(window);
COLORREF color;
COLORREF characteristic_color = 5460819;
RECT rect = {};
GetClientRect(window, &rect);
for (int i = rect.left; i < rect.right; i++) {
for (int j = rect.top; j < rect.bottom; j++) {
color = GetPixel(hdc, i, j);
std::cout << color << std::endl;
if (color == characteristic_color) {
std::cout << "FOUND!" << std::endl;
SetCursorPos(i, j);
ReleaseDC(window, hdc);
break;
}
}
}
ReleaseDC(window, hdc);
std::cout << "not found..!" << std::endl;
break;
}
}
std::cout << "end" << std::endl;
return 0;
}
I tried to follow some tutorials and I search several hours for this problem but I can't find a good answer. I have seen the BITMAP structure but I don't know how to use it and I don't think it will solve my problem.
For example my code works well on "paint" but there is a bug on google chrome.
I tried to use the mouse to get the pixel but it returns 0 too. I tried to use the function GetDC(NULL) and it works well, but I need to get just the window of the web browser, not all my screen.
The goal of the program is to find a specific COLORREF but it returns always 0 on google chrome.
I apologize for my ignorance and hope someone can help me!
Thank you!

AVI Generated From D3D11_MAPPED_SUBRESOURCE->pData is Blank

I have a simple C++ application on Windows that is using DirectX to capture the screen to a bitmap vector, stored in format like this, based on WinDesktopDup sample here :
struct Bitmap {
int Width = 0;
int Height = 0;
std::vector<uint8_t> Buf;
};
I am trying to write a collection of this captures to a video file. I am trying to write to an AVI file using Windows APIs
The Visual Studio 2019 project is here
An AVI file is being generated, but it's blank and while seems to be valid, playing in Windows 11's media player, and VLC, and doesn't have any content just black screens.
The screen capture is being performed on has a resolution of 3840 x 2160. Each frame is taking about 33 MB of RAM, which is not very efficient but at this stage my goal is to get something that works. I am running as x64 and have plenty of free memory.
After the AVI header in file, the file is just full of 0 byte values:
The main section of code here:
#include "stdafx.h"
#include "WinDesktopDup.h"
#include "WriteAVI.h"
int main()
{
WinDesktopDup desktopDup;
desktopDup.Initialize();
desktopDup.CaptureNext();
const int numberOfBitmaps = 60;
const int frameRatePerSecond = 2;
Bitmap bmp[numberOfBitmaps];
for (int i = 0; i < numberOfBitmaps; i++)
{
bmp[i].Width = desktopDup.Latest.Width;
bmp[i].Height = desktopDup.Latest.Height;
bmp[i].Buf.resize(desktopDup.Latest.Buf.size());
}
int counter = 0;
bool done = false;
while (!done)
{
printf("Capturing frame %i / %i\r\n", counter, numberOfBitmaps);
desktopDup.CaptureNext();
std::copy(desktopDup.Latest.Buf.begin(), desktopDup.Latest.Buf.end(), bmp[counter].Buf.begin());
counter++;
if (counter >= numberOfBitmaps)
{
counter = 0;
done = true;
}
//if <some event triggered> done = true;
Sleep(1000 / frameRatePerSecond);
}
printf("Writing to AVI ...\r\n");
// dump bitmaps to video
wchar_t fileName[] = L"C:\\support\\test.avi";
CAVIFile aviFile(fileName, desktopDup.Latest.Width, desktopDup.Latest.Height);
BITMAPINFO inf;
memset(&inf, 0, sizeof(inf));
inf.bmiHeader.biSize = sizeof(inf.bmiHeader);
inf.bmiHeader.biWidth = desktopDup.Latest.Width;
inf.bmiHeader.biHeight = -desktopDup.Latest.Height;
inf.bmiHeader.biPlanes = 1;
inf.bmiHeader.biBitCount = 32;
inf.bmiHeader.biCompression = BI_RGB;
void* bits = nullptr;
HDC srcDC = GetWindowDC(NULL);
for (int i = 0; i < numberOfBitmaps; i++)
{
HBITMAP dib = CreateDIBSection(srcDC, &inf, 0, &bits, nullptr, 0);
memcpy(bits, bmp[i].Buf.data(), bmp[i].Width * bmp[i].Height * 4);
for (int j = 0; j < (15 / frameRatePerSecond); j++)
{
aviFile.AddFrame(dib);
}
DeleteObject(dib);
}
DeleteObject(srcDC);
}

C++ Console - properly sized still leaves empty space for scroll bars

I am (as many before me, I have done a lot of searcing) trying to have my console display the buffer with no scroll bars. I have the window resized based on the system font size and the requested buffer size, but even after altering (and updating) the Console's style flags, I am still left with empty spaces where the horizontal and vertical scroll bars were.
Can anyone please assist me with this issue?
#include <windows.h>
#include <iostream>
const bool adjustWindowSize( const unsigned int p_console_buffer_width,
const unsigned int p_console_buffer_height )
{
/// Get the handle to the active window
HWND l_window_handle( GetConsoleWindow() );
if( l_window_handle == NULL )
{
std::cout << "GetConsoleWindow() failed\n";
return false;
}
/// Get the dimensions of the active window
RECT l_window_rect;
if( !GetWindowRect( l_window_handle, &l_window_rect ) )
{
std::cout << "GetWindowRect() failed\n";
return false;
}
/// Remove unwanted WindowStyle flags
LONG l_style( GetWindowLong( l_window_handle, GWL_STYLE ) );
l_style &= ~( WS_VSCROLL | WS_HSCROLL | WS_MAXIMIZEBOX | WS_MINIMIZEBOX |
WS_SIZEBOX );
SetWindowLong( l_window_handle, GWL_STYLE, l_style );
/// Set new window size to update the style flags
if( !SetWindowPos( l_window_handle, HWND_TOP, l_window_rect.left,
l_window_rect.top, l_window_rect.right -
l_window_rect.left, l_window_rect.bottom -
l_window_rect.top, SWP_HIDEWINDOW ) )
{
std::cout << "SetWindowPos() failed\n";
return false;
}
/// Get the dimensions of the client area within the window's borders
RECT l_client_rect;
if( !GetClientRect( l_window_handle, &l_client_rect ) )
{
std::cout << "GetClientRect() failed\n";
return false;
}
/// Get handle to console
HANDLE l_console_handle( GetStdHandle( STD_OUTPUT_HANDLE ) );
if( l_console_handle == nullptr )
{
std::cout << "GetStdHandle() failed\n";
return false;
}
/// Get font information
CONSOLE_FONT_INFO l_font_info;
if( !GetCurrentConsoleFont( l_console_handle, false, &l_font_info ) )
{
std::cout << "GetCurrentConsoleFont() failed\n";
return false;
}
/// Prepare desired client area size
unsigned int l_target_width( l_font_info.dwFontSize.X *
p_console_buffer_width );
unsigned int l_target_height( l_font_info.dwFontSize.Y *
p_console_buffer_height );
POINT l_top_left;
l_top_left.x = l_client_rect.left;
l_top_left.y = l_client_rect.top;
ClientToScreen( l_window_handle, &l_top_left );
POINT l_bottom_right;
l_bottom_right.x = l_client_rect.right;
l_bottom_right.y = l_client_rect.bottom;
ClientToScreen( l_window_handle, &l_bottom_right );
unsigned int l_diff_x = l_window_rect.right - l_bottom_right.x +
l_top_left.x - l_window_rect.left;
unsigned int l_diff_y = l_window_rect.bottom - l_bottom_right.y +
l_top_left.y - l_window_rect.top;
/// Adjust window to fit exactly it's borders + the new client size
l_window_rect.right = l_target_width + l_diff_x;
l_window_rect.bottom = l_target_height + l_diff_y;
/// Set new window size
if( !SetWindowPos( l_window_handle, HWND_TOP, l_window_rect.left,
l_window_rect.top, l_window_rect.right,
l_window_rect.bottom, SWP_SHOWWINDOW ) )
{
std::cout << "SetWindowPos() failed\n";
return false;
}
/// Set new console buffer size
if( !SetConsoleScreenBufferSize( l_console_handle,
COORD( { (SHORT)p_console_buffer_width,
(SHORT)p_console_buffer_height } ) ) )
{
std::cout << "SetConsoleScreenBufferSize() failed\n";
return false;
}
return true;
}
int main()
{
SetConsoleTitle( (LPCSTR)"Console Test" );
unsigned int l_buffer_x( 100 );
unsigned int l_buffer_y( 40 );
if( !adjustWindowSize( l_buffer_x, l_buffer_y ) )
{
std::cout << "adjustWindowSize() failed\n";
return 1;
}
for( unsigned int i( 0 ); i < l_buffer_x * l_buffer_y; ++i )
{
std::cout << i % 10;
}
SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ),
COORD( { 0, 0 } ) );
return 0;
}
Picture of console with empty spaces where scroll bars were
As I understood your question, you want to create console window that has no scroll bars and the visible area is exactly the size of the output screen buffer? This is how you can do this:
#include <windows.h>
#include <iostream>
void SetConsoleWindow(HANDLE conout, SHORT cols, SHORT rows)
{
CONSOLE_SCREEN_BUFFER_INFOEX sbInfoEx;
sbInfoEx.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
GetConsoleScreenBufferInfoEx(conout, &sbInfoEx);
sbInfoEx.dwSize.X = cols;
sbInfoEx.dwSize.Y = rows;
sbInfoEx.srWindow = { 0, 0, cols, rows };
sbInfoEx.dwMaximumWindowSize = { cols, rows };
SetConsoleScreenBufferInfoEx(conout, &sbInfoEx);
DWORD mode;
GetConsoleMode(conout, &mode);
mode &= ~ENABLE_WRAP_AT_EOL_OUTPUT;
SetConsoleMode(conout, mode);
SetConsoleTitle(L"Console Test");
}
int main()
{
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
SHORT cols = 100, rows = 20;
SetConsoleWindow(out, cols, rows);
for (int y = 0; y < rows; ++y)
{
for (int x = 0; x < cols; ++x)
std::cout << y %10;
if (y < rows - 1)
std::cout << std::endl;
}
SetConsoleCursorPosition(out, { 0,0 });
return 0;
}
This needs some explanation. CONSOLE_SCREEN_BUFFER_INFOEX structure seem to contain all the params needed to make this happen. If you check properties of your console window and compare them with struct members
you find that dwSize corresponds to Screen Buffer Size, srWindow.Right - srWindow.Left and srWindow.Bottom - srWindow.Top correspond to Window Size.
If dwMaximumWindowSize is not set, it defaults to the boundaries of the desktop and adds scroll bars if window is larger. Setting it as well fixes that.
Lastly, ENABLE_WRAP_AT_EOL_OUTPUT needs to be removed from console options to stop cursor jumping to the next line at the end of line, thus scrolling buffer with the last printed character. I have adjusted the print loop to account for that.

GetDIBits sets image buffer to all 0's (all black)

Trying to take a screenshot of a window as a bitmap. The code below is creating a properly sized bitmap, but every pixel is black. In other words, GetDIBits is setting imageBuffer to all 0's.
The posted code saves a bitmap for every notepad open and visible on the screen. None of the asserts fail.
The BITMAPFILEHEADER and actual writing to a file is omitted, because the final for loop with asserts shows GetDIBits set imageBuffer to all 0's, so there's no need to examine code after that point.
(In the executable's properties, under Configuration Properties->General, I have Character Set to "Not Set" to avoid unicode necessities.)
#include "stdafx.h"
#include <vector>
#include <sstream>
#include <Windows.h>
#include <iostream>
#include <assert.h>
using namespace std;
BOOL CALLBACK getNotepadWindowsCallback(HWND window, LPARAM notepadWindowsLparam) {
if (NULL != GetParent(window)) {
return true;
}
if (false == IsWindowVisible(window)) {
return true;
}
char text[1024] = { 0 };
GetWindowText(window, text, sizeof(text));
if (NULL == strstr(text, " - Notepad")) {
return true;
}
reinterpret_cast<vector<HWND>*>(notepadWindowsLparam)->push_back(window);
return true;
}
vector<HWND> getNotepadWindows() {
vector<HWND> notepadWindows;
EnumWindows(getNotepadWindowsCallback, reinterpret_cast<LPARAM>(&notepadWindows));
return notepadWindows;
}
int _tmain(int argc, _TCHAR* argv[]) {
for (HWND notepadWindow : getNotepadWindows()) {
HDC notepadWindowDeviceContext = GetDC(notepadWindow);
assert(NULL != notepadWindowDeviceContext);
HDC memoryDeviceContext = CreateCompatibleDC(notepadWindowDeviceContext);
assert(NULL != memoryDeviceContext);
RECT notepadWindowRectangle;
if (0 == GetClientRect(notepadWindow, &notepadWindowRectangle)) {
assert(true == false);
}
SIZE notepadWindowSize;
notepadWindowSize.cx = notepadWindowRectangle.right - notepadWindowRectangle.left + 1;
notepadWindowSize.cy = notepadWindowRectangle.bottom - notepadWindowRectangle.top + 1;
HBITMAP memoryBitmap = CreateCompatibleBitmap(notepadWindowDeviceContext, notepadWindowSize.cx, notepadWindowSize.cy);
assert(NULL != memoryBitmap);
HBITMAP defaultBitmap = static_cast<HBITMAP>(SelectObject(memoryDeviceContext, memoryBitmap));
assert(NULL != defaultBitmap);
assert(TRUE == BitBlt(memoryDeviceContext, 0, 0, notepadWindowSize.cx, notepadWindowSize.cy, notepadWindowDeviceContext, notepadWindowRectangle.left, notepadWindowRectangle.right, SRCCOPY));
BITMAPINFO bitmapinfo = { 0 };
bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapinfo.bmiHeader.biWidth = notepadWindowSize.cx;
bitmapinfo.bmiHeader.biHeight = notepadWindowSize.cy;
bitmapinfo.bmiHeader.biPlanes = 1;
bitmapinfo.bmiHeader.biBitCount = 4 * 8;
bitmapinfo.bmiHeader.biCompression = BI_RGB;
//bitmapinfo.bmiHeader.biSizeImage, per MSDN, may be set to zero for BI_RGB bitmaps
int imageBufferSize = notepadWindowSize.cx*notepadWindowSize.cy;
int* imageBuffer = new(int[imageBufferSize]);
// doing a memset here to initialize imageBuffer to 0's makes no change - leaving it out makes clear GetDIBits is setting imageBuffer to 0's, because it goes in with random garbage
assert(NULL != SelectObject(memoryDeviceContext, defaultBitmap)); // this must happen before GetDIBits, per MSDN, so memoryBitmap is not selected into a device context
int returnValue = GetDIBits(memoryDeviceContext, memoryBitmap, 0, notepadWindowSize.cy, static_cast<LPVOID>(imageBuffer), &bitmapinfo, DIB_RGB_COLORS);
assert(0 != returnValue);
cout << "returnValue is " << returnValue << endl; // shows proper number of lines is written
for (int i = 0; i < imageBufferSize; ++i) {
assert(0 == imageBuffer[i]);
}
DeleteDC(memoryDeviceContext);
ReleaseDC(NULL, notepadWindowDeviceContext);
}
}
Oops. Helps to give BitBlt notepadWindowRectangle.top instead of notepadWindowRectangle.right for its y1 parameter. Fixing that makes it work.

Reducing console size

I got a problem with changing console size. This is my code:
BOOL setConsole(int x, int y)
{
hStdin = GetStdHandle(STD_INPUT_HANDLE);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdin == INVALID_HANDLE_VALUE ||
hStdout == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, TEXT("GetStdHandle"),
TEXT("Console Error"), MB_OK);
return false;
}
SMALL_RECT windowSize = {0, 0, x-1, y-1};
// Change the console window size:
SetConsoleWindowInfo(hStdout, TRUE, &windowSize);
COORD c = { x, y};
//Change the internal buffer size:
SetConsoleScreenBufferSize(hStdout, c);
SetConsoleDisplayMode(hStdout,CONSOLE_FULLSCREEN_MODE, &c);
return true;
}
It works perfectly fine, when I try to enlarge the console. When one parameter is smaller than previous one nothing happens. What is wrong?
#edit: after some tests I noticed, that resizing(reducing) is possible if I change one parameter at once. Example(assume console is 100x100)
setConsole(90,90); //dosen't work.
setConsole(90,100);
setConsole(90,90); // works perfectly
WHY?!
SetConsoleScreenBufferSize changes the size of the internal buffer of the console.
Changing it has no effect on the console windows extent.
Call SetConsoleWindowInfo if you need an effect on the visible part of the console (buffer).
The window buffer cannot be smaller than the internal buffer , and decreasing it will also decrease the internal buffer,
but not the other way around.
If you call SetConsoleScreenBufferSize with illegal value in COORDS (e.g. too little height/width) then you get an
error, usually 87 'invalid argument'.
Try this code:
#include <iostream>
#include <windows.h>
using namespace std;
void SetWindow(int Width, int Height)
{
_COORD coord;
coord.X = Width;
coord.Y = Height;
_SMALL_RECT Rect;
Rect.Top = 0;
Rect.Left = 0;
Rect.Bottom = Height - 1;
Rect.Right = Width - 1;
HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE); // Get Handle
SetConsoleScreenBufferSize(Handle, coord); // Set Buffer Size
SetConsoleWindowInfo(Handle, TRUE, &Rect); // Set Window Size
}
int main(void)
{
SetWindow(80,40);
int dx=1,i=5,l=0;
while(l<5)
{
i=i+dx;
if( (i<1) || (i>10)){ dx=-dx; l++;}
SetWindow(10*i,5*i);
Sleep(100);
}
cout<<" \nPress any key to continue\n";
cin.ignore();
cin.get();
return 0;
}
Late to the party ...
As far as can be devised from MSDN and a few tests, the screen buffer can't be set smaller than the window's extent or the window's extent made bigger than the screen buffer.
One hack is to shrink the window to a minimal before changing the buffer size :
static void
set_console_size(HANDLE screen_buffer, SHORT width, SHORT height)
{
assert(screen_buffer != NULL);
assert(width > 0);
assert(height > 0);
COORD const size = { width, height };
BOOL success;
SMALL_RECT const minimal_window = { 0, 0, 1, 1 };
success = SetConsoleWindowInfo(screen_buffer, TRUE, &minimal_window);
CHECK(success);
success = SetConsoleScreenBufferSize(screen_buffer, size);
CHECK(success);
SMALL_RECT const window = { 0, 0, size.X - 1, size.Y - 1 };
success = SetConsoleWindowInfo(screen_buffer, TRUE, &window);
CHECK(success);
}
try this code:
system("mode 650");
I modified the code provided by 'Software_Designer' on Oct 15' 12 and created a command line utility to set the console size and scroll buffers.
I compiled it using DEV C++ (http://www.bloodshed.net/devcpp.html).
An executable is included in https://sourceforge.net/projects/wa2l-wintools/. I hope this helps.
/*
* consolesize.cpp - set console size and buffer dimensions
*
* [00] 02.07.2016 CWa Initial Version
*
* inspired by: http://stackoverflow.com/questions/12900713/reducing-console-size
*
*/
#include <iostream>
#include <windows.h>
using namespace std;
// SetWindow(Width,Height,WidthBuffer,HeightBuffer) -- set console size and buffer dimensions
//
void SetWindow(int Width, int Height, int WidthBuffer, int HeightBuffer) {
_COORD coord;
coord.X = WidthBuffer;
coord.Y = HeightBuffer;
_SMALL_RECT Rect;
Rect.Top = 0;
Rect.Left = 0;
Rect.Bottom = Height - 1;
Rect.Right = Width - 1;
HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE); // Get Handle
SetConsoleScreenBufferSize(Handle, coord); // Set Buffer Size
SetConsoleWindowInfo(Handle, TRUE, &Rect); // Set Window Size
} // SetWindow
// main(Width,Height,WidthBuffer,HeightBuffer) -- main
//
int main(int argc, char *argv[]) {
int width = 80;
int height = 25;
int wbuffer = width + 200;
int hbuffer = height + 1000;
if ( argc == 5 ){
width = atoi(argv[1]);
height = atoi(argv[2]);
wbuffer = atoi(argv[3]);
hbuffer = atoi(argv[4]);
} else if ( argc > 1 ) {
cout << "Usage: " << argv[0] << " [ width height bufferwidth bufferheight ]" << endl << endl;
cout << " Where" << endl;
cout << " width console width" << endl;
cout << " height console height" << endl;
cout << " bufferwidth scroll buffer width" << endl;
cout << " bufferheight scroll buffer height" << endl;
return 4;
}
SetWindow(width,height,wbuffer,hbuffer);
return 0;
}
/* So, tiny recap --
SetConsoleScreenBufferSize(): fails if buffer width and height
are less than the width and height of the current screen window
rectangle.
SetConsoleWindowInfo(): fails if the specified window rectangle
is larger than the boundaries of the screen buffer.
Setting the correct one 1st (buffer or window rectangle) would
solve much in a screen resize, but that's hard to know because
calls to GetConsoleScreenBufferInfo() fail easily, and so you cannot
reliably discover the current screen rectangle and/or buffer size,
and hence you cannot know if you'll be setting the screen rectangle
larger or smaller than the current size, and in turn you can't
always know which function to call 1st.
WORKAROUND:
Sloppy solution but super-reliable...
- Set the buffer 1st to something uncommonly large -- like 1000x1000.
- Then set the window rectangle to the actual desired size.
- Finally, set the window buffer to the actual desired size
(matching the screen rectangle) */
int set_screen_size(int requested_wdth, int requested_hgt)
{
SMALL_RECT srWindowRect; /* hold the new console size */
COORD coordBuffer;
BOOL bsuccess = FALSE, wsuccess = FALSE;
srWindowRect.Left = 0;
srWindowRect.Right = requested_wdth-1;
srWindowRect.Top = 0;
srWindowRect.Bottom = requested_hgt-1;
/*set buffer oversize -- like 1000x1000 (500x500 and less
could do too)*/
coordBuffer.X = coordBuffer.Y = 1000;
bsuccess = SetConsoleScreenBufferSize(hConOut, coordBuffer);
wsuccess = SetConsoleWindowInfo(hConOut, TRUE, &srWindowRect);
coordBuffer.X = requested_wdth;
coordBuffer.Y = requested_hgt;
bsuccess = SetConsoleScreenBufferSize(hConOut, coordBuffer);
/* ... */
}