Zamiana int na string w okienku HWND

0

Witam!

Mam pytanie, tworzyłem okienko w WinApi, utworzyłem uchwyt HWND, i teraz mam problem, bo wartość którą wpisuje do mojego editext oznaczonego jako HA, nie mogę przypisać do funkcji obliczającej deltę w moim programie. I tutaj pojawia się pytanie, jakiej mam funkcji użyć, bo wiem że w C# istnieje funkcja która zamienia tekst wpisany do okienka na string i od razu można przypisać tą wartość do zmiennej np. "a" pojawia się pytanie czy w C++ istnieje również taka funkcja?

0

Może pokaż jakiś kod i opisz co chcesz uzyskać, bo nie za bardzo wiadomo o co chodzi, zwłaszcza w powiązaniu z tematem „zamiana int na string” (a z treści z dużym trudem daje się wywnioskować coś odwrotnego).

0

Dobra a więc po kolei bo sie chyba nie zrozumieliśmy :D

To jest mój kod jeżeli potrzebujecie cały:


#include <Windows.h>
#include <stdlib.h>
#include <iostream>
#include <cstdlib>
#include <string>
#include <sstream>
using namespace std;

#define FILE_MENU_NEW 1
#define FILE_MENU_OPEN 2
#define FILE_MENU_EXIT 3
#define GENERATE_BUTTON 4

#define POBIERZ_A 5
#define POBIERZ_B 6
#define POBIERZ_C 7
#define POBIERZ_D 8

LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);


void AddControls(HWND hWnd);


HWND hName, hAge, hOut, hDel, hA, hB, hOA, hOB, hC, hOC, hD;
HMENU hMenu;



//-------------------------------------------------------------------------------------------------------------------------------------------------------
double licz(double a, double b, double c)
{
	double  delta = (b*b) - (4 * a*c);
	return delta;
}





int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow)
{


	WNDCLASSW wc = { 0 };

	wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hInstance = hInst;
	wc.lpszClassName = L"Funkcja Kwadratowa";
	wc.lpfnWndProc = WindowProcedure;

	if (!RegisterClassW(&wc))
		return -1;


	HWND hwnd = CreateWindow("Funkcja Kwadratowa",
		"Tytul",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		1200, 700,
		NULL,
		NULL,
		hInst,
		NULL);

	ShowWindow(hwnd, ncmdshow);
	UpdateWindow(hwnd);

	MSG msg = { 0 };

	while (GetMessage(&msg, NULL, NULL, NULL))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}


	return 0;
}


LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{



	switch (msg)
	{
	case WM_COMMAND:
		switch (wp)
		{

		case GENERATE_BUTTON:

			double a;
			double b;
			double c;
			double delta = 0;

			//delta = licz(a, b, c);


			

		}
		break;
	case WM_CREATE:

		AddControls(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return	DefWindowProcW(hWnd, msg, wp, lp);
	}





}


void AddControls(HWND hWnd)
{
	hA = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "a", WS_CHILD | WS_VISIBLE | WS_BORDER, 20, 60, 50, 30, hWnd, NULL, NULL, NULL);
	hB = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "b", WS_CHILD | WS_VISIBLE | WS_BORDER, 80, 60, 50, 30, hWnd, NULL, NULL, NULL);
	hC = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "c", WS_CHILD | WS_VISIBLE | WS_BORDER, 140, 60, 50, 30, hWnd, NULL, NULL, NULL);
hOut = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, 200, 60, 50, 30, hWnd, NULL, NULL, NULL);
CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", "Obliczanie", WS_CHILD | WS_VISIBLE | WS_BORDER, 20, 100, 150, 30, hWnd, (HMENU)GENERATE_BUTTON, NULL, NULL);


}


I teraz może będzie łatwiej mi wytłumaczyć, otóż chodzi mi o to, że potrzebuje funkcje dzięki której będę mógł przypisać do zmiennej "double a" w przycisku GENERATE_BUTTON, tekst wpisany do okienka hA. Prościej mówiąc, wpisuje tekst do okienka hA, naciskam przycisk oznaczony w kodzie jako "GENERATE_BUTTON", tekst wpisany do okienka zostaje przypisany do zmiennej a, i dzięki temu mogę liczyć delte. Tak wiem mam korzystać z GetWindowText SetWindowText, ale nie umiem pobierać tej wartości z okienka, może ktoś pomoże?

2

