W jaki sposób programowo ustawić kolory dla konsoli, inne niż standardowe?

0

Temat zapewne banalny, ale na prawdę szukałem i nie znalazłem odpowiedzi. Wszędzie, na każdej stronie jest tylko 16 kolorów wymienionych. A mnie zastanawia jedno. Jeżeli w opcjach skrótu można wybrać dowolny kolor konsoli to czy nie da się też tego ustawić w kodzie programu. Ciężko jest cokolwiek zrobić natak na prawdę 8 kolorach. Bo ja nie widzę żadnej różnicy pomiędzy n, a n+8.

Czy da się w jakiś sposób ustawić te kolory? Nie chodzi o tryb graficzny.

0

Jaki system?

0

To ma to jakieś znaczenie? W8.

0

Ja jestem poziom, a raczej kilka poziomów niżej, tak więc nie mam pojęcia jak mam rozumieć to co jest w linku. Mógłbyś to jakoś rozjaśnić?

0

To że ktoś zaczyna czy, że jest jak to określasz ileś poziomów niżej, nie zwalnia go na pewno z używania mózgu. Czy aż tak trudno spojrzeć na wyniki w google po wpisaniu SetConsoleScreenBufferInfoEx delphi? Wprawdzie piąty link to post z kodem w C++ na właśnie forum 4p. Ale kod jest na tyle banalny, że nie problem go sobie szybko przetłumaczyć na choćby FPC. A kiedy się uważniej poszuka. I postudiuje strony jakie zwraca Google, to pewnie i można na coś lepszego - w Twoim rozumieniu - trafić.

Ty byś do wszystkiego chciał przykłady, jak dla jakiegoś chłopka roztropka z pola. Co mu pokaząc jak łopatą machać, a on dalej nie będzie ni cholery kumał co ma robić. A ja bym chciał, że jeżeli dostaniesz już link do oficjalnej dokumentacji na MSDN, to sobie poczytał najpierw i pokmbinował SAM. Nie patrzyłem na chronologię Twoich postów. Ale obiecałeś w wątku, który czytałem przed chwilą (polskie fonty w konsoli) się ogarnąć i nie pytać o wszystko co chwila na forum, co można samemu wyszukać. Także dotrzymaj słowa i się po prostu ogarnij. Najwyższy czas.

0

Spójrz: dokumentacja mówi, że funkcja ta wygląda tak:

BOOL WINAPI SetConsoleScreenBufferInfoEx(
  _In_  HANDLE hConsoleOutput,
  _In_  PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx
);

Tłumacząc na Delphi:

Function SetConsoleScreenBufferInfoEx(hConsoleOutput: HANDLE; lpConsoleScreenBufferInfoEx: PCONSOLE_SCREEN_BUFFER_INFOEX): Boolean; stdcall;

(powinno to już być przetłumaczone w module Windows.)*

Patrzymy na pierwszy argument - uchwyt konsoli. Szybkie wyszukiwanie w Google i dowiadujemy się, że można go pobrać za pomocą funkcji GetConsoleWindow. Załatwione.
Drugi to jakaś długa nazwa typu - znów patrzymy w dokumentację MSDN.

typedef struct _CONSOLE_SCREEN_BUFFER_INFOEX {
  ULONG      cbSize;
  COORD      dwSize;
  COORD      dwCursorPosition;
  WORD       wAttributes;
  SMALL_RECT srWindow;
  COORD      dwMaximumWindowSize;
  WORD       wPopupAttributes;
  BOOL       bFullscreenSupported;
  COLORREF   ColorTable[16];
} CONSOLE_SCREEN_BUFFER_INFOEX, *PCONSOLE_SCREEN_BUFFER_INFOEX;

(również powinno być przetłumaczone.)*

Czyżby... tak! ColorTable na samym końcu.
Teraz tylko patrzymy, czym jest COLORREF...

MSDN napisał(a)

When specifying an explicit RGB color, the COLORREF value has the following hexadecimal form:
0x00bbggrr

I właściwie wszystko mamy załatwione - pozostało tylko pozbierać to w całość.


`*` chociaż w Delphi 7 przykładowo tego nie ma ;p - w razie czego jednak powinieneś dać radę sobie z tym radę, wielkiej magii tutaj nie ma.
0

