Page 1 of 1

[How-To] Get or set the console font size and font name (PowerShell hybrid)

Posted: 31 Jul 2021 17:22
by aGerman
Carlos, penpen, me, and probably others have been working for a long time to do this.
Latest attempts that I recall can be found in this thread: viewtopic.php?f=3&t=5617

I'd like to offer a pure script solution that should work for supported ttf fonts in console windows on Vista onwards. For raster fonts use font name Terminal. The code implements the %setfont% macro and shows how to use it. All font updates are volatile and only effective in the current console window. Default settings are untouched.

Code: Select all

@echo off &setlocal

:: initialize the %setfont% macro
call :init_setfont

echo - current font:
%setfont%
pause

echo - cache the current font in a temporary file
:: the parentheses are critical for the redirection
:: capturing in a FOR /F loop doesn't work and thus, the temporary file is necessary in this case
>"%temp%\setfont.tmp~" (%setfont%)
pause

echo - 14 (same font name)
%setfont% 14
pause

echo - 20 Lucida Console
%setfont% 20 Lucida Console
pause

echo - (same font size) Consolas
%setfont% 0 Consolas
pause

echo - 16 Consolas
%setfont% 16 Consolas
pause

echo - reset
for /f "usebackq delims=" %%i in ("%temp%\setfont.tmp~") do %setfont% %%i
del "%temp%\setfont.tmp~"
pause

exit /b


:init_setfont
:: - BRIEF -
::  Get or set the console font size and font name.
:: - SYNTAX -
::  %setfont% [fontSize [fontName]]
::    fontSize   Size of the font. (Can be 0 to preserve the size.)
::    fontName   Name of the font. (Can be omitted to preserve the name.)
:: - EXAMPLES -
::  Output the current console font size and font name:
::    %setfont%
::  Set the console font size to 14 and the font name to Lucida Console:
::    %setfont% 14 Lucida Console
setlocal DisableDelayedExpansion
set setfont=for /l %%# in (1 1 2) do if %%#==2 (^
%=% for /f "tokens=1,2*" %%- in ("? ^^!arg^^!") do endlocal^&powershell.exe -nop -ep Bypass -c ^"Add-Type '^
%===% using System;^
%===% using System.Runtime.InteropServices;^
%===% [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)] public struct FontInfo{^
%=====% public int objSize;^
%=====% public int nFont;^
%=====% public short fontSizeX;^
%=====% public short fontSizeY;^
%=====% public int fontFamily;^
%=====% public int fontWeight;^
%=====% [MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)] public string faceName;}^
%===% public class WApi{^
%=====% [DllImport(\"kernel32.dll\")] public static extern IntPtr CreateFile(string name,int acc,int share,IntPtr sec,int how,int flags,IntPtr tmplt);^
%=====% [DllImport(\"kernel32.dll\")] public static extern void GetCurrentConsoleFontEx(IntPtr hOut,int maxWnd,ref FontInfo info);^
%=====% [DllImport(\"kernel32.dll\")] public static extern void SetCurrentConsoleFontEx(IntPtr hOut,int maxWnd,ref FontInfo info);^
%=====% [DllImport(\"kernel32.dll\")] public static extern void CloseHandle(IntPtr handle);}';^
%=% $hOut=[WApi]::CreateFile('CONOUT$',-1073741824,2,[IntPtr]::Zero,3,0,[IntPtr]::Zero);^
%=% $fInf=New-Object FontInfo;^
%=% $fInf.objSize=84;^
%=% [WApi]::GetCurrentConsoleFontEx($hOut,0,[ref]$fInf);^
%=% If('%%~.'){^
%===% $fInf.nFont=0; $fInf.fontSizeX=0; $fInf.fontFamily=0; $fInf.fontWeight=0;^
%===% If([Int16]'%%~.' -gt 0){$fInf.fontSizeY=[Int16]'%%~.'}^
%===% If('%%~/'){$fInf.faceName='%%~/'}^
%===% [WApi]::SetCurrentConsoleFontEx($hOut,0,[ref]$fInf);}^
%=% Else{(''+$fInf.fontSizeY+' '+$fInf.faceName)}^
%=% [WApi]::CloseHandle($hOut);^") else setlocal EnableDelayedExpansion^&set arg=
endlocal &set "setfont=%setfont%"
if !!# neq # set "setfont=%setfont:^^!=!%"
exit /b
Magic numbers used:

$hOut=[WApi]::CreateFile('CONOUT$',-1073741824,2,[IntPtr]::Zero,3,0,[IntPtr]::Zero);
-1073741824 is for GENERIC_READ | GENERIC_WRITE
2 is for FILE_SHARE_WRITE
3 is for OPEN_EXISTING

$fInf.objSize=84;
84 is the size of the FontInfo structure in bytes

Steffen

Re: [How-To] Get or set the console font size and font name (PowerShell hybrid)

Posted: 17 Sep 2021 13:15
by IcarusLives
Hi! I love this, and I'd love to use it. Trying to tinker with it, but I don't know Powershell! Can you help me?

Typically I run my scripts in raster fonts 8x8. It's nice to have a nice square character to draw shapes and run animation.

Using %setfont%, I haven't been able to achieve it. I can get 4x6, 6x8, and then it seems to skip over 8x8. Is it possible to make this happen? Or even better, a smaller font size such as 1x1, 2x2 etc?

Sorry to bother, and thanks in advanced!

Re: [How-To] Get or set the console font size and font name (PowerShell hybrid)

Posted: 17 Sep 2021 13:33
by T3RRY
IcarusLives wrote:
17 Sep 2021 13:15
Hi! I love this, and I'd love to use it. Trying to tinker with it, but I don't know Powershell! Can you help me?

Typically I run my scripts in raster fonts 8x8. It's nice to have a nice square character to draw shapes and run animation.

Using %setfont%, I haven't been able to achieve it. I can get 4x6, 6x8, and then it seems to skip over 8x8. Is it possible to make this happen? Or even better, a smaller font size such as 1x1, 2x2 etc?

Sorry to bother, and thanks in advanced!
Have you tried the below?

Code: Select all

%setfont% 1 Raster Fonts

Re: [How-To] Get or set the console font size and font name (PowerShell hybrid)

Posted: 17 Sep 2021 14:03
by aGerman
aGerman wrote:
31 Jul 2021 17:22
For raster fonts use font name Terminal.
However, since all other fonts do not support the definition of the character width, the current code only supports the definition of the height. You can easily patch it for quadratic sizes though.

Code: Select all

%===% If([Int16]'%%~.' -gt 0){$fInf.fontSizeX=[Int16]'%%~.';$fInf.fontSizeY=[Int16]'%%~.'}^
IcarusLives wrote:
17 Sep 2021 13:15
Or even better, a smaller font size such as 1x1, 2x2 etc?
Not without having a raster font with 1 or 2 pixels size installed.
viewtopic.php?f=3&t=6254&p=39933

Steffen