DrawConsole i buttony ;)

DrawConsole i buttony ;)
wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
1

zrobiłem obsługę buttonów, działa myszka i lewy klawisz myszki :)
DrawConsole.rar

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

screenshot-20251020050305.png

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

jeszcze zrobię później obsługę EditBox do pobierania stringów, tak mam w planie 😀

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0
Kopiuj
class BaseButton
{
	public:
		char* name;
		int posX, posY;
		void Set(char* tname, int x, int y)
		{
			name = new char[strlen(tname)];
			name = tname;
			posX = x;
			posY = y;
		}

};
BaseButton bb[100];

void AddButton(char* aname, int x, int y)
{
	bb[totalbutton].Set(aname, x, y);
	totalbutton += 1;
}
void GetPositionAreaConsole(int& x, int& y)
{
	RECT clientRect;
	POINT topLeft;
	GetClientRect(myconsole, &clientRect);
	topLeft.x = clientRect.left;
	topLeft.y = clientRect.top;
	ClientToScreen(myconsole, &topLeft);
	x = topLeft.x;
	y = topLeft.y;
}
void ShowButtons()
	{
		POINT cursor_pos;
		SIZE textSize;
		int xc, yc,xm,ym;
		GetCursorPos(&cursor_pos);
		xm = cursor_pos.x;
		ym = cursor_pos.y;
		GetPositionAreaConsole(xc, yc);
		for (int i = 0; i < totalbutton; i += 1)
		{
			if(xm>=xc+ bb[i].posX && ym>=yc+ bb[i].posY &&
				xm< xc + bb[i].posX+276 && ym < yc + bb[i].posY + 70)
			DrawObiectImage(bb[i].posX, bb[i].posY, id_buttonB);
			else
				DrawObiectImage(bb[i].posX, bb[i].posY, id_buttonA);

			GetTextExtentPoint32(mydc, bb[i].name, strlen(bb[i].name), &textSize);
			int x = bb[i].posX+276/2-float(textSize.cx / 2);
			int y = bb[i].posY+5;

			if (xm >= xc + bb[i].posX && ym >= yc + bb[i].posY &&
				xm < xc + bb[i].posX + 276 && ym < yc + bb[i].posY + 70)
			{
				if (GetAsyncKeyState(VK_LBUTTON) & 0x8000)
				{
					TextOutXY(x, y, bb[i].name, 0, 255, 0);
					checkButton[i] = true;
				}
				else
					TextOutXY(x, y, bb[i].name, 255, 128, 0);
				
			}
			else
				TextOutXY(x, y, bb[i].name, 255, 128, 0);

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

Pobrałem projekt i przyciski m się nie wyświetlają:
screenshot-20251020105602.png

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

to jest nowe archiwum ... pobierz od nowa ten projetk:
DrawConsole.rar

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

Znalazłem Buga. Można nadusić lewy przycisk myszy poza buttonem, następnie przesunąć kursor na button i puścić przycisk myszy, a button wykrywa kliknięcie.
W ogóle za każdym razem gdy przycisk jest naduszony nad przyciskiem to pojawiaa się log, że kliknięto a przecież kliknięcie to naaduszenie lewego przycisku myszy i zwolnienie go nad polem przycisku

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

Wyłączenie trybu edycji w konsoli cmd przy użyciu kodu:

Kopiuj
// Pobierz uchwyt do standardowego wejścia konsoli
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);

// Odczytaj bieżące tryby wejścia
DWORD mode;
GetConsoleMode(hInput, &mode);

// Wyłącz tryb edycji (ENABLE_QUICK_EDIT_MODE) i zaznaczanie myszą
mode &= ~ENABLE_QUICK_EDIT_MODE;
mode &= ~ENABLE_INSERT_MODE;
mode &= ~ENABLE_MOUSE_INPUT;

// Zapisz zmiany
SetConsoleMode(hInput, mode);
wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0

już mam, zrobiłem trochę po swojemu z trybem edycji i naprawiłem buga z buttonem, tutaj projekt:
DrawConsole.rar

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

**Kod przycisku napisany w Python. Chodzi o zasadę działania. **

Przycisk ma parę funkcji podstawowych
-cursorHover() - sprawdza czy kursor jest nad przyciskiem i przypisuje ElementGUI_hovered
-handleEvent() - obsługuje naduszenia i puszczenia myszy i przypisuje ElementGUI_pressed
-update() - aktualizuje przycisk
-draw() - rysuje przycisk

Warto dodać
ElementGUIHovered* - który przycisk jest najechany kursorem. Resetowany (nullptr) na początku pętli - zaraz po tym sprawdzanie cursorHover()
ElementGUIClicked* - który przycisk jest kliknięty - Resetowane (nullptr) po akcji Button::click() na przycisku w Button::update

Button.hpp

Kopiuj
enum class ButtonState { Idle, Hover, Pressed };

class NormalButton {
public:
	sf::RectangleShape _rect;
	Texture* _texture;
	Texture* _hoverTexture;
	sf::Sprite _sprite;

	sf::Vector2f _position;
	
	ButtonState _state;
	std::function<void()> _hover_func;
	std::function<void()> _onclick_func;
	sf::Time _clickTime;


	NormalButton(Texture* texture, Texture* hoverTexture, sf::Vector2f position = sf::Vector2f(0, 0));
	~NormalButton();

	sf::Vector2f getSize();
	void setPosition(sf::Vector2f position);
	void unclick();
	void hover();
	void click();

	void cursorHover();
	void handleEvent(const sf::Event& event);
	void update();
	void draw();

};

Podstawowe Funkcje Dla Buttona

Kopiuj
void NormalButton::unclick() {
	_state = ButtonState::Idle;
	_sprite.setTexture(*_texture->_texture);

	_rect.setFillColor(tools_button_idle_color);
	_rect.setOutlineColor(tools_button_idle_border_color);
	
}

void NormalButton::hover() {
	_state = ButtonState::Hover;
	_sprite.setTexture(*_hoverTexture->_texture);
	_rect.setFillColor(tools_button_hover_color);
	_rect.setOutlineColor(tools_button_hover_border_color);

}

void NormalButton::click() {
	_state = ButtonState::Pressed;
	_sprite.setTexture(*_hoverTexture->_texture);
	_clickTime = currentTime;
	_rect.setFillColor(tools_button_press_color);
	_rect.setOutlineColor(tools_button_press_border_color);
}


void NormalButton::cursorHover() {

	if (_sprite.getGlobalBounds().contains(worldMousePosition)) {
		ElementGUI_hovered = this;
	}


}

void NormalButton::handleEvent(const sf::Event& event) {
	if (_sprite.getGlobalBounds().contains(worldMousePosition)) {
		
		if (const auto* mbp = event.getIf<sf::Event::MouseButtonPressed>(); mbp && mbp->button == sf::Mouse::Button::Left)	{		
			ElementGUI_pressed = this;
		}
		else if (const auto* mbr = event.getIf<sf::Event::MouseButtonReleased>(); mbr && mbr->button == sf::Mouse::Button::Left) {
			if (ElementGUI_pressed == this) {
				click();
			}
		}

	}
}

void NormalButton::update() {

	if (_state == ButtonState::Pressed) {
		if ((currentTime - _clickTime).asSeconds() > 0.05f) {
			if (_onclick_func) {
				_onclick_func();
			}
			ElementGUI_pressed = nullptr;
			unclick();
		}
	}
	else if (ElementGUI_hovered == this) {
		hover();
	}
	else
		unclick();
}

void NormalButton::draw() {
	window->draw(_rect);
	window->draw(_sprite);

}
wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
1
Kopiuj
void DisableModeEditConsole()
{
	const int DISABLE_QUICK_EDIT_MODE = 0x0080;
	const int CHECK_QUICK_EDIT = 0x0040;
	HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
	DWORD prev_mode;
	GetConsoleMode(hInput, &prev_mode);
	SetConsoleMode(hInput, prev_mode & DISABLE_QUICK_EDIT_MODE);
}
wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
1

poprawiona ostatecznie fizyka buttonów, tzn najechanie , przyciśnięcie a potem zwolnięcie i wtedy dopiero następuje właściwe kliknięcie, to jest to o co chodziło tBane , dodałem światło pod strzałkę myszki 😀
projekt: DrawConsole.rar

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0
Kopiuj
	if (draw.checkButtonB[0])
	{
		draw.TextOutXY(0, 0, (char*)"Kliknięto", 255, 128, 0);
		draw.checkButtonB[0] = false;
	}
Kopiuj
void ShowButtons()
{
	POINT cursor_pos;
	SIZE textSize;
	int xc, yc,xm,ym;
	GetCursorPos(&cursor_pos);
	xm = cursor_pos.x;
	ym = cursor_pos.y;
	GetPositionAreaConsole(xc, yc);
	for (int i = 0; i < totalbutton; i += 1)
	{
		if(xm>=xc+ bb[i].posX && ym>=yc+ bb[i].posY &&
			xm< xc + bb[i].posX+276 && ym < yc + bb[i].posY + 70)
		DrawObiectImage(bb[i].posX, bb[i].posY, id_buttonB);
		else
			DrawObiectImage(bb[i].posX, bb[i].posY, id_buttonA);

		GetTextExtentPoint32(mydc, bb[i].name, strlen(bb[i].name), &textSize);
		int x = bb[i].posX+276/2-float(textSize.cx / 2);
		int y = bb[i].posY+5;

		if (xm >= xc + bb[i].posX && ym >= yc + bb[i].posY &&
			xm < xc + bb[i].posX + 276 && ym < yc + bb[i].posY + 70)
		{
			if (GetAsyncKeyState(VK_LBUTTON) & 0x8000)
			{
				TextOutXY(x, y, bb[i].name, 0, 255, 0);
				
				if(checkButton[i]==false)
				checkButton[i] = true;
			}
			else
			{
				TextOutXY(x, y, bb[i].name, 255, 128, 0);
				if (checkButton[i] == true)
				{
					checkButton[i] = false;
					checkButtonB[i] = true;
				}

			}
			
		}
		else
		{
			TextOutXY(x, y, bb[i].name, 255, 128, 0);
			checkButton[i] = false;
			checkButtonB[i] = false;
		}

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

poprawka lepiej widać efekt pojedynczego zwolnienia kliknięcia:
DrawConsole.rar

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

Screenshot z programu uruchomionego na Windows 11 - ne renderuje nic

screenshot-20251021123705.png

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

ChatGPT mowi tak:

Nowoczesne podejście – pseudokonsola (ConPTY)

Jeśli tworzysz własną aplikację z terminalem (np. emulator terminala lub backend), możesz użyć ConPTY:

Kopiuj
// przykład uproszczony; wymaga Windows 10/11 i nagłówków SDK
#include <windows.h>
#include <iostream>
#include <string>

int main() {
    HPCON hPC;
    COORD size = { 80, 25 };

    if (CreatePseudoConsole(size, GetStdHandle(STD_INPUT_HANDLE), GetStdHandle(STD_OUTPUT_HANDLE), 0, &hPC) != S_OK) {
        std::cerr << "Nie udało się utworzyć pseudokonsoli!" << std::endl;
        return 1;
    }

    std::cout << "Pseudokonsola utworzona. PID procesu: " << GetCurrentProcessId() << std::endl;

    // Uwaga: aby w pełni używać ConPTY, trzeba utworzyć dziecko procesu z CreateProcess
    // i odpowiednio skonfigurować strumienie przez pipe'y.

    ClosePseudoConsole(hPC);
    return 0;
}

może to pomoże?

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

wpisz w ChatGPT:
Windows 11 Home i CMD nowy, HWND WINAPI GetConsoleWindow(); jaki jest nowy?

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

Napisał coś takiego ale nie jestem w stanie zweryfikować czy to poprawne:

Świetne pytanie 👍

Funkcja:

Kopiuj
HWND WINAPI GetConsoleWindow();

nadal istnieje i działa normalnie w Windows 11 (Home, Pro, itp.) — nie została usunięta ani zastąpiona.
To oficjalna funkcja WinAPI z biblioteki kernel32.dll, służąca do pobrania uchwytu (HWND) do okna konsoli, jeśli proces go posiada.

📘 Nowości w Windows Terminal / Windows 11

To, co mogło Cię zmylić, to fakt, że w Windows 11 CMD (cmd.exe) i PowerShell domyślnie uruchamiają się wewnątrz Windows Terminala, a nie jako klasyczne okno conhost.exe.

To oznacza, że:

aplikacja nadal ma konsolę, ale

niekoniecznie ma własne okno konsoli, jeśli jest hostowana w Windows Terminal.

W takiej sytuacji:

Kopiuj
HWND hwnd = GetConsoleWindow();

może zwrócić NULL, ponieważ proces nie posiada fizycznego okna konsoli, tylko jest połączony przez kanał pseudokonsoli (pseudoconsole / ConPTY).

🔍 Jeśli chcesz pobrać "nowy" uchwyt konsoli w Windows 11

W nowym modelu (ConPTY) nie ma już jednego prostego HWND.
Nowe API to Pseudoconsole API:

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

HPCON hPC;
CreatePseudoConsole(..., &hPC);

Ale to działa tylko, jeśli sam tworzysz pseudokonsolę — to nowoczesny mechanizm używany np. przez Windows Terminal do hostowania cmd.exe lub PowerShella w jednym oknie.

🔧 Podsumowując:
Funkcja / API Status Działa w Windows 11 Opis
GetConsoleWindow() ✅ Tak, wciąż dostępna Zwraca HWND klasycznego conhost.exe, jeśli istnieje
GetStdHandle(STD_OUTPUT_HANDLE) ✅ Tak Zwraca uchwyt do strumienia konsoli
ConPTY / Pseudoconsole API 🆕 Tak (Windows 10+ i 11) Nowy model konsoli bez HWND, używany w Windows Terminal

Jeśli chcesz, mogę Ci pokazać jak wykryć, czy Twój program działa w klasycznej konsoli (conhost.exe), czy w Windows Terminal (ConPTY).
Chcesz przykład w C++?

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

już lepiej tylko jak porównać kiedy działać po staremu a kiedy w nowej wersji?
jak w Windows Terminal dostać się do HWND? np przez jakąś konwersje?

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

Po aktualizacji Visual Studio do najnowszej wersji 17.14.18 na Windows 11 nadal czarne okno.

screenshot-20251021131609.png

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

tBane mam z ChatGPT, patrz to i sprawdź potem napisz czy działa::

Alternatywa (bez rejestru): ustawienie przez UI (Windows 11)
Jeśli masz Windows 11:
Otwórz Ustawienia
Przejdź do Personalizacja → Pasek zadań → Zachowanie paska zadań
Znajdź opcję Zamień Wiersz polecenia na Windows Terminal, odznacz ją (lub zaznacz – zależnie od wersji).

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

. Otwórz Edytor Rejestru
Wciśnij Win + R, wpisz regedit i naciśnij Enter.
2. Przejdź do klucza:
3. HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
3. Znajdź lub utwórz wartość:
Nazwa: DontUseTerminal
Typ: DWORD (32-bit)
Wartość:
1 – używa CMD zamiast Windows Terminal
0 – domyślnie używa Windows Terminal (lub jeśli brak wartości)
4. Zapisz zmiany i uruchom ponownie Eksploratora Windows:

Możesz też się wylogować i zalogować ponownie lub zrestartować komputer.

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 678
0
Kopiuj
#include <windows.h>

int main() {
    // Uruchamia CMD
    system("start cmd.exe DrawConsole.exe");
    return 0;
}

czy takie coś zadziała?

flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
0

Windows Terminal nie jest zwykłym programem, takim jak klasyczna konsola (conhost) i z tego powodu nie można w nowym terminalu robić takich rzeczy jak dawniej. Ba, nawet systemowe API dotyczące konsoli, w połączeniu z Windows Terminal działa tylko częściowo, natomiast wiele funkcji nie działa w ogóle lub glitchuje okno terminala.

Jeśli chcecie się bawić w starej konsoli, mieć (tak jak dawniej) pełną kontrolę nad oknem konsoli oraz uniezależnić jej tworzenie od systemowych ustawień (terminal vs konsola), to polecam ją alokować dynamicznie. Macie do tego funkcję AllocConsole, która tworzy nowe okno starej konsoli (czyli instancję procesu conhost.exe). Ze starą konsolą można wszystko, bo ma się pełną kontrolę nad jej oknem.

W przypadku Windows 11, cmd.exe nie reprezentuje starej konsoli — to jedynie coś w rodzaju proxy, otwierającego Windows Terminal (wt.exe) lub starą konsolę (conhost.exe), w zależności od ustawień systemowych.

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

robisz aplikacje Run.exe z takim kodem

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

int main()
{
    system("DrawConsole.exe");
}

i umieszczasz do katalogu z plikiem DrawConsole.exe i klikasz tzn włączasz Run.exe pytanie czy włączy się ta aplikacja DrawConsole w CMD classis?

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

tBane sprawdź teraz bo jest dopisana funkcja AllocConsole(void);
DrawConsole.rar

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

Ndal nic nie renderuje
screenshot-20251021151208.png

flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
1

@wilkwielki: w Windows 11, domyślnym hostem konsoli jest Windows Terminal, czyli nowy, wielozakładkowy terminal, nad którym kontrolę ma system, a nie użytkownik. Z oknem nowego terminala nie można robić wszystkiego co się chce — Microsoft to zablokował celowo. Nowy terminal może być używany jako standardowe wyjście/wejście, ale to w sumie tyle.

Żeby twój program uruchomił się w klasycznej konsoli (czyli conhost.exe), użytkownik musi mieć ustawiony Windows Console Host jako domyślną aplikację terminala — a w Windows 11, domyślną jest Windows Terminal. Nie możesz zmuszać użytkownika do zmiany ustawień, aby twój program działał, bo to nieprofesjonalne. To co możesz zrobić, to wymusić użycie klasycznej konsoli.


Pisałem wyżej — jeśli chcesz, aby twój program używał klasycznej konsoli (conhost.exe) na każdej wersji Windowsa i bez względu na ustawienia użytkownika, to ją samodzielnie zaalokuj. Do tego służy funkcja AllocConsole — wywołujesz ją i system tworzy nowe okno konsoli dla twojego procesu.

Jeśli zechcesz użyć konsoli jako standardowe wyjście, to musisz zaktualizować uchwyt stdout, tak aby przekierować wyjście na konsolę. Nie piszę w C++, a we Free Pascalu — cały kod alokacji starej konsoli dla procesu silnika mojej gry to trzy linijki kodu:

Kopiuj
if AllocConsole() then
begin
  IsConsole := True;
  SysInitStdIO();
end;

Jeśli alokacja konsoli powiedzie się, to system stworzy nowe okno konsoli i przyłączy je do procesu mojej gry. Ustawienie flagi IsConsole jest konieczne, natomiast funkcja SysInitStdIO aktualizuje uchwyty wejścia/wyjścia, tak abym mógł logować dane w konsoli np. za pomocą WriteLn. Ale to jest specyficzne dla Free Pascala — w C++ uchwyty trzeba zaktualizować inaczej.


Ty potrzebujesz zrobić to samo. Twój program powinien być GUI, czyli taki, który nie będzie automatycznie tworzył terminala przy rozruchu. Na początku jego funkcji main alokujesz konsolę za pomocą AllocConsole i to tyle. Skoro chcesz malować w oknie, to nie musisz aktualizować uchwytów wejścia/wyjścia.

Z takim oknem konsoli możesz robić wszystko co tylko chcesz, bo masz nad nim pełną kontrolę (nie to co w przypadku Windows Terminal). Uchwyt okna konsoli możesz pobrać za pomocą GetConsoleWindow, uchwyt do menu za pomocą GetSystemMenu itd.

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

to co ja mam napisać na wejściu po funkcji " int main() " w języku C++ ?

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

screenshot-20251021153233.png

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.