Thread overview
Windows SetConsoleScreenBufferSize() returning an odd error code
Oct 05, 2013
webwraith
Oct 05, 2013
Andrej Mitrovic
Oct 05, 2013
webwraith
Oct 05, 2013
webwraith
Oct 05, 2013
Andrej Mitrovic
Oct 05, 2013
webwraith
Oct 05, 2013
Andrej Mitrovic
Oct 10, 2013
webwraith
October 05, 2013
I'm not sure if it's my code, although I feel fairly confident it isn't, but SetConsoleScreenBufferSize() is failing with error 87, which a quick browse of MSDN tells me is ERROR_INVALID_PARAMETER. Could someone give this code the quick once over and tell me where I'm going wrong, or simply how to get this to work?

---

module sample;

import std.c.windows.windows;
import std.conv;
import std.format;
import std.array;
import std.stdio;

alias HANDLE handle;

void main(){
	auto buff = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, null, CONSOLE_TEXTMODE_BUFFER, null);
	if( buff == INVALID_HANDLE_VALUE )
		throw new Exception("Unable to create new screen buffer. Error: " ~ text( GetLastError() ) );
	
	COORD c = {60, 30};
	
	// get the console window dims, to make sure this screen buffer is as large or larger
	CONSOLE_SCREEN_BUFFER_INFO* csbi = new CONSOLE_SCREEN_BUFFER_INFO;
	
	GetConsoleScreenBufferInfo( buff, csbi );
	short width = cast(short)(csbi.srWindow.Right-csbi.srWindow.Left);
	short height = cast(short)(csbi.srWindow.Bottom-csbi.srWindow.Top);
	
	if(c.X<width)
		c.X = width;
	if(c.Y<height)
		c.Y = height;
	
	// set the screen buffer size !!!<= THIS IS WHAT DOESN'T WORK!
	if(SetConsoleScreenBufferSize( buff, c ) == 0){
		auto err = GetLastError();
		throw new Exception("Unable to set buffer dimensions. Error: " ~ text(err) );
	}
	
	SetConsoleTextAttribute( buff, FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|BACKGROUND_INTENSITY );
	
	c.X = 2; c.Y = 28;
	SetConsoleCursorPosition( buff, c );
	readln();
}
---

In advance, I really appreciate any help you can give me
October 05, 2013
On 10/5/13, webwraith <webwraith@fastmail.fm> wrote:
> Could someone give this code the quick once over and tell me where I'm going wrong, or simply how to get this to work?

In the docs: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686044%28v=vs.85%29.aspx

It says:

dwSize [in]

    A COORD structure that specifies the new size of the console
screen buffer, in character rows and columns. The specified width and
height cannot be less than the width and height of the console screen
buffer's window.
**The specified dimensions also cannot be less than the minimum size
allowed by the system.  This minimum depends on the current font size
for the console (selected by the user) and the SM_CXMIN and SM_CYMIN
values returned by the GetSystemMetrics function.**

So you need to make these calls:

-----
short width  = cast(short)(csbi.srWindow.Right - csbi.srWindow.Left);
short height = cast(short)(csbi.srWindow.Bottom - csbi.srWindow.Top);

auto minX = GetSystemMetrics(SM_CXMIN);
auto minY = GetSystemMetrics(SM_CYMIN);

c.X = cast(short)max(minX, width);
c.Y = cast(short)max(minY, height);
-----

