www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Windows SetConsoleScreenBufferSize() returning an odd error code

reply "webwraith" <webwraith fastmail.fm> writes:
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
Oct 05 2013
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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.
Oct 05 2013
parent reply "webwraith" <webwraith fastmail.fm> writes:
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...
Oct 05 2013
parent reply "webwraith" <webwraith fastmail.fm> writes:
...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.
Oct 05 2013
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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
Oct 05 2013
parent reply "webwraith" <webwraith fastmail.fm> writes:
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?
Oct 05 2013
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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
Oct 05 2013
parent "webwraith" <webwraith fastmail.fm> writes:
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
Oct 10 2013