GDI a operowanie na napisach

GDI a operowanie na napisach
wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

są funkcje takie jak DrawText albo TextOut tylko jak zmienić rozmiar czcionki i kolor czcionki oraz tło ustawić na przeźroczyste?

Kopiuj
RECT rect;
GetClientRect(draw.myconsole, &rect);

DrawText(draw.mydc, (char *)("Hello, GDI DrawText!"), -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
TextOut(draw.mydc, 100, 100, "test data", 9);

chciałbym polskiego Ariala
EDIT: funkcja SetTextColor zmienia kolor, jeszcze rozmiar czcionki i tło na przeźroczyste

Kopiuj
	SetTextColor(draw.mydc, 0x00FF00);
	TextOut(draw.mydc, 100, 100, "test data", 9);

jest kolor zielony
EDIT: mam rozmiar czcionki proporcje 64 na 32

Kopiuj
RECT hwndRect;
HFONT titleFont = CreateFont(64, 32, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_CHARACTER_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, (char *)("Arial"));
SelectObject(draw.mydc, titleFont);

SetTextColor(draw.mydc, 0x00FF00);
TextOut(draw.mydc, 100, 100, "test data", 9);

jeszcze przeźroczystość dla tła tekstu ... ?
EDIT:już mam z ChatGPT dla przeźroczystości

Kopiuj
SetBkMode(draw.mydc, TRANSPARENT);

przepraszam że nie sprawdziłem z góry tylko wstawiłem wątek bez sprawdzenia

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

gotowe:

Kopiuj
	void TextOutXY(int x, int y, char* data,int red,int green,int blue)
	{
		HFONT titleFont = CreateFont(64, 32, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_CHARACTER_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, (char*)("Arial"));
		SelectObject(mydc, titleFont);
		SetTextColor(mydc, RGB(red, green, blue));
		SetBkMode(mydc, TRANSPARENT);
		TextOut(mydc, x, y, data, strlen(data));
		SetBkMode(mydc, OPAQUE);
	}

tylko nie działają polskie znaki, jak uruchomić z Arialem polskim?

Marius.Maximus
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2184
0

@wilkwielki

  1. obejrzyj pamięć tekstu w hex-edytorze a potem pocztyaj dokumentację
  2. https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createfonta
  3. https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createfontw

I będziesz wiedział dlaczego nie ma polskich znaków, to Cie natchnie na pewno

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

dużo tego jest, gdzie zacząć?
EDIT:już mam musi być tak:

Kopiuj
HFONT titleFont = CreateFont(64, 32, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET, OUT_DEFAULT_PRECIS, CLIP_CHARACTER_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, (char*)("Arial"));

zamiast ANSI to trzeba na EASTEUROPE_CHARSET
dzięki za pomoc Marius.Maximus 😀

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
0
wilkwielki napisał(a):

tylko nie działają polskie znaki, jak uruchomić z Arialem polskim?

Najprawdopodobniej jest problem z kodowanie znaków (które można ustalić w locale).

  1. Czy te polskie znaki idą z literałów, czy z jakiś danych zewnętrznych
  2. Jak zewnętrzne dane jakie kodowanie?
  3. Jak literały to jakie masz flagi budowania i kodowanie źródeł?
  4. Jakie masz ustawienia systemowe - code page?
  5. Czy konfigurowałeś setlocale (C), std::locale::global (C++)?
wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

już mi działają polskie znaki, trzeba było podać argument "EASTEUROPE_CHARSET" zamiast "ANSI_CHARSET" w funkcji "CreateFont"i działa polska czcionka, temat do zamknięcia myślę ale dzięki za pomoc 😉

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

inne pytanie nr2..., jak zrobić napis TextOut do buffora tzn do tablicy aby wpisać potem ten buffor do centralnego buffora od renderingu grafiki do funkcji mojej DrawBuffor? czy tak można? każda podpowiedź mile widziana 😀 bo mam pomysł ale potrzebuje funkcji która kopiuje fragment obrazu do buffora a potem wpisać do centralnego...

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

mam tak:

Kopiuj
HDC screenDC = GetDC(NULL); // Pobiera cały ekran (desktop)
std::vector<BYTE> pixelBuffer;
if (CopyRegionToBuffer(screenDC, 100, 100, 200, 150, pixelBuffer)) {
    std::cout << "Fragment obrazu został skopiowany do bufora!" << std::endl;
    // Teraz pixelBuffer zawiera dane BGRA dla obszaru 200x150
} else {
    std::cout << "Nie udało się skopiować obrazu." << std::endl;
}
ReleaseDC(NULL, screenDC);

powinno działać, muszę to przerobić na unsigned char* pixelBuffer
EDIT:jest problem, długość stringa w TextOut liter jest zmienna i nie można ustalić długości pojedynczego znaku bo jest zmienny w zależności od danej litery, żeby można przewidzieć wielkość pojedynczego znaku, to można by zrobić to co bym chciał a nie da się...
EDIT: na ChatGPT jest pisanie TextOut do buffora c++

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

ta funkcja pobiera szerokość i wysokość tekstu w pixelach GetTextExtentPoint32

Kopiuj
SIZE textSize;
GetTextExtentPoint32(mydc, data, strlen(data), &textSize);
Box2d(x, y, x + textSize.cx, y + textSize.cy);

jeszcze jedno, funkcja od skopiowania fragmentu obrazu do buffora?
EDIT: https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getdibits jak to obsłużyć?
zna ktoś się na GDI?
EDIT: ten https://chatgpt.com/ pokazuje różne przykłady i nie ma podania pozycji początkowej do końca tylko sama wielkość buffora

Marius.Maximus
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2184
0

@wilkwielki może jesteś nie kompatybilny mentalnie z tym modelem LLM, spróbuj innego :D
Ja zadałem pytanie i u mnie wynik wygląda OK
CreateCompatibleDC, CreateCompatibleBitmap, SelectObject, TextOut
Bez kompilatora wydaje się że ma to sens, trzeba potwierdzić empirycznie

Ja zapytałem tak:

void TextOutXY(int x, int y, char* data,int red,int green,int blue)
{
HFONT titleFont = CreateFont(64, 32, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_CHARACTER_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, (char*)("Arial"));
SelectObject(mydc, titleFont);
SetTextColor(mydc, RGB(red, green, blue));
SetBkMode(mydc, TRANSPARENT);
TextOut(mydc, x, y, data, strlen(data));
SetBkMode(mydc, OPAQUE);
}

czy to mozna zrobic do jakiegos bufora pamieci ?

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

też zapytałem tak:

Kopiuj


    void TextOutXY(int x, int y, char* data,int red,int green,int blue)
    {
    HFONT titleFont = CreateFont(64, 32, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_CHARACTER_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, (char*)("Arial"));
    SelectObject(mydc, titleFont);
    SetTextColor(mydc, RGB(red, green, blue));
    SetBkMode(mydc, TRANSPARENT);
    TextOut(mydc, x, y, data, strlen(data));
    SetBkMode(mydc, OPAQUE);
    }

    czy to mozna zrobic do jakiegos bufora pamieci ?

i to co pokazał ChatGPT to nie ma wzmianki o skopiowaniu fragmentu obrazu do buffora, nigdzie nie pisze, że trzeba podać pozycje początkowe a potem dopiero szerokość i wysokość. czyli lipa
osobiście to chciałbym aby był dostępny taki występek:

Kopiuj
width=xEnd-xStart;
height=yEnd-yStart;
unsigned char* data_image = new unsigned char[width * height * 3];
data_image=CopyImageToBuffor(hdc,xStart,yStart,xEnd ,yEnd );
Marius.Maximus
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2184
0

jak koncept GDI jest problematyczny to moze cimg lepiej sie spisze ? https://cimg.eu/
tam możesz rysować po czystych wskaźnikach

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

to jest biblioteka kolejna do opanowania potężna , mi starczy GDI ale dzięki za podpowiedź

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

znalazłem na ChatGPT zastępnik funkcji GetPixel a mianowicie:

Kopiuj
#include <windows.h>
#include <vector>

struct RGB {
    BYTE blue;
    BYTE green;
    BYTE red;
};

bool GetPixelsFromScreen(HDC hdc, int x, int y, int width, int height, std::vector<RGB>& outPixels) {
    HDC hdcMem = CreateCompatibleDC(hdc);
    HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
    SelectObject(hdcMem, hBitmap);

    // Kopiuj obraz z ekranu do bitmapy
    BitBlt(hdcMem, 0, 0, width, height, hdc, x, y, SRCCOPY);

    BITMAPINFO bmi = { 0 };
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biHeight = -height; // Negatywna wysokość = górna linia pierwsza
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 24;
    bmi.bmiHeader.biCompression = BI_RGB;

    outPixels.resize(width * height);

    // Pobierz piksele
    BOOL success = GetDIBits(hdcMem, hBitmap, 0, height, outPixels.data(), &bmi, DIB_RGB_COLORS);

    // Sprzątanie
    DeleteObject(hBitmap);
    DeleteDC(hdcMem);

    return success == TRUE;
}

a potem użycie:

Kopiuj
HDC hdcScreen = GetDC(NULL); // NULL = cały ekran
std::vector<RGB> pixels;
if (GetPixelsFromScreen(hdcScreen, 0, 0, 1920, 1080, pixels)) {
    RGB pixel = pixels[100 * 1920 + 100]; // Piksel w (100, 100)
    printf("R: %d G: %d B: %d\n", pixel.red, pixel.green, pixel.blue);
}
ReleaseDC(NULL, hdcScreen);

jak pobrać tablice typu unsigned char z obiektu pixels?

Kopiuj
unsigned char *data=new unsigned char[1920*1080*3]
data=pixels.data();

dobrze napisałem? jak dojść do surowych danych rgb z pixels na unsigned char * ... może jakaś konwersja? bo można zrobić ręcznie dwie pętly jedna w drugiej ale to zwolni delikatnie na ogółe ....

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

napisałem wstępnie tak funkcje moją TextOutXY:

Kopiuj
void TextOutXY(int x, int y, char* data,int red,int green,int blue)
{

	SetTextColor(mydc, RGB(red, green, blue));
	SetBkMode(mydc, TRANSPARENT);
	TextOut(mydc, x, y, data, strlen(data));
	SetBkMode(mydc, OPAQUE);

	SIZE textSize;
	GetTextExtentPoint32(mydc, data, strlen(data), &textSize);
	Box2d(x, y, x + textSize.cx, y + textSize.cy);

	std::vector<RGB> pixels;
	GetPixelsFromScreen(mydc, x, y, textSize.cx, textSize.cy, pixels);
	
	//RGB pixel = pixels[100 * 1920 + 100]; // Piksel w (100, 100)
	// pixel.red, pixel.green, pixel.blue
     for (int xp = 0; xp < textSize.cx; xp += 1)
     {
	for (int yp = 0; yp < textSize.cy; yp += 1)
	{
		//(px * 3 + (h - py) * w * 3);
		int index = (xp * textSize.cx + yp* textSize.cy);
		RGB pixel = pixels[index];
		Color3iT(pixel.red, pixel.green, pixel.blue);
		PutPixelT(xp+x ,yp+y);
	}
    }
	
	
}

ale coś jeszcze jest źle nie chce działać właściwie, pomocy!screenshot-20251017163049.png

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

tBane sprawdź funkcje TextOutXY i napraw jak potrafisz DrawConsole.rar

tBane
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 526
0

Powinieneś dodać jakąś alphę do koloru jak chcesz przezroczystość. Tutaj zrobiłem w ten sposób, że gdy kolor jest czarny to go nie renderuje. Nie mogę Ci za bardzo pomóc, bo nie znam się na tym. Ja to tylko C++ i SFML znam :-)