1.: Bardzo ciężko będzie Ci pomóc, ponieważ tutaj:

HWND hName, hAge, hOut, hDel, hA, hB, hOA, hOB, hC, hOC, hD;
HMENU hMenu;

większość ludzi przestaje czytać...

2. Niepotrzebnie wrzucasz cały kod. Wrzuć fragmenty powiązane z problemem, który opisujesz.

3. W jaki sposób chcesz utworzyć funkcję, którą przypiszesz do zmiennej typu double? Może chodzi Ci o wskaźnik do funkcji, tak?

4. Co do tego fragmentu:

tekst wpisany do okienka zostaje przypisany do zmiennej a

można to zrobić choćby wykorzystując funkcję GetWindowText, do której podajesz okienko/kontrolkę z której chcesz ten tekst wczytać, bufor do którego chcesz tekst wczytać oraz długość tekstu.
Na przykład tak:

void WindowC::ReadFrame( const MainControlls_t textFrame )
{
    wchar_t* tmpTextBuffer = new wchar_t[ MAX_USER_DATA_TEXT_LENGTH ];
    memset( tmpTextBuffer, '\0', MAX_USER_DATA_TEXT_LENGTH );
    GetWindowText( controlls.at( textFrame ), tmpTextBuffer, MAX_USER_DATA_TEXT_LENGTH );

    // Put the tmpTextBuffer into the desired string variable

    delete[] tmpTextBuffer;
}

Mam nadzieję, że odpowiedziałem na Twoje pytanie. Jeśli nie, to doprecyzuj, bo w tej chwili trochę ciężko zrozumieć gdzie dokładnie utknąłeś.

0

Dobrze to wrzucając fragmentami:

w zmiennych globalnych mam utworzoną funkcje liczącą deltę:

double licz(double a, double b, double c)
{
	double  delta = (b*b) - (4 * a*c);
	return delta;
}

teraz żeby ją obliczyć muszę mieć liczby, liczby muszę pobrać z okienka które są utworzone tutaj:

void AddControls(HWND hWnd)
{
	hA = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "a", WS_CHILD | WS_VISIBLE | WS_BORDER, 20, 60, 50, 30, hWnd, NULL, NULL, NULL);
	hB = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "b", WS_CHILD | WS_VISIBLE | WS_BORDER, 80, 60, 50, 30, hWnd, NULL, NULL, NULL);
	hC = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "c", WS_CHILD | WS_VISIBLE | WS_BORDER, 140, 60, 50, 30, hWnd, NULL, NULL, NULL);
	hOut = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, 200, 60, 50, 30, hWnd, NULL, NULL, NULL);
	 CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", "Obliczanie", WS_CHILD | WS_VISIBLE | WS_BORDER, 20, 100, 150, 30, hWnd, (HMENU)GENERATE_BUTTON, NULL, NULL);


}

a teraz główny problem jest przy tworzeniu przycisku GENERATE_BUTTON który w kodzie wygląda na ten moment tak:

switch (msg)
	{
	case WM_COMMAND:
		switch (wp)
		{

		case GENERATE_BUTTON:

			double a;
			double b;
			double c;
			double delta = 0;

			//delta = licz(a, b, c)
		}
		break;

i o to mi chodzi że nie umiem odpowiednio zaprogramować przycisku tak, żeby po naciśnięciu liczył mi delte i wyprowadzał tą deltę w okienku hOut.

Główny problem dla mnie to jest pobieranie tekstu właśnie do zmiennej określonej w przycisku jako double a, double b, double c, ponieważ GetWindowText umie pobierać znaki ale tylko do zmiennych typu char, a tutaj mam double bo potrzebuje double, i to jest ten główny problem, po prostu liczenie delty za pomocą przycisku.

0

Rozumiem, że Twój problem to jedynie zrobienie z przykładowego tekstu: 1 + 2 + 3 = x kolejnych zmiennych typu double równych a == 1, b == 2, c == 3.

Jeśli tak, to sprawa jest prosta: Iteruj po znakach w Twoim ciągu char lub string, jeśli rozpoznasz coś, co jest cyfrą iteruj aż do napotkania czegoś innego niż cyfra lub kropka. Zapisuj znaki z iteracji do osobnego ciągu, który na koniec przekonwertujesz na typ double funkcją standardową atof().

Całość kontynuuj aż do napotkania końca całego ciągu pobranego z kontrolki, lub do momentu, aż osiągniesz maksymalną długość tekstu z kontrolki.

To tyle. Sposób, który podałem jest trochę łopatologiczny, ale wykorzystując string zamiast char powinno być to odrobinę prostsze.

0

No dokładnie to będzie działało tak że do okienka hA wpisujesz pierwszą liczbę do okienka hB drugą liczbę do okienka hC trzecią liczbę, naciskam przycisk oblicz czyli ten GENERATE_BUTTON po czym on wykonując funkcje w sobie liczy mi deltę która pokazuje się w okienku hOut no łatwiej tego opisać nie potrafię :D Moje hA to tak jakby x^2 hB to x a hC to wyraz wolny w funkcji kwadratowej :D

0

Ponieważ nie używasz przecinków, ani znaków interpunkcyjnych, stawiam je sobie sam w Twojej wypowiedzi i wierz mi lub nie - za każdym razem rozumiem Twój post zupełnie inaczej ;)


