News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

SetConsoleDisplayMode not defined in MASM32

Started by Brannagan, September 15, 2014, 06:29:51 AM

Previous topic - Next topic

jj2007

The console can handle its own sizing just fine. See MoveWindow in my post above.

Brannagan

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

Brannagan

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

dedndave

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

jj2007

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.

Brannagan

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


nidud

#21
deleted

Brannagan

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.

nidud

#23
deleted

Brannagan

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.

nidud

#25
deleted

Brannagan

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.

nidud

#27
deleted