Mam nadzieję, że zrozumiałem wszystko dobrze. Wydaje mi się, że właśnie brakowało mi zrozumienia jak mam to odczytać. Teraz wydaje mi się to łatwiejsze.

Aczkolwiek funkcja ta nie działa. Choć pewnie coś źle zrozumiałem. Dopisałem do uses windows, jednak po próbie kompilacji wyświetla się komunikat, że taka zmienna nie istnieje.

0

Czyli jednak Twój kompilator nie ma tej funkcji w bibliotece standardowej - cóż, zdarza się.

Function SetConsoleScreenBufferInfoEx(hConsoleOutput: HANDLE; lpConsoleScreenBufferInfoEx: PCONSOLE_SCREEN_BUFFER_INFOEX): Boolean; stdcall; external 'kernel32.dll';

Plus coś w stylu

Type PCONSOLE_SCREEN_BUFFER_INFOEX = ^_CONSOLE_SCREEN_BUFFER_INFOEX;
     _CONSOLE_SCREEN_BUFFER_INFOEX =
Packed Record
 cbSize: Longword;
 dwSize, dwCursorPosition: COORD;
 wAttributes: Word;
 srWindow: SMALL_RECT;
 dwMaximumWindowSize: COORD;
 wPopupAttributes: Word;
 bFullscreenSupported: Boolean;
 ColorTable: Array[0..15] of COLORREF; // uint32 najpewniej
End;

Gdzieś na początek kodu.


Pisane z palca, więc w razie czego popraw ewentualne błędy :P
0

Ten sam błąd wychodzi w przypadku GetConsoleWindow, ale to jakoś rozwiązałem, nie wiem czy prawidłowo, ale już nie wyskakuje. Teraz mam problem z tą ostatnią częścią, colorref. Zapewne coś źle wpisuję, nie to co trzeba, bo w żaden sposób to nie wychodzi, albo wyświetla się, że nie ma takiej zmiennej, albo że nieprawidłowy typ.

0

Więc spójrz do dokumentacji.

0

Tak, próbuję, a jednak ciągle są te same błędy.

0

Jakiego Ty w ogóle używasz kompilatora? Przecież zarówno aktualne FPC jak i Lazarus w module Windows mają te definicje. To podstawowy typ dla WinAPI. Sprawdziłem, że istniał już przynajmniej w statusienkim Delphi 3. Także jak może Tobie nie istnieć. Ogarnałeś w ogóle sekcje uses. Poczytaj Ty chłopie w końcu jakiś kurs. Chcesz pisać w FPC zahaczając o WinAPI, a nie dodałeś chyba najważniejszego modułu do uses. Bo inaczej nie widzę powodu, dlaczego kompilator miałby się tego czepiać, jeżeli nie ma literówki i błędów składni, a jest undeclared identifier. Toż to ręce opadają. A obiecywałeś nam w końcu się ogarnąć wczoraj w jednym z wątków. I nie pytać więcej o pierdoły. Ewentualnie jeżeli nadal nie widzi tego typu to dodaj sobie takowy. Przecież wiadomo, że jeżeli coś ma przyjmować wartości od $0 do $FFFFFFFF. To będzie to najpewniej po prostu zwykły DWORD i tak należy próbować.

type
  COLORREF = DWORD;
0

Pytań nie zadaje. Tylko kontynuuje to co zostało otwarte. Wyskakuje identifier not found. w uses mam dos, crt, math, windows, fileutil;
Funkcja np. SetConsoleTitle działa prawidłowo.

A przy colorref najcześciej pokazuje się błąd:

program.lpr(714,62) Error: Incompatible type for arg no. 2: Got "LongInt", expected "_CONSOLE_SCREEN_BUFFER_INFOEX"

dodanie znacznika <code> - furious programming

0

Wrzuć cały kod.

0

Ok, to dodaj sobie ten typ, tak jak pokazałem. Ale podejrzewam, że używasz bardzo starego FPC albo robisz jakieś literówki, bo z modułem Windows nie ma problemów. Oto dowód. Poniższy kod skompilowany na szybko pod edytorem z filemanager FAR i ConEmu. Z zastosowaniem pluginu EXTCOM i pluginem do kolorowanie składni pod edytorem HIGHLIGHT. Na screenie jest tyle linii, bo pododawałem puste, początkowo kombinując jak pokazać wyniki razem kodem zęby wszystko było widoczne.

