Specific console colours — is it possible?

Just starting out? Need help? Post your questions and find answers here.
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Specific console colours — is it possible?

Post by Oso »

Hi all, I have a question on the console and apologise for bringing up this subject again. Some folks probably think this is all I do :D In the below working example, courtesy of Mijikai, there are three possible colours, which, according to the API documentation, can be used in various combinations, though still very limited. As this is a very uninspiring and bland grey, reminiscent of a dull sky, is there a way to set each RGB colour specifically? By contrast, in the equivalent Windows console properties (cmd window), there are three RGB settings that can be set — for example an ideal combination 240, 240, 240. This doesn't seem to be mentioned in the API document. Is it possible to do this programmatically?

https://learn.microsoft.com/en-us/windo ... attributes

Code: Select all

Procedure Set_Up_Console()
  
  Define librno.i
  Define handle.i
  Define hwnd.i
  Define csbi.CONSOLE_SCREEN_BUFFER_INFO
  Define conoffset.i
  Define conlength.i
  Define cx, cy
  
  OpenConsole()

  librno.i=OpenLibrary(#PB_Any,"kernel32.dll")
  hwnd.i=CallFunction(librno.i,"GetConsoleWindow")
  CloseLibrary(librno.i)

  handle = GetStdHandle_(#STD_OUTPUT_HANDLE)
  If handle <> #INVALID_HANDLE_VALUE
    If GetConsoleScreenBufferInfo_(handle,@csbi)
      If SetConsoleTextAttribute_(handle,#BACKGROUND_BLUE|#BACKGROUND_GREEN|#BACKGROUND_RED)
        FillConsoleOutputAttribute_(handle,#BACKGROUND_BLUE|#BACKGROUND_GREEN|#BACKGROUND_RED,csbi\dwSize\x * csbi\dwSize\y,conoffset,@conlength)
      EndIf
    EndIf
  EndIf

  cx = GetSystemMetrics_(#SM_CXSCREEN);
  cy = GetSystemMetrics_(#SM_CYSCREEN);
  SetWindowPos_(hwnd,#Null,-5, 100,#Null,#Null,#SWP_NOSIZE|#SWP_NOZORDER)
  
  ConsoleTitle("Title")
  ConsoleColor(3,7)
  PrintN("Welcome...")
  ConsoleColor(1,7)
  PrintN("Console ")
  Input()
  
EndProcedure

Set_Up_Console()
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4659
Joined: Sun Apr 12, 2009 6:27 am

Re: Specific console colours — is it possible?

Post by RASHAD »

Code: Select all

; /*Enum To store Foreground colors*/
;     typedef enum FG_COLORS 
;     {
;         FG_BLACK = 0,
;         FG_BLUE = 1,
;         FG_GREEN = 2,
;         FG_CYAN = 3,
;         FG_RED = 4,
;         FG_MAGENTA = 5,
;         FG_BROWN = 6,
;         FG_LIGHTGRAY = 7,
;         FG_GRAY = 8,
;         FG_LIGHTBLUE = 9,
;         FG_LIGHTGREEN = 10,
;         FG_LIGHTCYAN = 11,
;         FG_LIGHTRED = 12,
;         FG_LIGHTMAGENTA = 13,
;         FG_YELLOW = 14,
;         FG_WHITE = 15
;     }FG_COLORS;
; 
;     /*Enum To store Background colors*/
;     typedef enum BG_COLORS 
;     {
;         BG_NAVYBLUE = 16,
;         BG_GREEN = 32,
;         BG_TEAL = 48,
;         BG_MAROON = 64,
;         BG_PURPLE = 80,
;         BG_OLIVE = 96,
;         BG_SILVER = 112,
;         BG_GRAY = 128,
;         BG_BLUE = 144,
;         BG_LIME = 160,
;         BG_CYAN = 176,
;         BG_RED = 192,
;         BG_MAGENTA = 208,
;         BG_YELLOW = 224,
;         BG_WHITE = 240
;     }BG_COLORS;96

Procedure Set_Up_Console()
  
  Define librno.i
  Define handle.i
  Define hwnd.i
  Define csbi.CONSOLE_SCREEN_BUFFER_INFO
  Define conoffset.i
  Define conlength.i
  Define cx, cy
  
  OpenConsole()

  librno.i=OpenLibrary(#PB_Any,"kernel32.dll")
  hwnd.i=CallFunction(librno.i,"GetConsoleWindow")
  CloseLibrary(librno.i)

  handle = GetStdHandle_(#STD_OUTPUT_HANDLE)
  If handle <> #INVALID_HANDLE_VALUE
    If GetConsoleScreenBufferInfo_(handle,@csbi)
      If SetConsoleTextAttribute_(handle,#BACKGROUND_BLUE|#BACKGROUND_GREEN|#BACKGROUND_RED)
        FillConsoleOutputAttribute_(handle,#BACKGROUND_BLUE|#BACKGROUND_GREEN|#BACKGROUND_RED,csbi\dwSize\x * csbi\dwSize\y,conoffset,@conlength)
      EndIf
    EndIf
  EndIf

  cx = GetSystemMetrics_(#SM_CXSCREEN);
  cy = GetSystemMetrics_(#SM_CYSCREEN);
  SetWindowPos_(hwnd,#Null,-5, 100,#Null,#Null,#SWP_NOSIZE|#SWP_NOZORDER)
  
  ConsoleTitle("Title")
  
  SetConsoleTextAttribute_(handle,8+96)   ;FG-Color + BG-Color
  ;ConsoleColor(3,48)
  PrintN("Welcome...")
  SetConsoleTextAttribute_(handle,4+224)
  ;ConsoleColor(1,7)
  PrintN("Console ")
  Input()
  
EndProcedure

Set_Up_Console()
Egypt my love
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Specific console colours — is it possible?

Post by Mijikai »

There seems to be a colortable accessable via Get/SetConsoleScreenBufferInfoEx.
I tried to make something work but so far without success.

Nfo:
https://learn.microsoft.com/en-us/windo ... fer-infoex

Code (not working!):

Code: Select all

EnableExplicit

Import "kernel32.lib"
  GetConsoleScreenBufferInfoEx_.i(hConsoleOutput.i,*lpConsoleScreenBufferInfoEx) As "GetConsoleScreenBufferInfoEx";<- new apis
  SetConsoleScreenBufferInfoEx_.i(hConsoleOutput.i,*lpConsoleScreenBufferInfoEx) As "SetConsoleScreenBufferInfoEx" 
EndImport

Structure CONSOLE_SCREEN_BUFFER_INFOEX;<- the needed structure
  cbSize.l;<- not sure about this
  dwSize.COORD
  dwCursorPosition.COORD
  wAttributes.w
  srWindow.SMALL_RECT
  wPopupAttributes.w
  bFullscreenSupported.l;<- not sure about this
  ColorTable.l[16];<- only 16 available color entries!
EndStructure

Procedure.i RegisterConsoleColor(*Buffer,Index.i,Colors.i)
  Protected hout.i
  Protected csbi.CONSOLE_SCREEN_BUFFER_INFOEX
  hout = GetStdHandle_(#STD_OUTPUT_HANDLE) 
  If hout
    Debug 1
    csbi\cbSize = SizeOf(CONSOLE_SCREEN_BUFFER_INFOEX)
    If GetConsoleScreenBufferInfoEx_(hout,@csbi);<- get the info (it fails for me here)
      Debug 2
      ;CopyMemory(*Buffer + (Index << 2),@csbi\ColorTable[0],Colors << 2);<- copy the colors
      If SetConsoleScreenBufferInfoEx_(hout,@csbi);<- use the updated color table
        Debug 3
        ProcedureReturn #True  
      EndIf
    EndIf  
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.i Main()
  Protected hwnd.i
  Protected color.i
  If OpenConsole(#Null$)
    color = $C2F08A
    RegisterConsoleColor(@color,#Null,1);<- register color/s
    PrintN("Hello World")
    Input()
    SetClassLongPtr_(hwnd,-10,color)
    CloseConsole()
  EndIf
  ProcedureReturn #Null
EndProcedure

Main()

End
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: Specific console colours — is it possible?

Post by Oso »

RASHAD wrote: Wed Jan 25, 2023 5:41 pm

Code: Select all

; /*Enum To store Foreground colors*/
;     typedef enum FG_COLORS 
;     {
;         FG_BLACK = 0,
;         FG_BLUE = 1,
;         FG_GREEN = 2,
;         FG_CYAN = 3,
Thank you RASHAD I've learnt something there. I realise now that I didn't explain well enough — it's the grey background that I'm hoping to change, which I think is this line...

Code: Select all

If FillConsoleOutputAttribute_(handle,#BACKGROUND_BLUE|#BACKGROUND_GREEN|#BACKGROUND_RED,csbi\dwSize\x * csbi\dwSize\y,offset,@length)
User avatar
ChrisR
Addict
Addict
Posts: 1150
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: Specific console colours — is it possible?

Post by ChrisR »

The names change a bit but I have more or less the same enumeration as Rashad

Code: Select all

Enumeration FOREGROUND
  #BlackFore   = 0
  #NavyFore    = #FOREGROUND_BLUE
  #GreenFore   = #FOREGROUND_GREEN
  #TealFore    = #FOREGROUND_GREEN | #FOREGROUND_BLUE
  #MaroonFore  = #FOREGROUND_RED
  #PurpleFore  = #FOREGROUND_RED | #FOREGROUND_BLUE
  #OliveFore   = #FOREGROUND_RED | #FOREGROUND_GREEN
  #GrayFore    = #FOREGROUND_RED | #FOREGROUND_GREEN | #FOREGROUND_BLUE
  #SilverFore  = #FOREGROUND_INTENSITY
  #BlueFore    = #FOREGROUND_INTENSITY | #FOREGROUND_BLUE
  #LimeFore    = #FOREGROUND_INTENSITY | #FOREGROUND_GREEN
  #AquaFore    = #FOREGROUND_INTENSITY | #FOREGROUND_GREEN | #FOREGROUND_BLUE
  #RedFore     = #FOREGROUND_INTENSITY | #FOREGROUND_RED
  #FuchsiaFore = #FOREGROUND_INTENSITY | #FOREGROUND_RED | #FOREGROUND_BLUE
  #YellowFore  = #FOREGROUND_INTENSITY | #FOREGROUND_RED | #FOREGROUND_GREEN
  #WhiteFore   = #FOREGROUND_INTENSITY | #FOREGROUND_RED | #FOREGROUND_GREEN | #FOREGROUND_BLUE
EndEnumeration

Enumeration BACKGROUND
  #BlackBack   = 0
  #NavyBack    = #BACKGROUND_BLUE
  #GreenBack   = #BACKGROUND_GREEN
  #TealBack    = #BACKGROUND_GREEN | #BACKGROUND_BLUE
  #MaroonBack  = #BACKGROUND_RED
  #PurpleBack  = #BACKGROUND_RED | #BACKGROUND_BLUE
  #OliveBack   = #BACKGROUND_RED | #BACKGROUND_GREEN
  #GrayBack    = #BACKGROUND_RED | #BACKGROUND_GREEN | #BACKGROUND_BLUE
  #SilverBack  = #BACKGROUND_INTENSITY
  #BlueBack    = #BACKGROUND_INTENSITY | #BACKGROUND_BLUE
  #LimeBack    = #BACKGROUND_INTENSITY | #BACKGROUND_GREEN
  #AquaBack    = #BACKGROUND_INTENSITY | #BACKGROUND_GREEN | #BACKGROUND_BLUE
  #RedBack     = #BACKGROUND_INTENSITY | #BACKGROUND_RED
  #FuchsiaBack = #BACKGROUND_INTENSITY | #BACKGROUND_RED | #BACKGROUND_BLUE
  #YellowBack  = #BACKGROUND_INTENSITY | #BACKGROUND_RED | #BACKGROUND_GREEN
  #WhiteBack   = #BACKGROUND_INTENSITY | #BACKGROUND_RED | #BACKGROUND_GREEN | #BACKGROUND_BLUE
EndEnumeration

Debug "FOREGROUND"
Debug "#BlackFore = "   + #BlackFore
Debug "#NavyFore = "    + #NavyFore
Debug "#GreenFore = "   + #GreenFore
Debug "#TealFore = "    + #TealFore
Debug "#MaroonFore = "  + #MaroonFore
Debug "#PurpleFore = "  + #PurpleFore
Debug "#OliveFore = "   + #OliveFore
Debug "#GrayFore = "    + #GrayFore
Debug "#SilverFore = "  + #SilverFore
Debug "#BlueFore = "    + #BlueFore
Debug "#LimeFore = "    + #LimeFore
Debug "#AquaFore = "    + #AquaFore
Debug "#RedFore = "     + #RedFore
Debug "#FuchsiaFore = " + #FuchsiaFore
Debug "#YellowFore = "  + #YellowFore
Debug "#WhiteFore = "   + #WhiteFore

Debug ""
Debug "BACKGROUND"
Debug "#BlackBack = "   + #BlackBack
Debug "#NavyBack = "    + #NavyBack
Debug "#GreenBack = "   + #GreenBack
Debug "#TealBack = "    + #TealBack
Debug "#MaroonBack = "  + #MaroonBack
Debug "#PurpleBack = "  + #PurpleBack
Debug "#OliveBack = "   + #OliveBack
Debug "#GrayBack = "    + #GrayBack
Debug "#SilverBack = "  + #SilverBack
Debug "#BlueBack = "    + #BlueBack
Debug "#LimeBack = "    + #LimeBack
Debug "#AquaBack = "    + #AquaBack
Debug "#RedBack = "     + #RedBack
Debug "#FuchsiaBack = " + #FuchsiaBack
Debug "#YellowBack = "  + #YellowBack
Debug "#WhiteBack = "   + #WhiteBack
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: Specific console colours — is it possible?

Post by Oso »

Mijikai wrote: Wed Jan 25, 2023 6:26 pm There seems to be a colortable accessable via Get/SetConsoleScreenBufferInfoEx.
I tried to make something work but so far without success.
Yes, I get the same result, it reaches '1' but fails at GetConsoleScreenBufferInfoEx_ I appreciate you trying Mijikai. The below is what inspired me to attempt this, where it shows three 'colour values'. The 240 RGB setting seems more pleasant to work with and looks more like a normal GUI colour :?

Image
User avatar
ChrisR
Addict
Addict
Posts: 1150
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: Specific console colours — is it possible?

Post by ChrisR »

Oso wrote: Wed Jan 25, 2023 6:30 pm Thank you RASHAD I've learnt something there. I realise now that I didn't explain well enough — it's the grey background that I'm hoping to change, which I think is this line...

Code: Select all

If FillConsoleOutputAttribute_(handle,#BACKGROUND_BLUE|#BACKGROUND_GREEN|#BACKGROUND_RED,csbi\dwSize\x * csbi\dwSize\y,offset,@length)
Seems to work here (Win 10) with a color rather than the attribute!
But I don't know if it is safe, it doesn't conform to the FillConsoleOutputAttribute API description

Code: Select all

FillConsoleOutputAttribute_(handle,RGB(58,150,220),csbi\dwSize\x * csbi\dwSize\y,conoffset,@conlength)
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: Specific console colours — is it possible?

Post by Oso »

ChrisR wrote: Wed Jan 25, 2023 6:39 pm The names change a bit but I have more or less the same enumeration as Rashad
Thanks ChrisR, I've just tried a few in the hope they might bring me a lighter shade :D . The grey is the same as what I have already. It's useful though, to see them set out in that way, with the colour mixes.
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: Specific console colours — is it possible?

Post by Oso »

ChrisR wrote: Wed Jan 25, 2023 6:47 pm Seems to work here (Win 10) with a color rather than the attribute! But I don't know if it is safe, it doesn't conform to the FillConsoleOutputAttribute API description

Code: Select all

FillConsoleOutputAttribute_(handle,RGB(58,150,220),csbi\dwSize\x * csbi\dwSize\y,conoffset,@conlength)
That's interesting, it works to a certain extent, but the colours being selected seem to be (from briefly testing it anyway) the same as the limited range of standard #-defined colours. For instance I tried 240,240,240 but it just gives a black background. I then tried 250,250,250 and got lime green :D
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4659
Joined: Sun Apr 12, 2009 6:27 am

Re: Specific console colours — is it possible?

Post by RASHAD »

Only the BG_COLORS are available for the console background color
For example

Code: Select all

FillConsoleOutputAttribute_(handle,112,csbi\dwSize\x * csbi\dwSize\y,conoffset,@conlength)
Egypt my love
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: Specific console colours — is it possible?

Post by Oso »

RASHAD wrote: Wed Jan 25, 2023 7:37 pm Only the BG_COLORS are available for the console background color
For example

Code: Select all

FillConsoleOutputAttribute_(handle,112,csbi\dwSize\x * csbi\dwSize\y,conoffset,@conlength)
I see, I guess this isn't going to be easy then :?
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: Specific console colours — is it possible?

Post by Oso »

I thought I would post an update on this, as I happened to notice something interesting. As I think the above thread concludes, console applications allow only a very limited set of background colours to be set programmatically through the Windows API. Most of the colours are unusable anyway, leaving at least for practical purposes, just black, white and grey.

I noticed that after opening a given PB console application and changing the colour properties of the console window, the setting is in fact preserved, even when the application is closed. I'm not sure where this setting is stored, although it appears to work. It also seems to be preserved after rebooting. Below explains :

1. Created a PB console application. The default is black.

Image

2. Right-click the title bar, then Properties, changing the three background RGB colours as desired, in this case 240, 240, 240.

Image

3. The new colour scheme then takes immediate effect.

Image

4. Close the application and re-run it. It doesn't appear to matter if the application is executed from the command prompt (as below), clicked via Explorer, or through the PB IDE. We can see here that the new colour has been preserved.

Image

5. As a test, run a different PB console application and default is black. This appears to show that the settings are recorded against the application. I'm not sure how that is done. Of course, this doesn't help those of us who would prefer to set the colour programmatically, but it does enable us to set a preference after installation.

Image
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Specific console colours — is it possible?

Post by JHPJHP »

Hi Oso,
Oso wrote:As I think the above thread concludes, console applications allow only a very limited set of background colours to be set programmatically through the Windows API.
An example to programmatically set the Windows Console background (RGB) color through an API can be found in Alternate Console.
Last edited by JHPJHP on Sun Feb 05, 2023 11:51 pm, edited 5 times in total.
User avatar
ChrisR
Addict
Addict
Posts: 1150
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: Specific console colours — is it possible?

Post by ChrisR »

The cmd configuration, font, color... seems to be stored in the shortcut:
%AppData%\Microsoft\Windows\Start Menu\Programs\System Tools\Command Prompt

To see it, copy the shortcut, run it and change the colors. Then compares the properties of the two shortcuts.
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: Specific console colours — is it possible?

Post by Oso »

ChrisR wrote: Fri Feb 03, 2023 8:39 pm The cmd configuration, font, color... seems to be stored in the shortcut:
%AppData%\Microsoft\Windows\Start Menu\Programs\System Tools\Command Prompt

To see it, copy the shortcut, run it and change the colors. Then compares the properties of the two shortcuts.
I'll look at this tomorrow ChrisR, thanks very much for mentioning this. The only thing I would say however, is that the colour setting I mentioned in the earlier message appeared to be specific to the particular PB executable, therefore not applying to the console in general. I may be wrong (it's late here :) ) but that seemed to be my finding earlier.
Post Reply