Kopiuj
if (!(pixel.red == 0 && pixel.green == 0 && pixel.blue == 0)) {
  Color3iT(pixel.red, pixel.green, pixel.blue);
  PutPixelT(xp + x, yp + y);
}

screenshot-20251017171821.png

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

kiedyś pisałem czytnik skryptów języka C to jest tylko faza pozątkowa na razie dałem sobie spokój, obczaj to:
token.cpp

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

tutaj jest błąd z pobraniem indexu:

Kopiuj
for (int xp = 0; xp < textSize.cx; xp += 1)
{
	for (int yp = 0; yp < textSize.cy; yp += 1)
	{
		//(px * 3 + (h - py) * w * 3);
		int index = (xp * textSize.cx + yp);
		RGB pixel = pixels[index];
		Color3iT(pixel.red, pixel.green, pixel.blue);
		PutPixelT(xp+x ,yp+y);
	}
}

jakie obliczenie należy zapodać do zmiennej index?

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

dlaczego nie ma napisu czy to moja wina zła kolejność funkcji operacyjnych:

Kopiuj
unsigned char *RenderTextToBuffer(int x,int y,int width, int height, char *text,int red,int green,int blue)
{

	// Ustaw informacje o bitmapie (top-down, 32 bity)
	BITMAPINFO bmi = { 0 };
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biWidth = width;
	bmi.bmiHeader.biHeight = -height;  // top-down bitmapa
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = 32;
	bmi.bmiHeader.biCompression = BI_RGB;

	void* dibBits = nullptr;

	HDC hdcScreen = GetDC(myconsole);
	HDC hdcMem = CreateCompatibleDC(hdcScreen);

	// Stwórz DIBSection, przypisz dane do `dibBits`
	HBITMAP hBitmap = CreateDIBSection(hdcMem, &bmi, DIB_RGB_COLORS, &dibBits, NULL, 0);
	

	HGDIOBJ oldBitmap = SelectObject(hdcMem, hBitmap);

	// Wyczyść bufor - biały kolor
	HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));
	RECT rect = { 0, 0, width, height };
	FillRect(hdcMem, &rect, hBrush);
	DeleteObject(hBrush);

	// Wybierz font
	HFONT hFont = CreateFont(64, 32, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET, OUT_DEFAULT_PRECIS, CLIP_CHARACTER_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, (char*)("Arial"));
	SelectObject(hdcMem, hFont);

	// Kolor i tryb tła
	SetBkMode(hdcMem, TRANSPARENT);
	SetTextColor(hdcMem, RGB(red, green, blue));  // czarny
	

	// Narysuj tekst
	TextOut(hdcMem, x, y, text, strlen(text));
	unsigned char* buffer = new unsigned char[width * height * 4];
	// Skopiuj dane do naszego bufora
	memcpy(buffer, dibBits, width * height * 4);  // 4 bajty na piksel

	// Sprzątanie
	SelectObject(hdcMem, oldBitmap);
	DeleteObject(hFont);
	DeleteObject(hBitmap);
	DeleteDC(hdcMem);
	ReleaseDC(NULL, hdcScreen);

	return buffer;
}