program a;
uses
  Windows;
var
  Test : COLORREF;
begin
end.

Zwraca:

╔════════════════════════ fpc "D:\a.pp" ═════════════════════════
║  Free Pascal Compiler version 2.4.2 [2010/11/10] for i386      
║  Copyright (c) 1993-2010 by Florian Klaempfl                   
║  Target OS: Win32 for i386                                     
║  Compiling D:\a.pp                                             
║  a.pp(7,3) Note: Local variable "Test" not used                
║  Linking D:\a.exe                                              
║  8 lines compiled, 0.1 sec , 26112 bytes code, 1560 bytes data 
║  1 note(s) issued                                              

Schowek01.png

0
Patryk27 napisał(a):

Wrzuć cały kod.

program test;

uses dos, crt, math, windows, fileutil;

type
     menu = record
          wybor :integer;
          szerokosc :integer;
     end;
Type PCONSOLE_SCREEN_BUFFER_INFOEX = ^_CONSOLE_SCREEN_BUFFER_INFOEX;
     _CONSOLE_SCREEN_BUFFER_INFOEX = Packed Record
          cbSize: Longword;
     	  dwSize, dwCursorPosition: COORD;
          wAttributes: Word;
          srWindow: SMALL_RECT;
          dwMaximumWindowSize: COORD;
          wPopupAttributes: Word;
          bFullscreenSupported: Boolean;
          ColorTable: Array[0..15] of COLORREF;
End;

var
     menu_dane :menu;
     oknox :integer;
     oknoy :integer;
     pozegnanie :string;
     dlugoscpozegnania :integer;
     x_pozegnanie :integer;
     y_pozegnanie :integer;
     powitanie :string;
     dlugoscpowitania :integer;
     x_powitanie :integer;
     y_powitanie :integer; 

     Function SetConsoleScreenBufferInfoEx(hConsoleOutput: HANDLE; lpConsoleScreenBufferInfoEx: _CONSOLE_SCREEN_BUFFER_INFOEX): Boolean; stdcall; external 'kernel32.dll';
     
     Function GetConsoleWindow: Boolean; stdcall; external 'kernel32.dll';   

begin
     SetConsoleScreenBufferInfoEx(GetConsoleWindow, ???);
     SetConsoleTitle('Program testowy');
     oknox := windmaxx;
     oknoy := windmaxy;
     cursoroff;
     textbackground(black);
     textcolor(white);
     //clrscr;
     powitanie := 'Witaj w programie';
     dlugoscpowitania := length(powitanie);
     x_powitanie := (oknox - dlugoscpowitania) div 2;
     y_powitanie := oknoy div 2;
     gotoxy(x_powitanie, y_powitanie);
     writeln(powitanie);
     delay(0200);
     gotoxy(1, 1);
     repeat
          menu_dane := menu_glowne(oknox, oknoy);
          if menu_dane.wybor = 1 then
               wyswietl1(oknox, oknoy, menu_dane);
          if menu_dane.wybor = 2 then
               wyswietl2(oknox, oknoy);
     until menu_dane.wybor = 8;
     window(1, 1, oknox, oknoy);
     textbackground(black);
     textcolor(white);
     clrscr;
     pozegnanie := 'Do zobaczenia.';
     dlugoscpozegnania := length(pozegnanie);
     x_pozegnanie := (oknox - dlugoscpozegnania) div 2;
     y_pozegnanie := oknoy div 2;
     gotoxy(x_pozegnanie, y_pozegnanie);
     writeln(pozegnanie);
     delay(5000);
end. 

Usunąłem tylko procedury i funkcje, które i tak są bez znaczenia.

0

Nie sądziłem, że można źle przekopiować funkcję...

Function SetConsoleScreenBufferInfoEx(hConsoleOutput: HANDLE; lpConsoleScreenBufferInfoEx: PCONSOLE_SCREEN_BUFFER_INFOEX): Boolean; stdcall; external 'kernel32.dll';

Jako parametr powinieneś przekazać wskaźnik typu CONSOLE_SCREEN_BUFFER_INFOEX - domyślasz się, jak to zrobić? (są dwa sposoby)

0

Nie, to nic nie zmienia. To chyba ja próbowałem coś zmienić i nie wróciłem do poprzedniego stanu. Tak czy inaczej i tak wyskakuje ten sam problem.

