News:

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

Main Menu

Question about a fonts in the console application

Started by Mikl__, February 12, 2016, 06:06:09 PM

Previous topic - Next topic

Mikl__

Why the program returns existence of 11 "Terminal" fonts in topic Changing the font and the font size of a console via API
And function GetNumberOfConsoleFonts in topic SetConsoleFont, Etc returns existence of 10?
Why in topic "Changing the font and the font size of a console via API" two fonts have same widht and height 12x8 or it is same font?
Why widht and height of fonts in both topics is not same?

nFonts|CONSOLE_FONT_INFO          |Fonts size via EnumFontFamiliesEx in LOGFONT structure ptr
      |.dwFontSize.x|.dwFontSize.y|LOGFONT.lfWidth x LOGFONT.lfHeight
________________________________________________________
0 80     |50           |4x6      50/4=12,5     80/6=13,33
1 20     |37           |16x8     37/16=2,3125  20/8=2,5
2 53     |33           |6x9      53/9=5,89     33/6=5,5
3 40     |33           |8x9      33/8=4,125    40/9=4,4
4 64     |25           |5x12     64/12=5,33    25/5=5
5 45     |25           |7x12     45/12=3,75    25/7=3,57
6 40     |25           |8x12     40/12=3,33    25/8=3,125
7 20     |25           |16x12    25/16=1,5625  20/16=1,25
8 26     |18           |12x16    26/16=1,625   18/12=1,5
9 32     |16           |10x18    32/18=1,78    16/10=1,6

dedndave

i can't tell you why
however, i can tell you how i handled it in an older program...

i created a list, including width, then height
i sorted that list by width, then by height
i removed duplicates from the list

it may be that there are 2 different versions of 8x12 - and the OS selects the one appropriate for your display mode and/or hardware

earlier in that same topic...

http://masm32.com/board/index.php?topic=1108.msg10456#msg10456

dedndave

now i remember that i modifed the code to a simpler method....

in the enumeration callback function,
check to see if the new width/height is already in the list before adding it   :t

Mikl__

dedndave
how to move from values returned function EnumFontFamiliesEx to values of CONSOLE_FONT_INFO ?
4x6 --> 50/80 ?
Console Font with INDEX=0    6/4=1.5   80/50=2.67    2.67/1.5=1.78
Console Font with INDEX=1    (8/16)*1.78=0.89=20/22
Console Font with INDEX=2    (9/6)*1.78=2.67 <> 53/33=1.6 ?


dedndave

ok - i understand the question
but, i don't understand your intent - lol

as i recall, the CONSOLE_FONT_INFO structure doesn't seem to have a lot of practical use
you can use the structure with GetCurrentConsoleFont (fills the structure)
that fills in the nIndex value, that can then be used with GetConsoleFontSize to get dimensions
but this only seems to apply to the current console font
i don't see what other use the nIndex value has

ultimately, you want to get the available fonts and select one - or let the user select one from a list
i suppose you could insert index numbers (0,1,...) into GetConsoleFontSize to create a list (never tried that)

what i did was use EnumFontFamiliesEx....
        INVOKE  GetDC,NULL
        mov     edx,offset lf
        push    eax                                          ;ReleaseDC:hDC
        mov dword ptr [edx].LOGFONT.lfFaceName,6D726554h     ;'Term'
        mov dword ptr [edx].LOGFONT.lfFaceName+4,6C616E69h   ;'inal'
        mov byte ptr [edx].LOGFONT.lfFaceName+8,0
        mov byte ptr [edx].LOGFONT.lfCharSet,OEM_CHARSET     ;EQU 255
        INVOKE  EnumFontFamiliesEx,eax,edx,EnumFntCB,0,0
        push    NULL                                         ;ReleaseDC:hWnd
        CALL    ReleaseDC


EnumFntCB is the callback routine
by specifying Terminal fonts with OEM_CHARSET, you get the fonts that are available for the console

