Recent

Author Topic: Console program - how to set font size (conflict with crt unit)?  (Read 6651 times)

dculp

  • Full Member
  • ***
  • Posts: 129
I'm trying to set the font size in a Windows console program. At the same time I want to be able to output hi-order characters (between 127 - 255) from codepage 437 (https://en.wikipedia.org/wiki/Code_page_437#Internationalization).

Corrected - The following works fine if "uses crt" is NOT included ("crt unit not used.jpg" shows the desired result with Greek characters). However if "uses crt" is included then the font characters aren't correct (appear to be from another codepage - see "crt unit used.jpg"). Note: the images show that the output codepage and the system codepage are the same in both cases. (The crt unit is not needed for this demo program but would be needed for the actual program.)

I don't want to use unicode as this may cause unforeseen problems (for example, in a wordwrap unit).

Note: below are two separate Set_default_codepage units. These are identical except that the first has mostly been stripped of comments. However, the last (fully commented) may be more informative.

Lazarus 1.6, FPC 3.0.0

Thanks,
Don C.

Code: Pascal  [Select][+][-]
  1. program Console_fontsize;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6. //   crt,
  7.    Set_default_codepage;
  8.  
  9. var
  10.    i: byte;
  11.    Fontsize: smallint;
  12.  
  13. begin
  14. Fontsize:= 18;
  15. Set_console_fontsize(Fontsize); // Set_default_codepage.pas
  16.  
  17. Writeln('Console output codepage: ', GetTextCodePage(Output));
  18. Writeln('System codepage: ', DefaultSystemCodePage);
  19. for i:= 224 to 238 do write(chr(i), ' '); // test - Greek characters
  20. readln;
  21. end.
  22.  