void TextOutXY(int x, int y, char* data,int red,int green,int blue)
{

	/*SetTextColor(mydc, RGB(red, green, blue));
	SetBkMode(mydc, TRANSPARENT);
	TextOut(mydc, x, y, data, strlen(data));
	SetBkMode(mydc, OPAQUE);*/

	SIZE textSize;
	GetTextExtentPoint32(mydc, data, strlen(data), &textSize);
	Box2d(x, y, x + textSize.cx, y + textSize.cy);

	unsigned char* image = new unsigned char[textSize.cx * textSize.cy * 4];
	image=RenderTextToBuffer(x, y, textSize.cx, textSize.cy, data, red, green, blue);
		for (int xp = 0; xp < textSize.cx; xp += 1)
		{
			for (int yp = 0; yp < textSize.cy; yp += 1)
			{
				//(px * 3 + (h - py) * w * 3);
				//uint32_t pixel = image[yp * textSize.cx + xp];
				//uint8_t r = (pixel >> 16) & 0xFF;
				//uint8_t g = (pixel >> 8) & 0xFF;
				//uint8_t b = pixel & 0xFF;
				int index = xp*4+ yp* textSize.cx*4;
				Color3iT(image[index], image[index+1], image[index+2]);
				//Color3iT(r, g, b);
				PutPixelT(xp+x ,yp+y);
			}
		}

		delete[]image;
}