A tak na poważnie:
Chcesz mieć trzy okienka wejściowe, w które wpisujesz jedynie liczby typu double.
Każde z tych okienek określa Ci wyrazy w funkcji: a, b oraz c.

To maksymalnie upraszcza problem. Chwytasz kontrolkę z a, odczytujesz tekst jako ciąg typu char lub string a następnie wykonujesz konwersję ciągu do typu float funkcją atof().
Nic prostszego nie jestem w stanie Ci powiedzieć - Twój problem wydaje się być banalny.

0

Ooooo dokładnie @Bartosz36! Właśnie mam ten problem. I nie wiem jak go rozwiązać, bo przez "chwycenie" kontroli z "a", masz na myśli użycie funkcji GetWindowText, czy może istnieje jakaś łatwiejsza funkcja? Konwersje do float umiem zrobić, bo to znalazłem już tutaj na forum. Najgorszy mam problem właśnie z tym odczytaniem tekstu jako ciąg typu char lub string? Jak tego dokonać? Możesz mi pomóc?

0

Przecież już Ci dwa razy pomogłem ;)

Tak. Mam na myśli GetWindowText(), lub jej pochodne (z dopiskiem A, lub W w nazwie).
Utwórz bufor tymczasowy tak jak w moim kodzie z któregoś posta, wrzuć go do funkcji GetWindowText().
Następnie przekonwertuj - to tyle.

2
Bartosz36 napisał(a):

2. Niepotrzebnie wrzucasz cały kod. Wrzuć fragmenty powiązane z problemem, który opisujesz.

Akurat dobrze, że wrzucił cały, bo w przykładach do WinAPI roi się od błędów - i są to zwykle te same błędy.

Krispi One napisał(a):
HWND hName, hAge, hOut, hDel, hA, hB, hOA, hOB, hC, hOC, hD;
HMENU hMenu;

Większość z tego (albo nawet wszystkie) wcale nie musi być zmiennymi globalnymi.

	wc.hbrBackground = (HBRUSH)COLOR_WINDOW;