============ Comments stripped out ============
Code: Pascal  [Select][+][-]
  1. unit Set_default_codepage;
  2.  
  3. {http://wiki.freepascal.org/Lazarus_with_FPC3.0_without_UTF-8_mode}
  4.  
  5. interface
  6.  
  7. procedure Set_console_fontsize(Fontsize: smallint {short});
  8.  
  9. implementation
  10.  
  11. uses
  12.   Windows;
  13.  
  14. const
  15.   LF_FACESIZE = 32;
  16.  
  17. type
  18.   CONSOLE_FONT_INFOEX = record
  19.     cbSize      : ULONG;
  20.     nFont       : DWORD;
  21.     dwFontSizeX : SHORT;
  22.     dwFontSizeY : SHORT;
  23.     FontFamily  : UINT;
  24.     FontWeight  : UINT;
  25.     FaceName    : array [0..LF_FACESIZE-1] of WCHAR;
  26.   end;
  27.  
  28. function SetCurrentConsoleFontEx(hConsoleOutput: HANDLE; bMaximumWindow: BOOL; var CONSOLE_FONT_INFOEX): BOOL;
  29.    stdcall; external 'kernel32.dll' name 'SetCurrentConsoleFontEx';
  30.  
  31. {***************************************************}
  32. procedure Set_console_fontsize(Fontsize: smallint {short});
  33.  
  34. const // choose one
  35.    Codepage: smallint = 437;
  36. // Codepage: smallint = 1252;
  37.  
  38. var
  39.   New_CONSOLE_FONT_INFOEX : CONSOLE_FONT_INFOEX;
  40.   Rslt: boolean;
  41.  
  42. begin
  43. SetConsoleOutputCP(Codepage);
  44. SetTextCodepage(Output, Codepage);
  45.  
  46. FillChar(New_CONSOLE_FONT_INFOEX, SizeOf(CONSOLE_FONT_INFOEX), 0);
  47.  
  48. with New_CONSOLE_FONT_INFOEX do
  49.    begin
  50.    cbSize := SizeOf(CONSOLE_FONT_INFOEX);
  51.    nFont:= 0;
  52.    dwFontSizeX:= 0;
  53.    dwFontSizeY:= Fontsize;
  54.    FontFamily := FF_DONTCARE;
  55.    FaceName := 'Lucida Console';
  56.    FontWeight:= 400 {FW_NORMAL};
  57.    end;
  58.  
  59. Rslt:= SetCurrentConsoleFontEx(StdOutputHandle,false,New_CONSOLE_FONT_INFOEX);
  60. writeln('SetCurrentConsoleFontEx = ', Rslt);
  61. end;
  62. {#########################################}
  63.  
  64. end.
  65.  

============ Fully commented ============
Code: Pascal  [Select][+][-]
  1. unit Set_default_codepage;
  2.  
  3. {Originally setdefaultcodepages
  4. http://wiki.freepascal.org/Lazarus_with_FPC3.0_without_UTF-8_mode}
  5.  
  6. {At cmd command line, can see active code page with "chcp";
  7. can set active code page with "chcp nnn"}
  8.  
  9. {https://msdn.microsoft.com/en-us/library/windows/desktop/dd317752(v=vs.85).aspx
  10. For both Windows code pages and OEM code pages, the code values 0x00 through 0x7F
  11. correspond to the 7-bit ASCII character set. Code values 0x00 through 0x19 and 0x7F
  12. always represent standardized control characters and 0x20 through 0x7E represent
  13. standardized displayable characters.
  14. Characters represented by the remaining codes, 0x80 through 0xff, vary among character sets.
  15. Each character set includes different special characters, typically customized
  16. for a language or group of languages.
  17. Windows code page 1252 and OEM code page 437 are generally used in the United States.
  18.  
  19. All codepages - https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx
  20.  
  21. https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/
  22. }
  23.  
  24. interface
  25.  
  26. procedure Set_console_fontsize(Fontsize: smallint {short});
  27.    {short - see https://msdn.microsoft.com/en-us/library/s3f49ktz.aspx
  28.    smallint - see https://www.freepascal.org/docs-html/ref/refsu4.html}
  29.  
  30. implementation
  31.  
  32. uses
  33.   Windows; // for types used in CONSOLE_FONT_INFOEX and function SetCurrentConsoleFontEx
  34.  
  35. const
  36.   LF_FACESIZE = 32;
  37.  
  38. type
  39.   CONSOLE_FONT_INFOEX = record
  40.     // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682069(v=vs.85).aspx
  41.     cbSize      : ULONG;
  42.     nFont       : DWORD; // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683165(v=vs.85).aspx
  43.     dwFontSizeX : SHORT;
  44.     dwFontSizeY : SHORT;
  45.     FontFamily  : UINT;
  46.     FontWeight  : UINT; // range from 100 to 1000, in multiples of 100
  47.     FaceName    : array [0..LF_FACESIZE-1] of WCHAR;
  48.   end;
  49.  
  50. { Only supported in Vista and onwards!}
  51.  
  52. function SetCurrentConsoleFontEx(hConsoleOutput: HANDLE; bMaximumWindow: BOOL; var CONSOLE_FONT_INFOEX): BOOL;
  53.    stdcall; external 'kernel32.dll' name 'SetCurrentConsoleFontEx';
  54.  
  55. {***************************************************}
  56. procedure Set_console_fontsize(Fontsize: smallint {short});
  57.  
  58. const // choose one
  59.         Codepage: smallint = 437; // OEM United States - see https://en.wikipedia.org/wiki/Code_page_437#Internationalization
  60.       {Font size & hi-chars are correct but only if not "uses crt"}
  61. // Codepage: integer = CP_UTF8; // original (= 65001; see D:\Lazarus\fpc\3.0.0\source\rtl\win\wininc\redef.inc)
  62.       {Font size is correct but hi-char output is all boxes}
  63. // Codepage: smallint = 1252; // ANSI Latin 1; Western European (Windows)
  64.       {Font size is correct but hi-char output is same as if "uses crt"}
  65.  
  66. var
  67.   New_CONSOLE_FONT_INFOEX : CONSOLE_FONT_INFOEX;
  68.   Rslt: boolean;
  69.  
  70. begin
  71. SetConsoleOutputCP(Codepage);
  72. SetTextCodepage(Output, Codepage);
  73.  
  74. FillChar(New_CONSOLE_FONT_INFOEX, SizeOf(CONSOLE_FONT_INFOEX), 0);
  75.  
  76. with New_CONSOLE_FONT_INFOEX do
  77.    begin
  78.    cbSize := SizeOf(CONSOLE_FONT_INFOEX);
  79.    nFont:= 0; // per http://stackoverflow.com/questions/33975912/how-to-set-console-font-to-raster-font-programmatically
  80.       {Values 0..100 don't seem to have any effect}
  81.    dwFontSizeX:= 0; {Values 0..100 don't seem to have any effect}
  82.    dwFontSizeY:= Fontsize;
  83.    FontFamily := FF_DONTCARE; // 5/5/2017 - http://stackoverflow.com/questions/33975912/how-to-set-console-font-to-raster-font-programmatically
  84.       {https://msdn.microsoft.com/en-us/library/cc250389.aspx
  85.        FF_DONTCARE = default font}
  86.  
  87.    FaceName := 'Lucida Console';
  88.       {For the following FaceName, font size becomes default (12), regardless of Fontsize -
  89.          ''
  90.          Consolas
  91.          Terminal}
  92.    FontWeight:= 400 {FW_NORMAL}; // http://stackoverflow.com/questions/33975912/how-to-set-console-font-to-raster-font-programmatically
  93.       {FW_NORMAL = 400}
  94.       {If <> 400 then Fontsize has no effect but hi-chars are displayed correctly
  95.       even if "uses crt"}
  96.    end;
  97.  
  98. Rslt:= SetCurrentConsoleFontEx(StdOutputHandle,false,New_CONSOLE_FONT_INFOEX);
  99.    // https://msdn.microsoft.com/en-us/library/windows/desktop/ms686200%28v=vs.85%29.aspx
  100.    {2nd param doesn't seem to have any effect}
  101. writeln('SetCurrentConsoleFontEx = ', Rslt);
  102.    {True regardless if "uses crt"}
  103. end;
  104. {#########################################}
  105.  
  106. end.
  107.  
« Last Edit: May 11, 2017, 12:53:11 pm by dculp »

mangakissa

  • Hero Member
  • *****
  • Posts: 1131
Re: Console program - how to set font size (conflict with crt unit)?
« Reply #1 on: May 11, 2017, 12:18:05 pm »
A console application is related to the DOS box / windows CMD command box. That's why selecting a bigger font is not working.

That's why there are GUI applications
Lazarus 2.06 (64b) / FPC 3.0.4 / Windows 10
stucked on Delphi 10.3.1

dculp

  • Full Member
  • ***
  • Posts: 129
Re: Console program - how to set font size (conflict with crt unit)?
« Reply #2 on: May 11, 2017, 12:57:20 pm »
I can get a bigger font. However, the font characters just aren't correct (see my revised post - second paragraph and images).

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Console program - how to set font size (conflict with crt unit)?
« Reply #3 on: May 11, 2017, 06:51:55 pm »
You just cannot do that with crt unit.

Bart

Thaddy

  • Hero Member
  • *****
  • Posts: 14201
  • Probably until I exterminate Putin.
Re: Console program - how to set font size (conflict with crt unit)?
« Reply #4 on: May 11, 2017, 08:38:36 pm »
Windows only, but you can use the attached console code from this post: http://forum.lazarus.freepascal.org/index.php/topic,30878.msg196875.html#msg196875
as a crt replacement. Note I forgot a closing bracket in the header, but works on win32/win64. Credits to Rudy Veldhuis.

That code does not suffer from codepage problems.
« Last Edit: May 11, 2017, 08:41:58 pm by Thaddy »
Specialize a type, not a var.

dculp

  • Full Member
  • ***
  • Posts: 129
Re: Console program - how to set font size (conflict with crt unit)?
« Reply #5 on: May 13, 2017, 09:24:21 pm »
Windows only, but you can use the attached console code from this post: http://forum.lazarus.freepascal.org/index.php/topic,30878.msg196875.html#msg196875
as a crt replacement. Note I forgot a closing bracket in the header, but works on win32/win64. Credits to Rudy Veldhuis.

That code does not suffer from codepage problems.

This seems to work well on a demo basis. (I haven't yet tried it in my main program.) However, a couple of questions --

1. Before I set a new FaceName, FontSize in procedure Set_console_fontsize, I want to save the current (original) values so that these can be restored when the program closes. How do I get the current values?

2. In program ConsoleDemo that is included in the console.7z download, there are compiler directives --
{$IFDEF FPC}{$MODE DELPHI}{$ASMMODE INTEL}{$H-}{$DEFINE INLINES}{$DEFINE HASERROUTPUT}{$ENDIF}
Disabling these seems to have no effect.
Are they actually needed there or are they just redundant from the console.pas unit where they are also included?

3. From my original post (code below), FontSize works correctly for FaceName 'Lucida Console' or 'Consolas'. I tried 'Arial' but it just reverted to the system font. Is there anywhere a list of FaceName that would allow the FontSize to scale correctly. (The two working FaceName are acceptable so this is more of a curiosity question.)

Code: Pascal  [Select][+][-]
  1. with New_CONSOLE_FONT_INFOEX do
  2.    begin
  3.    cbSize := SizeOf(CONSOLE_FONT_INFOEX);
  4.    nFont:= 0;
  5.    dwFontSizeX:= 0;
  6.    dwFontSizeY:= Fontsize;
  7.    FontFamily := FF_DONTCARE;
  8.    FaceName := 'Lucida Console';
  9.    FontWeight:= 400 {FW_NORMAL};
  10.    end;
  11.  


Thaddy

  • Hero Member
  • *****
  • Posts: 14201
  • Probably until I exterminate Putin.
Re: Console program - how to set font size (conflict with crt unit)?
« Reply #6 on: May 13, 2017, 09:42:14 pm »
1. There a win api cal to get the size. Will try and find it.
2. That is because when I made it FPC compatible I retained Delphi compatibility too. That's important for some if not most.
3. As already mentioned, you can only use fixed fonts, not fonts like arial. There are fixed fonts that look a bit like Arial, though. Like Segoe or Consolas. That's not a limitation of FPC or Lazarus but a limitation of the console. There is no work-around for that, although I have seen fonts that came in both fixed and variable pitch  Arial is not one of these..
https://en.wikipedia.org/wiki/Monospaced_font
« Last Edit: May 13, 2017, 09:55:21 pm by Thaddy »
Specialize a type, not a var.

 

TinyPortal © 2005-2018