News:

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

Main Menu

SetConsoleFont, Etc

Started by MichaelW, May 28, 2013, 06:34:22 AM

Previous topic - Next topic

MichaelW

This came up on the FreeBASIC forum recently, and I thought it was interesting so I did a MASM version.

AFAIK GetConsoleFontInfo, GetNumberOfConsoleFonts, and SetConsoleFont are currently undocumented, even though they are exported from the kernel32.dll on my Windows XP Pro installation CD, and the file date is March 31, 2003.

;==============================================================================
    include \masm32\include\masm32rt.inc
    include \masm32\include\kernl32p.inc
    includelib \masm32\lib\kernl32p.lib
;==============================================================================
CONSOLE_FONT_INFO struct
    nFont      DWORD ?
    dwFontSize COORD <>
CONSOLE_FONT_INFO ends
;==============================================================================
    .data
        hStdOut dd 0
        nFonts  dd 0
    .code
;==============================================================================
start:
;==============================================================================
    invoke GetStdHandle, STD_OUTPUT_HANDLE
    mov hStdOut, eax

    invoke GetNumberOfConsoleFonts
    mov nFonts, eax
    printf("%d\n",nFonts)

    mov eax, nFonts
    imul eax, SIZEOF CONSOLE_FONT_INFO
    mov esi, alloc(eax)

    invoke GetCurrentConsoleFont, hStdOut, TRUE, esi
    printf("%d\n",eax)

    printf("%d\t", [esi].CONSOLE_FONT_INFO.nFont)
    movzx eax, [esi].CONSOLE_FONT_INFO.dwFontSize.x
    printf("%d\t",eax)
    movzx eax, [esi].CONSOLE_FONT_INFO.dwFontSize.y
    printf("%d\n",eax)

    invoke SetConsoleFont, hStdOut, 0
    printf("%d\n",eax)

    invoke GetCurrentConsoleFont, hStdOut, TRUE, esi
    printf("%d\n",eax)

    printf("%d\t", [esi].CONSOLE_FONT_INFO.nFont)
    movzx eax, [esi].CONSOLE_FONT_INFO.dwFontSize.x
    printf("%d\t",eax)
    movzx eax, [esi].CONSOLE_FONT_INFO.dwFontSize.y
    printf("%d\n\n",eax)

    invoke GetConsoleFontInfo, hStdOut, TRUE, nFonts, esi
    xor ebx, ebx
    .WHILE ebx < nFonts
        printf("%d\t", [esi+ebx*8].CONSOLE_FONT_INFO.nFont)
        movzx eax, [esi+ebx*8].CONSOLE_FONT_INFO.dwFontSize.x
        printf("%d\t",eax)
        movzx eax, [esi+ebx*8].CONSOLE_FONT_INFO.dwFontSize.y
        printf("%d\n",eax)
        inc ebx
    .ENDW
    printf("\n")

    xor ebx, ebx
    .WHILE ebx < nFonts
        invoke SetConsoleFont, hStdOut, ebx
        invoke Sleep, 3000
        inc ebx
    .ENDW

    invoke SetConsoleFont, hStdOut, 0
    printf("%d\n\n",eax)

    free esi
    inkey
    exit
;==============================================================================
end start


The three undocumented functions are not included in kernel32.lib, but are in kernl32p.lib. I'm not sure how kernl32p.lib is supposed to be used, but what I did is copy kernel32.dll from my system32 directory to my working directory and rename it to kernl32p.dll. And what does the p stand for?

On my system I get:

5
1
0       80      49
1
1
0       80      49

0       80      49
1       66      49
2       61      49
3       36      27
4       34      27


Per the documentation for the CONSOLE_FONT_INFO structure here:
Quote
A COORD structure that contains the width and height of each character in the font, in logical units. The X member contains the width, while the Y member contains the height.

But since the console and character size increase as the font index increases, I suspect that the sizes are actually the number of characters that will fit in the console window (cols and rows) for the maximum-size console window as specified by the TRUE in the second parameter for GetConsoleFontInfo. See the documentation for the GetCurrentConsoleFont function here.
Well Microsoft, here's another nice mess you've gotten us into.

jj2007

Nice code, thanks :t

Unfortunately, GetConsoleFontInfo is not very helpful - it just returns the font size. Finding out which one is Lucida Console, for printing Unicode, would be a lot more useful...

qWord

With a few modification it also works on Win7, x64:
;==============================================================================
    include \masm32\include\masm32rt.inc