Do koloru podanego przez stałą trzeba tu dodać 1. Dlaczego? Bo dokumentacja RegisterClass tak mówi.
To znaczy że to co widzisz to nie jest COLOR_WINDOW. Prawidłowo powinno być `(HBRUSH)(COLOR_WINDOW + 1);

	wc.lpszClassName = L"Funkcja Kwadratowa";

	HWND hwnd = CreateWindow("Funkcja Kwadratowa",

Dwa razy używasz takiego samego magic stringa. Zdefiniuj jako stałą albo w CreateWindow jako klasy użyj tego co zwraca ci RegisterClass.

EDIT:

ATOM atom = RegisterClass( ... );
HWND hwnd = CreateWindow(MAKEINTATOM(atom), ... );

w ten sposób nie potrzebujesz ani powtarzać nazwy klasy, ani nawet nie trzeba definiować stałej. w dodatku jeśli RegisterClass zwróci NULL to CreateWindow zwróci NULL, więc nie musisz sprawdzać wyniku RegisterClass.

0

Mam jeszcze jeden problem może ktoś mi pomoże go rozwiązać, stworzyłem taki oto przycisk:


case GENERATE_BUTTON:

			double a = 0;
			string as = to_string(a);
			char * cas = new char[as.length() + 1];
			strcpy_s(cas, as.length()+1, as.c_str());
			GetWindowTextA(hA, cas, as.length() + 1);
			
			double b = 0;

			std::string bs = std::to_string(b);
			char * cbs = new char[bs.length() + 1];
			strcpy_s(cbs, bs.length() + 1, bs.c_str());

			GetWindowTextA((HWND)hB, cbs, bs.length() + 1);

			double c = 0;

			std::string cs = std::to_string(c);
			char * ccs = new char[cs.length() + 1];
			strcpy_s(ccs, cs.length() + 1, cs.c_str());

			GetWindowTextA((HWND)hC, ccs, cs.length() + 1);

			double delta = 0;

			delta = licz(a, b, c);

			std::string ds = std::to_string(delta);
			char * cds = new char[ds.length() + 1];
			strcpy_s(cds, ds.length() + 1, ds.c_str());

			SetWindowTextA((HWND)hOut, cds);

		}
		break;

Co ciekawe po naciśnięciu liczy Delte, czyli jest efekt który chciałem otrzymać, ale właśnie mam problem że jest gdzieś błąd w kodzie że liczy deltę tylko dla lprzypisanych wartości czyli dla

double a =0; double b = 0; double c = 0;

Co muszę zmienić/dodać, żeby zmienić wartość z 0 na wartość którą pobiorę z okienka za pomocą GetWindowTextA?

1
            double a = 0;
            string as = to_string(a);
            char * cas = new char[as.length() + 1];
            strcpy_s(cas, as.length()+1, as.c_str());
            GetWindowTextA(hA, cas, as.length() + 1);

Chyba nie rozumiesz co robisz:
- tworzysz double'a o wartości 0
- konwertujesz go na stringa
- zupełnie niepotrzebnie alokujesz innego stringa i kopiujesz tam pierwszego stringa
- pobierasz tekst kontrolki do tego drugiego stringa
- nie zwalniasz pamięci zaalokowanej przez new co powoduje wyciek pamięci.

W którą stronę to ma być operacja? To ma być w końcu pobranie tekstu z kontrolki czy wpisanie do niej tekstu?
1

Co muszę zmienić/dodać, żeby zmienić wartość z 0 na wartość którą pobiorę z okienka za pomocą GetWindowTextA?

Tak jak pisałem Ci już w dwóch innych postach:
1. Przygotowujesz sobie tymczasowy bufor w postaci ciągu char.
2. Wrzucasz go do funkcji GetWindowText(), aby ta funkcja zapisała do niego ciąg tekstowy z okienka
3. Otrzymany ciąg char przechowuje obecnie to, co wpisałeś w okienku - musisz to teraz przekonwertować do typu float. Wykorzystaj do tego na przykład atof().

W tym momencie wartość zmiennej została zmieniona z inicjalizacyjnej wartości 0 na wartość wpisaną do okienka.

0

Panowie dziękuję bardzo za pomoc, problem rozwiązany stworzyłem przycisk w pełni funkcjonalny nie ma z nim problemów ;) liczy wszystko ładnie, pomieszane bo trochę string, trochę char ale działa poniżej kod:

case GENERATE_BUTTON:

			double a;
			char bufor[100];
			GetWindowTextA(hA, bufor, 100);
			a = atof(bufor);

			double b;
			char bufor1[100];
			GetWindowTextA(hB, bufor1, 100);
			b = atof(bufor1);

			double c;
			char bufor2[100];
			GetWindowTextA(hC, bufor2, 100);
			c = atof(bufor2);

			double delta = 0;
			delta = licz(a, b, c);
			std::string ds = std::to_string(delta);
			char * cds = new char[ds.length() + 1];
			strcpy_s(cds, ds.length() + 1, ds.c_str());
			SetWindowTextA((HWND)hOut, cds);

			if (delta > 0)
			{
				double x1 = 0;
				x1 = jeden(delta, b, a);
				std::string xs = std::to_string(x1);
				char * cxs = new char[xs.length() + 1];
				strcpy_s(cxs, xs.length() + 1, xs.c_str());
				SetWindowTextA((HWND)hX, cxs);

				double x2 = 0;
				x2 = dwa(delta, b, a);
				std::string zs = std::to_string(x2);
				char * czs = new char[zs.length() + 1];
				strcpy_s(czs, zs.length() + 1, zs.c_str());
				SetWindowTextA((HWND)hX2, czs);			
			}

			if (delta == 0)
			{
				double x0 = 0;
				x0 = zero(b, a);
				std::string ys = std::to_string(x0);
				char * cys = new char[ys.length() + 1];
				strcpy_s(cys, ys.length() + 1, ys.c_str());
				SetWindowTextA((HWND)hX0, cys);
			}

			if (delta < 0)
			{
				MessageBox(hWnd, "Delta mniejsza od zera. \n Brak miejsc zerowych", "Uwaga!!!", MB_ICONINFORMATION);
			}

		}
		break;

A tak poza tematem panowie, wiecie w jaki sposób czyścić okienko wypełnione daną wartością, bo np. liczę X0 i jak robię drugą funkcje co liczy miejsca X1 i X2, to X0 się nie kasuje, kasuje się dopiero po wypełnieniu go inną wartością ;) :D.

I jeszcze jedno pytanie, ale to pewnie będę musiał otworzyć nowy temat, ale może miał ktoś z was styczność, to podpowiecie mi, za pomocą jakiej funkcji/biblioteki, będę mógł narysować wykres? Bo jeszcze do tej delty muszę narysować wykres, ale jestem zielony w tym temacie i nawet nie wiem czego się chwycić żeby się co nieco przyuczyć ;)

Jeszcze raz dziękuję za pomoc i cierpliwość ;)

0
Krispi One napisał(a):
               std::string xs = std::to_string(x1);
               char * cxs = new char[xs.length() + 1];
               strcpy_s(cxs, xs.length() + 1, xs.c_str());
               SetWindowTextA((HWND)hX, cxs);

Ale po co kopiujesz tego stringa? Na dodatek gubisz pamięć, bo masz new a nie masz delete.

std::string xs = std::to_string(x1);
SetWindowTextA(hX, xs.c_str());
0

Cieknie z tego kodu jak przez sito:

char * czs = new char[zs.length() + 1];
strcpy_s(czs, zs.length() + 1, zs.c_str());
SetWindowTextA((HWND)hX2, czs);


Po co ten `new` i `strcpy`? Tak:
```cpp
SetWindowTextA((HWND)hX2, zs.c_str()); 