co jest źle tło jest czarne jak jest ustawione a napisu nie widać :/
screenshot-20251018093023.png

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
1

już mm skończyłem wersja full działająca:

Kopiuj
	unsigned char *RenderTextToBuffer(int x,int y,int width, int height, char *text,int red,int green,int blue)
	{

		// Ustaw informacje o bitmapie (top-down, 32 bity)
		BITMAPINFO bmi = { 0 };
		bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
		bmi.bmiHeader.biWidth = width;
		bmi.bmiHeader.biHeight = -height;  // top-down bitmapa
		bmi.bmiHeader.biPlanes = 1;
		bmi.bmiHeader.biBitCount = 32;
		bmi.bmiHeader.biCompression = BI_RGB;

		void* dibBits = nullptr;

		HDC hdcScreen = GetDC(NULL);
		HDC hdcMem = CreateCompatibleDC(hdcScreen);

		// Stwórz DIBSection, przypisz dane do `dibBits`
		HBITMAP hBitmap = CreateDIBSection(hdcMem, &bmi, DIB_RGB_COLORS, &dibBits, NULL, 0);
		

		HGDIOBJ oldBitmap = SelectObject(hdcMem, hBitmap);

		// Wyczyść bufor
		HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));
		RECT rect = { 0, 0, width, height };
		FillRect(hdcMem, &rect, hBrush);
		DeleteObject(hBrush);

		// Wybierz font
		HFONT hFont = CreateFont(64, 32, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET, OUT_DEFAULT_PRECIS, CLIP_CHARACTER_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, (char*)("Arial"));
		SelectObject(hdcMem, hFont);

		// Kolor i tryb tła
		SetBkMode(hdcMem, TRANSPARENT);
		SetTextColor(hdcMem, RGB(red, green, blue));  
		// Narysuj tekst
		TextOut(hdcMem, x, y, text, strlen(text));
		unsigned char* buffer = new unsigned char[width * height * 4];
		// Skopiuj dane do naszego bufora
		memcpy(buffer, dibBits, width * height * 4);  // 4 bajty na piksel

		// Sprzątanie
		SelectObject(hdcMem, oldBitmap);
		DeleteObject(hFont);
		DeleteObject(hBitmap);
		DeleteDC(hdcMem);
		ReleaseDC(NULL, hdcScreen);

		return buffer;
	}

	void TextOutXY(int x, int y, char* data,int red,int green,int blue)
	{
		SIZE textSize;
		GetTextExtentPoint32(mydc, data, strlen(data), &textSize);

		unsigned char* image = new unsigned char[textSize.cx * textSize.cy * 4];
		image=RenderTextToBuffer(0, 0, textSize.cx, textSize.cy, data, red, green, blue);
			for (int xp = 0; xp < textSize.cx; xp += 1)
			{
				for (int yp = 0; yp < textSize.cy; yp += 1)
				{
					int index = xp*4+ yp* textSize.cx*4;
					if (image[index] != 0 || image[index + 1] != 0 || image[index + 2] != 0)
					{
						Color3iT(image[index], image[index + 1], image[index + 2]);
						PutPixelT(xp + x, yp + y);
					}
				}
			}

			delete[]image;
	}

screenshot-20251018095317.png

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

to jest tak robi buffor podręczny potem rendering napisu do tego buffora potem przeklepanie do buffora centralnego i już nie mruga napis :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.