dotnet / pinvoke

A library containing all P/Invoke code so you don't have to import it every time. Maintained and updated to support the latest Windows OS.
MIT License
2.12k stars 223 forks source link

Kernel32.GetConsoleScreenBufferInfo seems to be giving incorrect data #312

Closed drako0812 closed 7 years ago

drako0812 commented 7 years ago

It might be a problem with the CONSOLE_SCREEN_BUFFER_INFO struct itself, but I'm unsure. For context I'm on Windows 10 and using VS 2015. Anyway, on a 80x25 cell console for srWindow I get {Left=0, Right=24, Top=79, Bottom=80} and for dwMaximumWindowSize I get {X=52, Y=0}. I'll give a code example soon.

drako0812 commented 7 years ago

Here's an example:

var hOut = GetStdHandle(STD_OUTPUT_HANDLE); // Also this isn't in the PInvoke library as far as I know
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hOut, out csbi);
Console.WriteLine("csbi.srWindow = [Left={}, Right={}, Top={}, Bottom={}]", csbi.srWindow.Left, csbi.srWindow.Right, csbi.srWindow.Top, csbi.srWindow.Bottom);
Console.WriteLine("csbi.dwMaximumWindowSize = [X={}, Y={}]", csbi.MaximumWindowSize.X, csbi.MaximumWindowSize.Y);

Also, my implementation of GetStdHandle is the following:

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);

const int STD_OUTPUT_HANDLE = -11;

My two ideas are either the command prompt that System.Console uses is not actually the one identified by GetStdConsole(STD_OUTPUT_CONSOLE), or that the Kernel32.CharacterAttributesFlags enum needs to be explicitly typed as short or ushort (ie. public enum CharacterAttributesFlags : ushort.

AArnott commented 7 years ago

Very good sleuthing, @drako0812. You're right about the size of the enum. I checked and the only other place it's used also calls for a 16-bit length value so adding :ushort looks like the right fix.

I'm throwing in the StdHandle functions you used as well into the PR to fix this.

drako0812 commented 7 years ago

Cool! Thanks for that. I've been trying to make a console wrapper that is more appropriate for a roguelike than System.Console. This was preventing me from detecting and changeing the size of the console window.

I've never understood why System.Console doesn't give a way to at least pass a buffer of chars and colors to a method to update the entire screen at one time. Going through each cell individually is abysmally slow.

drako0812 commented 7 years ago

Probably should make another issue, but I found another unsized enum that should be a ushort: Kernel32.InputEventTypeFlag

AArnott commented 7 years ago

Probably should make another issue

Yes, please do.

AArnott commented 7 years ago

meh, never mind. I'll throw it into the same PR for this issue.