nie wystarczy?

Po co definiujesz bufor1 i bufor2, skoro możesz spokojnie wykorzystać bufor?

0

Dziękuję bardzo panowie za porady, błędy poprawione już nie ma tych błędnych funkcji, jak i również korzystam z jednego buforu ;) poniżej kod, macie może jeszcze jakieś uwagi?

case GENERATE_BUTTON:

			double a;
			char bufor[100];
			GetWindowTextA(hA, bufor, 100);
			a = atof(bufor);

			double b;
			GetWindowTextA(hB, bufor, 100);
			b = atof(bufor);

			double c;
			GetWindowTextA(hC, bufor, 100);
			c = atof(bufor);

			double delta = 0;
			delta = licz(a, b, c);
			std::string ds = std::to_string(delta);
			SetWindowTextA((HWND)hOut, ds.c_str());

			if (delta > 0)
			{
				double x1 = 0;
				x1 = jeden(delta, b, a);
				std::string xs = std::to_string(x1);
				SetWindowTextA((HWND)hX, xs.c_str());

				double x2 = 0;
				x2 = dwa(delta, b, a);
				std::string zs = std::to_string(x2);
				SetWindowTextA((HWND)hX2, zs.c_str());			
			}

			if (delta == 0)
			{
				double x0 = 0;
				x0 = zero(b, a);
				std::string ys = std::to_string(x0);
				SetWindowTextA((HWND)hX0, ys.c_str());
			}

			if (delta < 0)
			{
				MessageBox(hWnd, "Delta mniejsza od zera. \n Brak miejsc zerowych", "Uwaga!!!", MB_ICONINFORMATION);
			}

		}
		break;
0

Możesz nieco skrócić:

auto get_as_double = [] (HWND h) -> double {
		char bufor[100];
		GetWindowTextA(h, bufor, 100);
		return atof(bufor);
	};

double a = get_as_double(hA);
double b = get_as_double(hB);
double c = get_as_double(hC);


double delta = licz(a, b, c);
SetWindowTextA((HWND)hOut, std::to_string(delta).c_str());

if (delta > 0)
{
	double x1 = jeden(delta, b, a);
	SetWindowTextA((HWND)hX, std::to_string(x1).c_str());

	double x2 = dwa(delta, b, a);
	SetWindowTextA((HWND)hX2, std::to_string(x2).c_str());          
}

if (delta == 0)
{
	double x0 = zero(b, a);
	SetWindowTextA((HWND)hX0, std::to_string(x0).c_str());
}

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