8

How do I change the font in my C++ Windows console app?

It doesn't seem to use the font cmd.exe uses by default (Lucida Console). When I run my app through an existing cmd.exe (typing name.exe) it looks like this: http://dathui.mine.nu/konsol3.png which is entierly correct. But when I run my app seperatly (double-click the .exe) it looks like this: http://dathui.mine.nu/konsol2.png. Same code, two different looks.

So now I wonder how I can change the font so it always looks correctly regardless of how it's run.


EDIT:

Ok, some more information. When I just use this little snippet:

SetConsoleOutputCP(CP_UTF8);
wchar_t s[] = L"èéøÞǽлљΣæča";
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
char* m = new char[bufferSize]; 
WideCharToMultiByte(CP_UTF8, 0, s, -1, m, bufferSize, NULL, NULL);
wprintf(L"%S", m);

it works with the correct font. But in my real application I use WriteConsoleOutput() to print strings instead:

CHAR_INFO* info = new CHAR_INFO[mWidth * mHeight];
for(unsigned int a = 0; a < mWidth*mHeight; ++a) {
    info[a].Char.UnicodeChar = mWorld.getSymbol(mWorldX + (a % mWidth), mWorldY + (a / mWidth));
    info[a].Attributes = mWorld.getColour(mWorldX + (a % mWidth), mWorldY + (a / mWidth));
}
COORD zero;
zero.X = zero.Y = 0;
COORD buffSize;
buffSize.X = mWidth;
buffSize.Y = mHeight;
if(!WriteConsoleOutputW(window, info, buffSize, zero, &rect)) {
    exit(-1);
}

and then it uses the wrong font. I use two different windows, created like this:

mHandleA = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0,
                                     NULL, CONSOLE_TEXTMODE_BUFFER, NULL);

Might I be setting the codepage for just the standard output or something?

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
dutt
  • 7,909
  • 11
  • 52
  • 85
  • Hm ... weird, there is a way to detect console vs double-click with a few exceptional cases. This article is a good start but it does not go far enough: http://www.codeguru.com/cpp/misc/misc/consoleapps/article.php/c15893/ – Hamish Grubijan Dec 17 '09 at 15:03
  • Which compiler you use ? – Sajad Bahmani Dec 17 '09 at 15:09
  • Perhaps trace the startup code - from pre main() - to see what code is actually building the console window itself? I assume that there must be code that is part of your .exe supplied by the compiler / console project that detects if your app is starting in a console already, or if it needs one, in which case creates a console window for you. This is my intuition, not researched fact, but might be verifiable with only a few mins debugging. At which point, you can see the source for that, and see what you may need to do to get access to that console HWND, to set its font differently... – Mordachai Dec 17 '09 at 15:11
  • Ipthnc: sounds like a roundabout way, but thanks for the tip. SjB: Visual Studio 2008 proff. Mordachai: Hm, where could i find the pre-main code? – dutt Dec 17 '09 at 16:02

3 Answers3

4

Windows stores the cmd settings (including the font) in the registry using the exe path as the key. The root key is 'HKEY_CURRENT_USER\Console' so if you take a look in there with regedit you should see several sub-keys named after varous exe's.

To copy the settings of an existing exe, you can export the key to a text file, then edit the file to change the key name to that of your exe, then reimport it.

You can also progmatically modify the registry though i doubt that would take immediate effect w.r.t. to your console window.

jon hanson
  • 8,722
  • 2
  • 37
  • 61
3

You could try the SetCurrentConsoleFontEx() function.

Ferruccio
  • 98,941
  • 38
  • 226
  • 299
  • 1
    You might want to mention GetStdHandle too - http://msdn.microsoft.com/en-us/library/ms683231(VS.85).aspx – Mark Ransom Dec 17 '09 at 15:41
  • iirc that only exists on vista and later, prefer is this is doable on xp as well since alot of people still run it. – dutt Dec 17 '09 at 16:05
  • Strange, they claim you need Vista but also claim you should define _WIN32_WINNT as 0x0500 (Windows 2000) or later. Seems contradictory. – Mark Ransom Dec 17 '09 at 16:32
  • Mark, that's probably just a typo — should have been a 6 instead of a 5. – Rob Kennedy Dec 17 '09 at 18:12
2

For Vista and above, there is SetCurrentConsoleFontEx, as already has been said.

For 2K and XP, there is an undocumented function SetConsoleFont; e.g. read here.

typedef BOOL (WINAPI *FN_SETCONSOLEFONT)(HANDLE, DWORD);
FN_SETCONSOLEFONT SetConsoleFont;
..........
HMODULE hm = GetModuleHandle(_T("KERNEL32.DLL"));
SetConsoleFont = (FN_SETCONSOLEFONT) GetProcAddress(hm, "SetConsoleFont");
// add error checking
..........

SetConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), console_font_index);

Now, console_font_index is an index into console font table, definition of which is unknown. However, console_font_index == 10 is known to identify Lucida Console (a Unicode font). I'm not sure how stable is this value across different OS versions.

UPDATE

After dutt's comment, I've run an experiment on a clean XP SP2 setup.

  • Initially, GetNumberOfConsoleFonts(), indeed, returns 10, and font indices 0..9 specify various raster fonts.

  • After I open a console with Lucida font selected in its properties (just once; I can close it immediately after opening but the effect is the same), suddenly GetNumberOfConsoleFonts() starts to return 12, and indices 10 and 11 select Lucida of different sizes.

So it seems this trick worked for me when I played with it because I always had running at least one console app with Lucida font selected.

Thus, for practical purposes, jon hanson's answer seems better. Besides offering better control, it actually works. :)

Community
  • 1
  • 1
atzz
  • 17,507
  • 3
  • 35
  • 35
  • It does change the font, but GetNumberOfConsoleFonts() return 10 for me and I've tried 0-9 (and 10,11,...) but none of those were Lucida Console. So now the question is, how do i use this to change to Lucida console? :) – dutt Dec 17 '09 at 19:48