I am trying to use the SetConsoleDisplayMode function, but when I compile it MASM complains that it is undefined.
LOCAL bufferSize:COORD
invoke SetConsoleDisplayMode, hStdOut, 2, DWORD PTR bufferSize
error A2006: undefined symbol : SetConsoleDisplayMode
Is there other includes I need to add in addition to \masm32\include\masm32rt.inc?
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686028(v=vs.85).aspx
Hi Brannagan,
Could you try the attached kernel32.lib ? It's rebuilt to include SetConsoleDisplayMode. Also, don't forget to specify the prototype in your source code :
SetConsoleDisplayMode PROTO :DWORD,:DWORD,:DWORD
Thanks Vortex, it now compiles, but when it encounters the SetConsoleDisplayMode invoke, it crashes the exe. :(
After some further research, I think I do not need SetConsoleDisplayMode after all. What I am trying to do is programmatically change the size of my Console Window, so the user can set it to either the default 80x25 mode, or 80x50 mode. I have it almost working now that I adjust the buffer size before adjusting the console size, and the only detail I was not able to accomplish is maximizing the Console to the full 80x50 size. It does make the maximum Window size 80x50, but it's actual Size is still 80x25, with the addition of the scrollbar on the right side allowing me to scroll down to see the additional 25 lines. In order to see all 50 lines, I must click on the "Maximize" button in the upper right, but I want it this size programmatically.
I thought I could do this using ShowWindow, but it had no effect.
LOCAL windowSize:SMALL_RECT
LOCAL bufferSize:COORD
mov windowSize.Left, 0
mov windowSize.Right, 0
mov windowSize.Top, 79
mov windowSize.Bottom, 24
mov bufferSize.x, 80
mov bufferSize.y, 25
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hStdOut,eax
invoke SetConsoleWindowInfo, hStdOut, TRUE, ADDR windowSize
invoke SetConsoleScreenBufferSize, hStdOut, DWORD PTR bufferSize
invoke ShowWindow, hStdOut, SW_MAXIMIZE
Any ideas?
See How To Obtain a Console Window Handle (http://support.microsoft.com/kb/124103)
include \masm32\include\masm32rt.inc
.data?
buffer db 1000 dup(?)
.code
start: print "Hello World", 13, 10
mov esi, offset buffer
invoke GetConsoleTitle, esi, sizeof buffer
invoke FindWindow, 0, esi
push SW_MAXIMIZE
push eax
print str$(eax), " is the handle"
call ShowWindow
exit
end start
Hi JJ,
I see that by your example, a Console Window handle is not the same as the consoles STD_OUTPUT_HANDLE.
I will have to give some thought to how I can change my application to use a unique title, since there could be multiple copies of my application running at the same time I would want to make sure the right one is selected.
Perhaps I'm better off solving this another way, such as simulating a mouse click on the maximize button. I will do some more research.
the attached program works
however, it's odd that the function appears in kernl32p.inc/lib but not kernel32.inc/lib :P
EDIT: sorry - fixed a couple typos
Quote from: Brannagan on September 15, 2014, 09:07:00 AM
I will have to give some thought to how I can change my application to use a unique title, since there could be multiple copies of my application running at the same time I would want to make sure the right one is selected.
Use
invoke GetConsoleWindow (http://msdn.microsoft.com/en-gb/library/windows/desktop/ms683175(v=vs.85).aspx)
instead. It was (probably) invented to circumvent this problem.
If its simple console you are after, there are a number of macros that help here.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
print "Cannon to right of us",13,10
fn SetConsoleTitle,"New Window Title"
inkey "next ..."
print "Cannon to left of us",13,10
fn SetConsoleTitle,"Title Number 2"
inkey "next ..."
print "Cannon in front of us",13,10
fn SetConsoleTitle,"Third Title"
inkey "next ..."
print "Volleyed and thundered",13,10
fn SetConsoleTitle,"Fourth Title"
inkey "next ..."
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
As I know, resolution of console screen could change user by window menu, so documented API for it is absent - could be counted as Windows conception. But if is much outputing, possible adjust console buffer size :biggrin:
Place this at the start of the cde section :-
SetSmallRect proc ps_r:DWORD,left:DWORD,top:DWORD,right:DWORD,bottom:DWORD
mov edx,ps_r
mov eax,left
mov [edx].SMALL_RECT.Left,ax
mov eax,top
mov [edx].SMALL_RECT.Top,ax
mov eax,right
mov [edx].SMALL_RECT.Right,ax
mov eax,bottom
mov [edx].SMALL_RECT.Bottom,ax
invoke SetConsoleWindowInfo,hConsoleOutput,TRUE,ADDR small_rect
ret
Call it from within your program with this :-
invoke SetSmallRect,ADDR small_rect,0,0,79,49
This will display a console window with 80 columns & 50 rows. Don't forget row & column counts start at zero.
Forgot to say that that in the .data? section put this:-
small_rect SMALL_RECT <>
i Think i'm getting a bit forgetful in my old age, of course this is required also in the .data? section:-
SMALL_RECT STRUCT
Left WORD ?
Top WORD ?
Right WORD ?
Bottom WORD ?
SMALL_RECT ENDS
Thanks everyone!
adeyblue: Nice, by using GetConsoleWindow, I won't need to set a unique title and use FindWindow :)
This appeared to solve things at first, until I realized that my console was not being sized correctly. It seems that the way I'm accessing the SMALL_RECT structure was bad...
dedndave: I'll go back to giving SetConsoleDisplayMode another try, but from what I have read it seems that what should be needed is a combination of SetConsoleWindowInfo and SetConsoleScreenBufferSize as demonstrated here:
http://www.cplusplus.com/forum/windows/10731/
(http://www.cplusplus.com/forum/windows/10731/)
and here is a version redskull ported which also has the SMALL_RECT structure broken:
http://www.masmforum.com/board/index.php?topic=14129.0
(http://www.masmforum.com/board/index.php?topic=14129.0)
Neil, I think you may be on the right track with your example, but when I made it into the following program, it does not change the console to 80x50 as it should have.. Did I overlook anything?
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
.data
small_rect SMALL_RECT <>
hStdOut dd 0
.data?
SMALL_RECT STRUCT
Left WORD ?
Top WORD ?
Right WORD ?
Bottom WORD ?
SMALL_RECT ENDS
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
SetSmallRect proc ps_r:DWORD,left:DWORD,top:DWORD,right:DWORD,bottom:DWORD
mov edx,ps_r
mov eax,left
mov [edx].SMALL_RECT.Left,ax
mov eax,top
mov [edx].SMALL_RECT.Top,ax
mov eax,right
mov [edx].SMALL_RECT.Right,ax
mov eax,bottom
mov [edx].SMALL_RECT.Bottom,ax
invoke SetConsoleWindowInfo,hStdOut,TRUE,ADDR small_rect
ret
SetSmallRect endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hStdOut,eax
invoke SetSmallRect,ADDR small_rect,0,0,79,49
print "The Console should now be 80x50",13,10
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
include \masm32\include\masm32rt.inc
.code
start: print "Hello World", 13, 10
xchg ebx, rv(GetConsoleWindow)
invoke MoveWindow, ebx, 100, 100, 600, 300, 1
inkey str$(ebx), " is the handle"
exit
end start
it's been a few years since I wrote a console program, I've given it some thoughyt & think that the console buffer has to be as large or greater than the console display itsel. So add this to The .data? section :-
csbi CONSOLE_SCREEN_BUFFER_INFO <>
Put this in the code section before changing console window size :-
mov ax,50
shl eax,16
mov ax,csbi.dwSize.x
invoke SetConsoleScreenBufferSize,hConsoleOutput,eax
This works for me, by the way small_rect SMALL_RECT <> should be in the .data? section.
The console can handle its own sizing just fine. See MoveWindow in my post above.
JJ: Your code changed my console window from 80x25 Window Size to 80x23 Window Size, but I don't understand what parameters are needed for 80x25 or 80x50.
Neil: I updated your suggestion with the changes you mentioned, but it's still not changing my Console Window Size (or buffer size) at all.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
.data
hStdOut dd 0
.data?
SMALL_RECT STRUCT
Left WORD ?
Top WORD ?
Right WORD ?
Bottom WORD ?
SMALL_RECT ENDS
small_rect SMALL_RECT <>
csbi CONSOLE_SCREEN_BUFFER_INFO <>
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
SetSmallRect proc ps_r:DWORD,left:DWORD,top:DWORD,right:DWORD,bottom:DWORD
mov edx,ps_r
mov eax,left
mov [edx].SMALL_RECT.Left,ax
mov eax,top
mov [edx].SMALL_RECT.Top,ax
mov eax,right
mov [edx].SMALL_RECT.Right,ax
mov eax,bottom
mov [edx].SMALL_RECT.Bottom,ax
invoke SetConsoleWindowInfo,hStdOut,TRUE,ADDR small_rect
ret
SetSmallRect endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hStdOut,eax
mov ax,50
shl eax,16
mov ax,csbi.dwSize.x
invoke SetConsoleScreenBufferSize,hStdOut,eax
invoke SetSmallRect,ADDR small_rect,0,0,79,49
print "The Console should now be 80x50",13,10
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
I made some progress by updating the old code from redskull, and now when I run it in a 80x25 console it changes to an 80x50 console with no issues at all.
But once I am in 80x50 mode, I am unable to go back to 80x25 mode for some reason. Also I see that there is an issue with the way that the SMALL_RECT is being addressed here:
mov windowSize.Left, 0
mov windowSize.Right, 0
mov windowSize.Top, 79
mov windowSize.Bottom, 24
Notice that windowSize.Top is 79, and windowSize.Right is 0, but this appears to be an invalid SMALL_RECT since it should use the Left/Top corner (0,0), and the Right/Bottom Corner (79/24) instead.
.386
.model flat, STDCALL
option casemap:none
include \masm32\include\masm32rt.inc
.data?
hStdOut HANDLE ?
hStdIn HANDLE ?
.data
windowSize SMALL_RECT<>
bufferSize COORD<>
consolemode dd 0
.data?
SMALL_RECT STRUCT
Left WORD ?
Top WORD ?
Right WORD ?
Bottom WORD ?
SMALL_RECT ENDS
.code
start:
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hStdOut,eax
invoke GetStdHandle, STD_INPUT_HANDLE
mov hStdIn,eax
conloop:
print "Press Q to quit, or any key to toggle console",10,13
getkey
or al,020h
cmp al,'q'
je exitloop
xor consolemode,1
jz do25
do50:
call Console80x50
jmp conloop
do25:
call Console80x25
jmp conloop
exitloop:
ret
Console80x25 PROC
mov windowSize.Left, 0
mov windowSize.Right, 0
mov windowSize.Top, 79
mov windowSize.Bottom, 24
mov bufferSize.x, 80
mov bufferSize.y, 25
invoke SetConsoleWindowInfo, hStdOut, TRUE, ADDR windowSize
invoke SetConsoleScreenBufferSize, hStdOut, DWORD PTR bufferSize
; invoke GetConsoleWindow
; invoke ShowWindow, eax, SW_MAXIMIZE
print "Console set to 80x25",13,10
ret
Console80x25 ENDP
Console80x50 PROC
mov windowSize.Left, 0
mov windowSize.Right, 0
mov windowSize.Top, 79
mov windowSize.Bottom, 49
mov bufferSize.x, 80
mov bufferSize.y, 50
invoke SetConsoleWindowInfo, hStdOut, TRUE, ADDR windowSize
invoke SetConsoleScreenBufferSize, hStdOut, DWORD PTR bufferSize
invoke GetConsoleWindow
invoke ShowWindow, eax, SW_MAXIMIZE
print "Console set to 80x50",13,10
ret
Console80x50 ENDP
end start
yes - the top value should be less than the bottom
i played with the console window quite a bit when i first started win32 programming
it is a buggish world to program in
i mention this so that you don't put too much effort into it, only to be disappointed
for any "major" application, i use a GUI window
Quote from: Brannagan on September 15, 2014, 06:38:53 PM
JJ: Your code changed my console window from 80x25 Window Size to 80x23 Window Size, but I don't understand what parameters are needed for 80x25 or 80x50.
MoveWindow uses screen coordinates in pixels. If you need 80x25, try width in pixels=80*7, height=25*12 or similar. It's not rocket science, really - just check the font properties of your console window.
JJ: It would be a very ugly kluge to have to compute the pixel size based on the currently selected font size.
Dave: I've considered creating an emulated console from a GUI, but why re-invent the wheel if we don't have to?
After a good night's sleep, a solution was much easier to find. It turns out that when resizing the console using just SetConsoleWindowInfo and SetConsoleScreenBufferSize , they must be called in the correct order depending on going larger or smaller.
To make the Console window smaller, you must call in this order:
invoke SetConsoleWindowInfo, hStdOut, TRUE, ADDR windowSize
invoke SetConsoleScreenBufferSize, hStdOut, DWORD PTR bufferSize
To make the Console window larger, you must call in this order:
invoke SetConsoleScreenBufferSize, hStdOut, DWORD PTR bufferSize
invoke SetConsoleWindowInfo, hStdOut, TRUE, ADDR windowSize
After some more experimenting, I found that in case we don't know if it's going to be larger or smaller, the following always works: call SetConsoleWndowInfo twice, first before calling SetConsoleScreenBufferSize, and then again afterwards:
invoke SetConsoleWindowInfo, hStdOut, TRUE, ADDR windowSize
invoke SetConsoleScreenBufferSize, hStdOut, DWORD PTR bufferSize
invoke SetConsoleWindowInfo, hStdOut, TRUE, ADDR windowSize
Also, I had to change the improperly numbered windowSize elements from redskull's code back to the correct SMALL_RECT:
mov windowSize.Left, 0
mov windowSize.Top, 0
mov windowSize.Right, 79
mov windowSize.Bottom, 24
.386
.model flat, STDCALL
option casemap:none
include \masm32\include\masm32rt.inc
.data?
hStdOut HANDLE ?
hStdIn HANDLE ?
.data
consolemode dd 0
.data?
;SMALL_RECT STRUCT
; Left WORD ?
; Top WORD ?
; Right WORD ?
; Bottom WORD ?
;SMALL_RECT ENDS
windowSize SMALL_RECT<>
bufferSize COORD<>
.code
start:
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hStdOut,eax
invoke GetStdHandle, STD_INPUT_HANDLE
mov hStdIn,eax
conloop:
print "Press Q to quit, or any key to toggle console",10,13
getkey
or al,020h
cmp al,'q'
je exitloop
xor consolemode,1
jz do25
do50:
call Console80x50
jmp conloop
do25:
call Console80x25
jmp conloop
exitloop:
ret
Console80x25 PROC
mov windowSize.Left, 0
mov windowSize.Top, 0
mov windowSize.Right, 79
mov windowSize.Bottom, 24
mov bufferSize.x, 80
mov bufferSize.y, 25
invoke SetConsoleWindowInfo, hStdOut, TRUE, ADDR windowSize
invoke SetConsoleScreenBufferSize, hStdOut, DWORD PTR bufferSize
invoke SetConsoleWindowInfo, hStdOut, TRUE, ADDR windowSize ; not needed when going smaller
; invoke GetConsoleWindow
; invoke ShowWindow, eax, SW_MAXIMIZE
print "Console set to 80x25",13,10
ret
Console80x25 ENDP
Console80x50 PROC
mov windowSize.Left, 0
mov windowSize.Top, 0
mov windowSize.Right, 79
mov windowSize.Bottom, 49
mov bufferSize.x, 80
mov bufferSize.y, 50
invoke SetConsoleWindowInfo, hStdOut, TRUE, ADDR windowSize ; not needed when going larger
invoke SetConsoleScreenBufferSize, hStdOut, DWORD PTR bufferSize
invoke SetConsoleWindowInfo, hStdOut, TRUE, ADDR windowSize
print "Console set to 80x50",13,10
ret
Console80x50 ENDP
end start
deleted
Hi nidud,
The last version I posted works perfectly, setting either 80x25 or 80x50 mode console size in a window. I have not tested it on older versions of Windows which support "full screen" console mode, so you could be right about it not allowing that. I know of a simple trick to send an ALT-Enter key to the keyboard which can force full screen mode in XP, but as far as I know this can not work in Vista, 7, 8, etc.
I ran your code under Windows 7, and it does switch from a 80x24 console window to a 182x60 console window just fine, but it did not switch to 80x50 mode as the source code indicated it should. Thanks for posting it.
deleted
Hi nidud,
You can fix the last version I posted so that it works in XP by uncommenting these 2 lines:
; invoke GetConsoleWindow
; invoke ShowWindow, eax, SW_MAXIMIZE
I tried it using XP Mode, and it worked perfect.
I didn't try your updated version yet, but will look at it more tonight. Still I think it's best to not have to shell out to mode.exe if it can be done programmatically, but I may have to in order to support XP full screen mode.
deleted
Yes it could be a font related issue.
In my tests I was using Lucida Console, set to Size 14. I also tested it in Win7 using the Consolas Font set to Size 14, and my monitor resolution is 1280x800 so the console is fully visable when it is 80x50.
In XP (using XP Mode emulator on Win7, also at 1280x800), I tested it with both Lucida Console Size 14, and Raster Font Size 8x12 and both of these work, but if I choose a larger font which can not be displayed fully at 80x50 then the buffer size is set but the Window size remains non-maximized.
deleted