;==============================================================================
CONSOLE_FONT_INFO struct
    nFont      DWORD ?
    dwFontSize COORD <>
CONSOLE_FONT_INFO ends

GETCONSOLEFONTINFO typedef proto stdcall :DWORD,:DWORD,:DWORD,:DWORD
PGETCONSOLEFONTINFO typedef ptr GETCONSOLEFONTINFO
GETNUMBEROFCONSOLEFONTS typedef proto stdcall
PGETNUMBEROFCONSOLEFONTS typedef ptr GETNUMBEROFCONSOLEFONTS
SETCONSOLEFONT typedef proto stdcall :DWORD,:DWORD
PSETCONSOLEFONT typedef ptr SETCONSOLEFONT
;==============================================================================
    .data?
    hKernel32 HANDLE ?
        hStdOut dd ?
        nFonts  dd ?
    GetConsoleFontInfo PGETCONSOLEFONTINFO ?
    GetNumberOfConsoleFonts PGETNUMBEROFCONSOLEFONTS ?
    SetConsoleFont PSETCONSOLEFONT ?
    .code
;==============================================================================
start:
;==============================================================================
    fnx hKernel32 = GetModuleHandle,"kernel32.dll"
    fnx GetConsoleFontInfo = GetProcAddress,hKernel32,"GetConsoleFontInfo"
    fnx GetNumberOfConsoleFonts = GetProcAddress,hKernel32,"GetNumberOfConsoleFonts"
    fnx SetConsoleFont = GetProcAddress,hKernel32,"SetConsoleFont"
   
    .if !GetConsoleFontInfo
    printf("can not locate GetConsoleFontInfo\n")
    exit
    .endif
   
    .if !GetNumberOfConsoleFonts
    printf("can not locate GetNumberOfConsoleFonts\n")
    exit
    .endif
    .if !SetConsoleFont
    printf("can not locate SetConsoleFont\n")
    exit
    .endif
   
    invoke GetStdHandle, STD_OUTPUT_HANDLE
    mov hStdOut, eax

    invoke GetNumberOfConsoleFonts
    mov nFonts, eax
    printf("%d\n",nFonts)

    mov eax, nFonts
    imul eax, SIZEOF CONSOLE_FONT_INFO
    mov esi, alloc(eax)

    invoke GetCurrentConsoleFont, hStdOut, TRUE, esi
    printf("%d\n",eax)

    printf("%d\t", [esi].CONSOLE_FONT_INFO.nFont)
    movzx eax, [esi].CONSOLE_FONT_INFO.dwFontSize.x
    printf("%d\t",eax)
    movzx eax, [esi].CONSOLE_FONT_INFO.dwFontSize.y
    printf("%d\n",eax)

    invoke SetConsoleFont, hStdOut, 0
    printf("%d\n",eax)

    invoke GetCurrentConsoleFont, hStdOut, TRUE, esi
    printf("%d\n",eax)

    printf("%d\t", [esi].CONSOLE_FONT_INFO.nFont)
    movzx eax, [esi].CONSOLE_FONT_INFO.dwFontSize.x
    printf("%d\t",eax)
    movzx eax, [esi].CONSOLE_FONT_INFO.dwFontSize.y
    printf("%d\n\n",eax)

    invoke GetConsoleFontInfo, hStdOut, TRUE, nFonts, esi
    xor ebx, ebx
    .WHILE ebx < nFonts
        printf("%d\t", [esi+ebx*8].CONSOLE_FONT_INFO.nFont)
        movzx eax, [esi+ebx*8].CONSOLE_FONT_INFO.dwFontSize.x
        printf("%d\t",eax)
        movzx eax, [esi+ebx*8].CONSOLE_FONT_INFO.dwFontSize.y
        printf("%d\n",eax)
        inc ebx
    .ENDW
    printf("\n")

    xor ebx, ebx
    .WHILE ebx < nFonts
        invoke SetConsoleFont, hStdOut, ebx
        invoke Sleep, 3000
        inc ebx
    .ENDW

    invoke SetConsoleFont, hStdOut, 0
    printf("%d\n\n",eax)

    free esi
    inkey
    exit
;==============================================================================
end start
MREAL macros - when you need floating point arithmetic while assembling!

MichaelW

There is a documented function here that can return more information on the font, but unfortunately it's Vista or later.

By extending the display delay, or waiting on a key press, you can examine the console properties to determine which font and font size is being used. My few attempts to do this within the 3-second delay all showed Lucida Console.
Well Microsoft, here's another nice mess you've gotten us into.