0

U mnie "czepia się", co oczywiste tych ??? no i nie zna unitu fileutil, zresztą chyba tutaj zbędnego według mnie. Na pewno nie "czepia się" ColorTable : array[0..15] of COLORREF;, tak jak wywnioskowałeś nie wiadomo skąd.

0

fileutil jest po to by wyświetlały się polskie litery. Zrobiłem to według instrukcji, która ktoś wczoraj podawał.

Ale u mnie problemem jest właśnie to ???. Prawdopodobnie nie wiem co tam wpisać, jak ten parametr przekazać, bo z róznych kombinacji zawsze wyskakuje jakiś błąd.

0
Patryk27 napisał(a):

Jako parametr powinieneś przekazać wskaźnik typu CONSOLE_SCREEN_BUFFER_INFOEX - domyślasz się, jak to zrobić? (są dwa sposoby)

Wychodzi na to, że się nie domyślam.

0

Trzeba pogodzić się z tym że nie masz talentu do programowania, ale masz inny, wielki talent.
Zobacz, przyczyniłeś się do napisania 3-ch stron tekstu (częściowo sam napisałeś częściowo innych zmusiłeś ale nadal twoja zasługa) na temat kolorów na konsole. Nawet nie patrząc na to że nie o to ci chodzi. Nawet ewidentnie widząc że kolorów nadal będzie 16 szt ale mogą być wszystkie np w odcieniach zieleni.
Rzuć w cholerę informatykę i idź na dziennikarstwo, przed tobą świetlana kariera.

0

Ty za to masz wielki talent do krytykowania. To, że jest ich 16 widzę po tablicy. Ale chciałem to sprawdzić, zobaczyć jak to będzie wyglądało.

I jak mam rzucać informatykę? Studiuję zarządzanie, informatykę wykorzystuję do własnych celów. Nie jestem informatykiem i nie chcę nim być. Ale Pascal do tej pory mi bardzo pomógł, zaoszczędziłem wiele czasu dzięki niemu. A jeszcze pamiętaj, że talent, a wiedza to zupełnie coś innego. Może się na programistę nie nadaję, ale zawsze jako jedyny jeszcze w liceum to ogarniałem. Tyle tylko, że ja w większości korzystam z tego co się tam nauczyłem. Jeśli mam być szczery, to po prostu nie lubię, nie potrafię czytać i się uczyć. Ja się uczę praktyką. Nauczyciel pokazywał co się jak robi i ja po kilku sekundach wszystko wiedziałem. Właśnie dlatego najlepszą formą dla mnie jest forum. Pytam, dostaję odpowiedź i już wiem.

0

Rozumienie z przykładu to dobre ale problem jest w tym że nie zawsze można to mieć jak tego nie ma w dokumentacji.
Tak naprawdę jest na odwrót - prawie nigdy nie a przykładu.
Jak jest to twoje hobby to siedź i próbuj po rozwiązaniu będzie większa satysfakcja.

0
lucasp17 napisał(a):

Ale u mnie problemem jest właśnie to ???. Prawdopodobnie nie wiem co tam wpisać, jak ten parametr przekazać, bo z róznych kombinacji zawsze wyskakuje jakiś błąd.

Pomyśl tak na logikę - musisz coś tam przekazać.
To "coś" będzie wskaźnikiem na CONSOLE_SCREEN_BUFFER_INFOEX (stąd pełna nazwa tego typu w parametrze funkcji brzmi PCONSOLE_SCREEN_BUFFER_INFOEX -> początkowe P od pointer).
Zasadnicze pytanie - przerabiałeś już wskaźniki w Pascalu?

0

Czytałem o nich, ale nie używałem ani razu. Podobno to dobre narzędzie dla programistów, ale z drugiej strony nie zaleca się ich używania. Ja nie widząc potrzeby, nie używałem ich. Tak na prawdę nawet nie wiem do czego mógłbym ich użyć.

1
lucasp17 napisał(a)

Podobno to dobre narzędzie dla programistów, ale z drugiej strony nie zaleca się ich używania.

Huh? Co? Jak?
Czyżby coś mnie ominęło?

Tak na prawdę nawet nie wiem do czego mógłbym ich użyć.