once the user has selected a size, you want to create the font and store the handle
        INVOKE  GetStockObject,OEM_FIXED_FONT
        INVOKE  GetObject,eax,sizeof LOGFONT,offset lf
        mov     edx,offset lf
        mov     eax,cg.h.CellSize                 ;horz cell size selected by user
        mov     ecx,cg.v.CellSize                 ;vert cell size selected by user
        mov     [edx].LOGFONT.lfWidth,eax
        mov     [edx].LOGFONT.lfHeight,ecx
        INVOKE  CreateFontIndirect,edx
        mov     hFont,eax


the first 2 lines are used to fill the LOGFONT structure with valid values
you want to DeleteObject if there was a previosly selected hFont

the point is - i don't see where an nIndex value is of much use, here

dedndave

ok - i see where you are headed   :biggrin:

my program was a GUI app that used console fonts
your program is probably a console app using SetCurrentConsoleFontEx
for that, you need an nIndex value

i guess i would step through the nIndex values (0,1,...) and call GetConsoleFontSize rather than enumerating fonts
hopefully, GetConsoleFontSize fails when you get to an invalid index number   :redface:

from past experience, i try not to get too fancy with console apps
the console window is a little buggish - if i want to get fancy, i go with a GUI app

Mikl__

Hi, dedndave!
I solved it!
font height = 300/value in CONSOLE_FONT_INFO.dwFontSize.y
font width = 640/value in CONSOLE_FONT_INFO.dwFontSize.x

dedndave

are you sure 300 and 640 should be constants ?   :biggrin:

Mikl__

Hi, dedndave!
Yes, I'm sure
bat-filecls
set masm_path=c:\masm32
set filename=%1
del %filename%.exe
%masm_path%\bin\ml /c /Cp /Gz /I%masm_path%\include /coff /nologo %filename%.asm  || exit
%masm_path%\bin\Link /SUBSYSTEM:CONSOLE /LIBPATH:%masm_path%\lib /NOLOGO %filename%.obj
del %filename%.obj
asm-file; masm windows console #
.686
.model flat
include windows.inc
includelib kernel32.lib
includelib user32.lib
includelib gdi32.lib
includelib msvcrt.lib
extern _imp__AllocConsole@0:dword
extern _imp__CloseHandle@4:dword
extern _imp__ExitProcess@4:dword
extern _imp__FreeConsole@0:dword
extern _imp__FreeConsole@0:dword
extern _imp__GetStdHandle@4:dword
extern _imp__GetLargestConsoleWindowSize@4:dword
extern _imp__GetProcessHeap@0:dword
extern _imp__GetConsoleCursorInfo@8:dword
extern _imp__GetModuleHandleA@4:dword
extern _imp__GetProcAddress@8:dword
extern _imp__GetConsoleScreenBufferInfo@8:dword
extern _imp__GlobalAlloc@8:dword
extern _imp__GlobalFree@4:dword
extern _imp__HeapAlloc@12:dword
extern _imp__HeapFree@12:dword
extern _imp__ReadConsoleInputA@16:dword
extern _imp__ReadConsoleOutputW@20:dword
extern _imp__SetConsoleWindowInfo@12:dword
extern _imp__SetConsoleTitleA@4:dword
extern _imp__SetConsoleScreenBufferSize@8:dword
extern _imp__SetConsoleCursorPosition@8:dword
extern _imp__SetConsoleTextAttribute@8:dword
extern _imp__SetConsoleCursorInfo@8:dword
extern _imp__sprintf:dword
extern _imp__WriteFile@20:dword
extern _imp__WriteConsoleA@20:dword
extern _imp__WriteConsoleOutputW@20:dword
MAXSCREENX = 80
MAXSCREENY = 25
MAX_STACK  = 1000h
TOP_MENU   = 5
RIGHT_MENU = 34
COLS_MENU  = 17
;----------------------------------------------
CONSOLE_FONT_INFO struct
index dd ?
dwFontSize COORD <>
CONSOLE_FONT_INFO ends
;----------------------------------------------
.data
fmt db 'font size %d x %d',0
hOut dd ?
ConsoleTitle db 'Enum and set console fonts',0
Str1 db 'For move into menu press Up or Down Arrow key',13,10,\
'For set selected font press Enter',13,10,\
'For exit press ESC or CTRL+C or CTRL+Break'
Str2 db "kernel32.dll",0
Str3 db "SetConsoleFont",0
Str4 db "GetNumberOfConsoleFonts",0
Str5 db "GetConsoleFontInfo",0
hHeap dd ?
lpStack dd ?
dwStackTop dd -1

