by Michael S. Kaplan, published on 2011/09/22 07:01 -04:00, original URI: http://blogs.msdn.com/b/michkap/archive/2011/09/22/10215125.aspx
It was not quite a year ago, in Myth busting in the console, where Myth #12 was:
Myth #12: You can't change the setting of whether a console window is using a TrueType font.
This myth too is quite untrue.
I have used a few console API functions and that IsConsoleFontTrueType function from this blog to change the font within a console window to a TrueType font, from code running in the console window.
This is something I would never recommend in production code, mind you; I only did it because someone told me it wasn't possible and I was sure she was mistaken.
The impact of the accomplishment was interesting, mind you; she and I dated for about a month after that. ;-)
And the story there may be worthy of its own dedicated myth-busting blog, along with the code itself. If people are interested, I mean. Let me know....
I've had some people ask for the code, so I thought I would oblige...
Others wanted top hear the story about the relationship. Well let's just say it only lasted for a month. Like this code, it really was not something that worked in production!
Anyway, here is the code I wrote at the time:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Test {
public static class ConsoleStuff {
public static void Main() {
SwitchToAnyTrueTypeFont();
}
internal static bool SwitchToAnyTrueTypeFont() {
IntPtr stdout = GetStdHandle(STD_OUTPUT_HANDLE);
uint nFont = 0;
// First see if we are truetype already
if (IsConsoleFontTrueType(stdout)) {
return true;
}
// Get the current index to set it back if no font is found.
CONSOLE_FONT_INFO cfi = new CONSOLE_FONT_INFO();
if (GetCurrentConsoleFont(stdout, false, ref cfi)) {
nFont = cfi.Index;
}
CONSOLE_FONT_INFO[] fonts = new CONSOLE_FONT_INFO[GetNumberOfConsoleFonts()];
if (fonts.Length > 0) {
GetConsoleFontInfo(stdout, false, (uint)fonts.Length, fonts);
}
//
// Try to set each font until a TrueType one is found. This
// part is hacky, but AFAIK there is no way to get TrueType
// status on any fonts other than the current one.
//
for (int iFont = 0; iFont < fonts.Length; iFont++) {
if (SetConsoleFont(stdout, fonts[iFont].Index)) {
if (IsConsoleFontTrueType(stdout)) {
return true;
}
}
}
// Could not find a font, so give up
SetConsoleFont(stdout, nFont);
return false;
}
internal static bool IsConsoleFontTrueType(IntPtr std) {
CONSOLE_FONT_INFO_EX cfie = new CONSOLE_FONT_INFO_EX();
cfie.cbSize = (uint)Marshal.SizeOf(cfie);
if (GetCurrentConsoleFontEx(std, false, ref cfie)) {
return ((cfie.FontFamily & TMPF_TRUETYPE) == TMPF_TRUETYPE);
}
return false;
}
internal const int TMPF_TRUETYPE = 0x4;
internal const int LF_FACESIZE = 32;
internal const int STD_OUTPUT_HANDLE = -11; // Handle to the standard output device.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct CONSOLE_FONT_INFO {
internal uint Index;
internal ushort dwFontSizeX;
internal ushort dwFontSizeY;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
internal struct CONSOLE_FONT_INFO_EX {
internal uint cbSize;
internal uint nFont;
internal ushort dwFontSizeX;
internal ushort dwFontSizeY;
internal int FontFamily;
internal int FontWeight;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = LF_FACESIZE)]
internal string FaceName;
}
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern bool GetCurrentConsoleFontEx(
IntPtr hConsoleOutput,
bool bMaximumWindow,
ref CONSOLE_FONT_INFO_EX lpConsoleCurrentFontEx);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern bool GetCurrentConsoleFont(
IntPtr hConsoleOutput,
bool bMaximumWindow,
ref CONSOLE_FONT_INFO lpConsoleCurrentFont);
[DllImport("kernel32")]
private extern static bool SetConsoleFont(IntPtr hOutput, uint index);
[DllImport("Kernel32.DLL", ExactSpelling = true)]
internal static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32", ExactSpelling = true)]
private static extern bool GetConsoleFontInfo(
IntPtr hOutput,
bool bMaximize,
uint count,
[MarshalAs(UnmanagedType.LPArray), Out] CONSOLE_FONT_INFO[] fonts);
[DllImport("kernel32", ExactSpelling = true)]
internal static extern uint GetNumberOfConsoleFonts();
}
}
You get the point. Just don't get crazy on on it....
Simon Buchan on 22 Sep 2011 6:20 PM:
I'm assuming GetNumberOfConsoleFonts(), SetConsoleFont() is using Software\Microsoft\Windows NT\CurrentVersion\Console\{Raster,TrueType}Font?
I'm just glad Windows 7 made Consolas the default.