Also make sure to import std.algorithm to use the max() function.
October 05, 2013
On Saturday, 5 October 2013 at 11:24:49 UTC, Andrej Mitrovic wrote:
> On 10/5/13, webwraith <webwraith@fastmail.fm> wrote:
>> Could someone give this code the quick once over and tell me
>> where I'm going wrong, or simply how to get this to work?
>
> In the docs:
> http://msdn.microsoft.com/en-us/library/windows/desktop/ms686044%28v=vs.85%29.aspx
>
> It says:
>
> dwSize [in]
>
>     A COORD structure that specifies the new size of the console
> screen buffer, in character rows and columns. The specified width and
> height cannot be less than the width and height of the console screen
> buffer's window.
> **The specified dimensions also cannot be less than the minimum size
> allowed by the system.  This minimum depends on the current font size
> for the console (selected by the user) and the SM_CXMIN and SM_CYMIN
> values returned by the GetSystemMetrics function.**
>
> So you need to make these calls:
>
> -----
> short width  = cast(short)(csbi.srWindow.Right - csbi.srWindow.Left);
> short height = cast(short)(csbi.srWindow.Bottom - csbi.srWindow.Top);
>
> auto minX = GetSystemMetrics(SM_CXMIN);
> auto minY = GetSystemMetrics(SM_CYMIN);
>
> c.X = cast(short)max(minX, width);
> c.Y = cast(short)max(minY, height);
> -----
>
> Also make sure to import std.algorithm to use the max() function.

Thank you for pointing that out. It's a pity it's both annoying and confusing.
According to my system, GetSystemMetrics(SM_CXMIN) returns 132, and GetSystemMetrics(SM_CYMIN) returns 38, despite the fact that I can go into the preferences on the console window in question, and create a screen buffer that is 80x20, and even my intended 60x30. Truly frustrating...
October 05, 2013
...And that will teach me to look further. SM_CXMIN and SM_CYMIN are measured in pixels. I'll need to find out how big my font is, as well, but I'm pretty sure that 60x30 at the default system font should be bigger.
October 05, 2013
On 10/5/13, webwraith <webwraith@fastmail.fm> wrote:
> ...And that will teach me to look further. SM_CXMIN and SM_CYMIN are measured in pixels. I'll need to find out how big my font is, as well, but I'm pretty sure that 60x30 at the default system font should be bigger.

Ah right you are. For that I think you can use something like this:

TEXTMETRIC tm;
GetTextMetrics(hdc, &tm);   // Dimensions of the system font don't change
                                         // during a Windows session
int cxChar = tm.tmAveCharWidth;
int cyChar = tm.tmHeight + tm.tmExternalLeading;

There's a bunch of these calls in the SysMetrics examples you can look at here: https://github.com/AndrejMitrovic/DWinProgramming/tree/master/Samples/Chap04
October 05, 2013
I don't know about you, but it's beginning to look to me like SetConsoleScreenBufferSize() takes pixels as its unit of measurement, and not columns and rows, as is stated in its documentation. I don't suppose you could confirm this?
October 05, 2013
On 10/5/13, webwraith <webwraith@fastmail.fm> wrote:
> I don't know about you, but it's beginning to look to me like SetConsoleScreenBufferSize() takes pixels as its unit of measurement, and not columns and rows, as is stated in its documentation. I don't suppose you could confirm this?

I don't know, but maybe these are helpful:

http://stackoverflow.com/a/9237971/279684 http://msdn.microsoft.com/en-us/library/windows/desktop/ms686125%28v=vs.85%29.aspx
October 10, 2013
On Saturday, 5 October 2013 at 21:33:32 UTC, Andrej Mitrovic wrote:
> On 10/5/13, webwraith <webwraith@fastmail.fm> wrote:
>> I don't know about you, but it's beginning to look to me like
>> SetConsoleScreenBufferSize() takes pixels as its unit of
>> measurement, and not columns and rows, as is stated in its
>> documentation. I don't suppose you could confirm this?
>
> I don't know, but maybe these are helpful:
>
> http://stackoverflow.com/a/9237971/279684
> http://msdn.microsoft.com/en-us/library/windows/desktop/ms686125%28v=vs.85%29.aspx

thanks for the help Andrej. I had asked the question over on GameDev.net as well, and they ended up pointing me at the DOSBox sources, which gave me exactly what I needed. After mulling it over quickly, I realized it was a cnp to get it to work in D. I have the link here:
http://sourceforge.net/p/dosbox/code-0/HEAD/tree/dosbox/trunk/src/debug/debug_win32.cpp