.code
_main proc
local hIn:dword
local MOUSE_KEY:INPUT_RECORD
local result:dword
local ConsoleWindow:SMALL_RECT
local cci:CONSOLE_CURSOR_INFO
local hMem:dword
local hKernel:dword
local buffer[40]:byte
local CurrentConsoleFont:dword
local GetNumberOfConsoleFonts:dword
local SetConsoleFont:dword
local GetConsoleFontInfo:dword
local n:dword
local count:dword
local new_op:dword
local prev_op:dword
local coord:COORD

xor ebx,ebx
mov prev_op,1
mov new_op,1
mov coord,TOP_MENU*10000h+RIGHT_MENU

push offset Str2
call _imp__GetModuleHandleA@4
mov hKernel,eax
        push offset Str3
push eax
call _imp__GetProcAddress@8
mov SetConsoleFont,eax
        push offset Str4
push hKernel
call _imp__GetProcAddress@8
mov GetNumberOfConsoleFonts,eax
        push offset Str5
push hKernel
call _imp__GetProcAddress@8
mov GetConsoleFontInfo,eax

call _imp__GetProcessHeap@0
mov hHeap, eax
push 4*MAX_STACK ; dwBytes
push HEAP_ZERO_MEMORY ; dwFlags
push eax ; hHeap
call _imp__HeapAlloc@12
mov lpStack, eax
        call _imp__FreeConsole@0
        call _imp__AllocConsole@0
push STD_INPUT_HANDLE
        call _imp__GetStdHandle@4
        mov hIn,eax
        push STD_OUTPUT_HANDLE
call _imp__GetStdHandle@4
mov hOut,eax
        push eax ;hOut
call _imp__GetLargestConsoleWindowSize@4
; eax return in 31-16 bits: dwCoord.y
;               15-00 bits: dwCoord.x

        lea edi,ConsoleWindow
mov [edi],ebx ; ConsoleWindow.Left = 0
                        ; ConsoleWindow.Top = 0
sub ax, MAXSCREENX
sbb edx, edx
and ax, dx
add ax, MAXSCREENX-1
assume edi: ptr SMALL_RECT
mov [edi].Right,ax

shr eax, 16
sub eax, MAXSCREENY
sbb edx, edx
and eax, edx
add eax, MAXSCREENY-1
mov [edi].Bottom,ax
assume edi:nothing

push edi ; lpConsoleWindow
push TRUE ; bAbsolute
push hOut ; hConsoleOutput
call _imp__SetConsoleWindowInfo@12

push MAXSCREENY*10000h+MAXSCREENX;dwCoord
push hOut ; hConsoleOutput
call _imp__SetConsoleScreenBufferSize@8;establish the new size of a window of the console

push offset ConsoleTitle
call _imp__SetConsoleTitleA@4
;cursor hide----------------------------------------
lea edi,cci
push edi ; lpConsoleCursorInfo
push hOut ; hConsoleOutput
call _imp__GetConsoleCursorInfo@8
assume  edi: ptr CONSOLE_CURSOR_INFO
mov [edi].bVisible,FALSE
assume edi: nothing
push edi ; lpConsoleCursorInfo
push hOut ; hConsoleOutput
call _imp__SetConsoleCursorInfo@8
;------------------------------------------------------
        push ebx ;0
lea ecx,result
        push ecx ;&result
        push sizeof Str1
push offset Str1     
push hOut
        call _imp__WriteConsoleA@20