Musisz przekazać wskaźnik na strukturę CONSOLE_SCREEN_BUFFER_INFOEX jako drugi parametr funkcji.
Innymi słowy:

  1. alokujesz wskaźnik na tę strukturę
  2. wypełniasz dane (czyli to ColorTable)
  3. wywołujesz SetConsoleScreenBufferInfoEx(GetConsoleWindow, MojaZmiennaBedacaWskaznikiemNaTeStrukture);
  4. zwalniasz wskaźnik (chyba że będziesz jeszcze chciał wywoływać tę funkcję or sth) i voilà!

Ja nie widząc potrzeby, nie używałem ich.

Teraz jest potrzeba :P


Przy okazji: `GetConsoleWindow` zwraca `HWND`, a nie `Boolean`.
0
Patryk27 napisał(a):

Innymi słowy:

  1. alokujesz wskaźnik na tę strukturę
  2. wypełniasz dane (czyli to ColorTable)
  3. wywołujesz SetConsoleScreenBufferInfoEx(GetConsoleWindow, MojaZmiennaBedacaWskaznikiemNaTeStrukture);
  4. voilà!

Ad 1. Po kiego ?!
voilà! - masz na myśli zwalniasz alokowany wskaźnik?

  1. Tworzysz zmienną MojaZmiennaBedacaTaStruktura
  2. Wypełniasz dane (czyli to ColorTable)
  3. Wywołujesz SetConsoleScreenBufferInfoEx(GetConsoleWindow,@MojaZmiennaBedacaTaStruktura);
  4. voilà - sobie darować.
4

Pierwszym parametrem funkcji SetConsoleScreenBufferInfoEx nie ma być żaden uchwyt okna konsoli tylko buforu ekranu konsoli który można pobrać funkcją GetStdHandle(STD_OUTPUT_HANDLE) (a nie żadne GetConsoleWindow)
Zamiast wypełniać na piechotę strukturę można pobrać te informacje funkcją GetConsoleScreenBufferInfoEx a później podmienić tylko tabelę kolorów jak w przykładzie (dla Delphi):

program ConColorTest;

{$APPTYPE CONSOLE}

uses
  Windows, Graphics;

type
  PCONSOLE_SCREEN_BUFFER_INFOEX = ^_CONSOLE_SCREEN_BUFFER_INFOEX;

  _CONSOLE_SCREEN_BUFFER_INFOEX = packed record
    cbSize: ULONG;
    dwSize: COORD;
    dwCursorPosition: COORD;
    wAttributes: WORD;
    srWindow: SMALL_RECT;
    dwMaximumWindowSize: COORD;
    wPopupAttributes: WORD;
    bFullscreenSupported: BOOL;
    ColorTable: array [0..15] of COLORREF;
  end;

const
  KERNEL = 'kernel32.dll';

  function GetConsoleScreenBufferInfoEx(hConsoleOutput: THandle;
    lpConsoleScreenBufferInfoEx: PCONSOLE_SCREEN_BUFFER_INFOEX): BOOL; stdcall;
    external KERNEL;
  function SetConsoleScreenBufferInfoEx(hConsoleOutput: THandle;
    lpConsoleScreenBufferInfoEx: PCONSOLE_SCREEN_BUFFER_INFOEX): BOOL; stdcall;
    external KERNEL;

var
  hConOut: THandle;
  bi: _CONSOLE_SCREEN_BUFFER_INFOEX;
  i: Integer;
begin
  Randomize;
  hConOut:= GetStdHandle(STD_OUTPUT_HANDLE);
  bi.cbSize:= SizeOf(_CONSOLE_SCREEN_BUFFER_INFOEX);
  GetConsoleScreenBufferInfoEx(hConOut, @bi);

  for i:= 1 to 15 do //definiujesz kolory ja sobie w petli dla przykladu wylosuje
    bi.ColorTable[i]:=  RGB(Random(256), Random(256), Random(256));
  //wypelnialem od 1 bo nie chcialem zmieniac domyślnego czarnego koloru tła

  SetConsoleScreenBufferInfoEx(hConOut, @bi);

  for i:=1 to 15 do //petla wypisujaca napisy we wszyskich zdefiniowanych kolorach (z wyjątkiem 0 który zostawiam na tło)
  begin
    SetConsoleTextAttribute(hConOut, i);
    writeln('Testowy Tekst');
  end;
  readln;
end.

1 użytkowników online, w tym zalogowanych: 0, gości: 1