;---------------------------------------------------
call GetNumberOfConsoleFonts
mov count,eax
shl eax,3
push eax      ; eax = count * sizeof CONSOLE_FONT_INFO
push GMEM_FIXED or GMEM_ZEROINIT
call _imp__GlobalAlloc@8
mov hMem,eax
push eax
push count
push TRUE
push hOut
call GetConsoleFontInfo
;Draw menu-----------------------------------------------------------
push BACKGROUND_INTENSITY ; wAttributes
push hOut ; hConsoleOutput
call _imp__SetConsoleTextAttribute@8
mov eax,count
add eax,4
push eax ;rows   
push COLS_MENU+4 ;cols   
push TOP_MENU-2 ;y
push RIGHT_MENU-2 ;x
call draw

push BACKGROUND_BLUE or BACKGROUND_GREEN or BACKGROUND_RED; wAttributes
push hOut ; hConsoleOutput
call _imp__SetConsoleTextAttribute@8
        mov eax,count
add eax,2
push eax ;rows   
push COLS_MENU+2 ;cols   
push TOP_MENU-1 ;y
push RIGHT_MENU-1 ;x
call draw
;fill memu----------------------------------------------------------
mov ecx,count
mov esi,hMem
@@: push ecx
assume esi: ptr CONSOLE_FONT_INFO
mov eax,300
cdq
movzx ecx,[esi].dwFontSize.y
div ecx
        push eax ;font width
mov eax,640
cdq
movzx ecx,[esi].dwFontSize.x
div ecx
push eax              ;font height
push offset fmt
lea eax,buffer
push eax
        call _imp__sprintf
        push coord
push hOut
mov n,eax
call _imp__SetConsoleCursorPosition@8;establish a cursor position
        push ebx            ; lpOverlapped
lea eax,result
        push eax ; lpNumberOfBytesWritten
push n        ; nNumberOfBytesToWrite
lea eax,buffer
        push eax
push hOut
        call _imp__WriteConsoleA@20 ;display a line of symbols
inc coord.y
assume esi:nothing
add esi,sizeof CONSOLE_FONT_INFO
add esp,4*4
pop ecx
loop @b
push hMem
call _imp__GlobalFree@4
; Select first label
push TOP_MENU    ;y
call invert
; Keyboard read loop------------------------------------------------
@@:     lea eax,result
        push eax
push 1
lea edi,MOUSE_KEY
assume edi: ptr INPUT_RECORD
push edi
push hIn
call _imp__ReadConsoleInputA@16
cmp [edi].EventType,MOUSE_EVENT
je @b
cmp [edi].EventType,KEY_EVENT
jne @b
        cmp [edi].KeyEvent.bKeyDown,0
jne @b
        cmp [edi].KeyEvent.wVirtualKeyCode,VK_UP
        je vkUP
        cmp [edi].KeyEvent.wVirtualKeyCode,VK_DOWN
        je vkDOWN
        cmp [edi].KeyEvent.wVirtualKeyCode,VK_RETURN
        je vkRETURN
cmp [edi].KeyEvent.wVirtualKeyCode,VK_ESCAPE
assume edi: nothing
jne @b
exit:   push lpStack ; lpMem
push 0 ; dwFlags
push hHeap ; hHeap
call _imp__HeapFree@12
        push hOut ; hObject
call _imp__CloseHandle@4
push hIn ; hObject
call _imp__CloseHandle@4
call _imp__FreeConsole@0
        push ebx
        call _imp__ExitProcess@4
;-----------------------------------------------------     
vkUP:   dec new_op
        jnz     proceed
mov eax,count
        mov new_op,eax
jmp     proceed
vkDOWN: mov eax,count
inc new_op
        cmp new_op,eax
        jbe     proceed
        mov new_op,1
proceed: ; Select new label
        push new_op
        add new_op,TOP_MENU-1
push new_op
        call invert
        pop new_op
        add prev_op,TOP_MENU-1
push prev_op
        call invert
push new_op
        pop prev_op
        jmp @b
vkRETURN:mov eax,new_op
dec eax
push eax
push hOut
call dword ptr SetConsoleFont
        jmp @b

_main endp
;--------------------------------------------------------
draw proc x:dword, y:dword, cols:dword, rows:dword

local Csbi:CONSOLE_SCREEN_BUFFER_INFO

lea edx, Csbi
push edx ; lpConsoleScreenBufferInfo
push hOut ; hConsoleOutput
call _imp__GetConsoleScreenBufferInfo@8
push rows
push cols
push y
push x
call save
mov eax,dwStackTop
mov ecx,lpStack
mov edi, [ecx+eax*4]
movzx eax, word ptr cols
mul word ptr rows
mov ecx, eax
@@: mov ax,Csbi.wAttributes
shl eax,16
mov ax," ";char "space"=0x20
stosd
loop @b
push rows
push cols
push y
push x
call load
leave
retn 16
draw endp
;-------------------------------------------------------
load proc x:dword,y:dword,cols:dword,rows:dword

local lpBuffer:dword
local dwBufferCoord:COORD
local dwBufferSize:COORD
local lpWriteRegion:SMALL_RECT

mov dwBufferCoord, 0
mov ax, word ptr cols
mov dwBufferSize.x, ax
mov cx, word ptr rows
mov dwBufferSize.y, cx
dec eax
dec ecx
mov dx,word ptr x
mov lpWriteRegion.Left, dx
add ax, dx
mov lpWriteRegion.Right, ax
mov dx,word ptr y
mov lpWriteRegion.Top, dx
add cx, dx
mov lpWriteRegion.Bottom, cx
mov eax, dwStackTop
mov edx, lpStack

dec dwStackTop
mov ecx,[edx+eax*4]
mov dword ptr [edx+eax*4],0
mov lpBuffer,ecx

lea edx, lpWriteRegion
push edx ; lpWriteRegion
push dwBufferCoord ; dwBufferCoord
push dwBufferSize    ; dwBufferSize
push lpBuffer ; lpBuffer
push hOut ; hConsoleOutput
call _imp__WriteConsoleOutputW@20

push lpBuffer ; lpMem
push 0 ; dwFlags
push hHeap ; hHeap
call _imp__HeapFree@12
leave
retn 10h
load endp
;-------------------------------------------------------
save proc x:dword, y:dword, cols:dword, rows:dword

local lpBuffer:dword
local dwBufferCoord:COORD
local dwBufferSize:COORD
local lpReadRegion:SMALL_RECT

mov lpBuffer,0
mov dword ptr dwBufferCoord.x,0
mov ax,word ptr cols
mov dwBufferSize.x, ax
mov cx,word ptr rows
mov dwBufferSize.y, cx
dec eax
dec ecx
mov dx,word ptr x
mov lpReadRegion.Left,dx
add ax, dx
mov lpReadRegion.Right,ax
mov dx,word ptr y
mov lpReadRegion.Top,dx
add cx, dx
mov lpReadRegion.Bottom,cx
movzx eax,word ptr cols
mul rows
shl eax, 2
add eax, 260
push eax ; dwBytes
push HEAP_ZERO_MEMORY; dwFlags
push hHeap ; hHeap
call _imp__HeapAlloc@12

mov lpBuffer,eax
lea edx, lpReadRegion
push edx ; lpReadRegion
push dword ptr dwBufferCoord.x ; dwBufferCoord
push dword ptr dwBufferSize.x ; dwBufferSize
push eax ; lpBuffer
push hOut ; hConsoleOutput
call _imp__ReadConsoleOutputW@20

inc dwStackTop
mov eax, dwStackTop
mov ecx, lpStack
mov edx, lpBuffer
mov [ecx+eax*4],edx
leave
retn 10h
save endp
;-----------------------------------------------------------
invert proc y:dword

push 1 ;rows
push COLS_MENU ;cols
push y
push RIGHT_MENU ;x
call save
mov eax, dwStackTop
mov ecx, lpStack
mov edi, [ecx+eax*4]
mov esi, edi
mov ecx,COLS_MENU ; cols

@@: lodsd          ;eax=xxABxxxx
ror eax,16 ;eax=xxxxxxAB
ror al,4    ;eax=xxxxxxBA
rol eax,16 ;eax=xxBAxxxx
stosd
loop @b
push 1;rows
push COLS_MENU;cols
push y
push RIGHT_MENU;x
call load
leave
retn 4
invert endp
;-----------------------------------------------------------
end _main