[C++] Problem z wyświetleniem okna WINAPI


(Lord Nightmarek) #1

Po 2 dniach eksperymentów z kodem, przekopywania MSDN, czytania ze zrozumieniem poradnika : odpuściłem. Możecie mi pomóc w tej sprawie?

#define WIN32_LEAN_AND_MEAN

#define WINAPI __stdcall

#include 

#include 


std::string g_strKlasaOkna;

LRESULT CALLBACK WindowProc(HWND hOkno, UINT uMsg, WPARAM wParam, LPARAM lParam) 

{ 

	switch (uMsg) 

	{ 

		case WM_DESTROY: 

		// kończymy program 

		PostQuitMessage (0); 

		return 0; 

	} 

	return DefWindowProc(hOkno, uMsg, wParam, lParam);

}

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{	

	/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/gotoBEGINNING:/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

	UINT uDecyzja = MessageBox(NULL, (LPCTSTR)"Chcesz sie nauczyc programować?", (LPCTSTR)"Pytanie", MB_TOPMOST | MB_YESNO | MB_ICONQUESTION | MB_SYSTEMMODAL);


	switch(uDecyzja)

	{

	case IDYES:{MessageBox(NULL, (LPCTSTR)"No to ok, jedziemy dalej!", (LPCTSTR)"Komunikat", MB_OK | MB_ICONINFORMATION);};

		goto gotoREALWND;

	case IDNO:{UINT MsgIDNO = MessageBox(NULL, (LPCTSTR)"Więc nie zrozumiesz nigdy PC buahahaha", (LPCTSTR)"Error", MB_ABORTRETRYIGNORE | MB_ICONERROR);

				switch (MsgIDNO)

				{

				case IDABORT:

					break;

				case IDRETRY:{goto gotoBEGINNING;}

					break;

				case IDIGNORE:{MessageBox(NULL, (LPCTSTR)"Powrót", (LPCTSTR)"Powrót", MB_OK | MB_ICONEXCLAMATION);};

					goto gotoBEGINNING;

				}

			  };

	}

	/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/gotoREALWND:/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

	WNDCLASSEX hOknoc;

		ZeroMemory(&hOknoc, sizeof(WNDCLASSEX));

		hOknoc.cbSize = sizeof(WNDCLASSEX);

		hOknoc.style = CS_DROPSHADOW;

		hOknoc.lpfnWndProc = WindowProc;

		hOknoc.cbClsExtra = NULL;

		hOknoc.cbWndExtra = NULL;

		hOknoc.hInstance = hinstance;

		hOknoc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

		hOknoc.hCursor = LoadCursor(NULL, IDC_ARROW);

		hOknoc.hbrBackground = (HBRUSH) COLOR_WINDOW;

		hOknoc.lpszMenuName = NULL;

		hOknoc.lpszClassName = g_strKlasaOkna.c_str();

		hOknoc.hIconSm = NULL;


		// rejestrujemy klasę okna 

		RegisterClassEx (&hOknoc); 


												/* tworzymy okno */ 

		// tworzymy okno funkcją CreateWindowEx 

		HWND hOkno; 

		hOkno = CreateWindowEx(NULL, // rozszerzony styl 

								g_strKlasaOkna.c_str(), // klasa okna 

								"REALWND", // tekst na p. tytułu 

								WS_OVERLAPPEDWINDOW, // styl okna 

								CW_USEDEFAULT, // współrzędna X 

								CW_USEDEFAULT, // współrzędna Y 

								CW_USEDEFAULT, // szerokość

								CW_USEDEFAULT, // wysokość

								NULL, // okno nadrzędne 

								NULL, // menu 

								hinstance, // instancja aplikacji 

								NULL); // dodatkowe dane 

		///////////////////////////////////////// pokazujemy nasze okno /////////////////////////////////////////////

		ShowWindow (hOkno, nCmdShow); 

												/* pętla komunikatów */  

		uDecyzja = MessageBox(NULL, (LPCTSTR)"Naciśnij ok aby zakończyc program", (LPCTSTR)"Komunikat", MB_OK);


		MSG uMsg;


		if (uDecyzja = IDOK)

		{

			TranslateMessage(&uMsg);

			DispatchMessage(&uMsg);

		}


		while(GetMessage(&uMsg, NULL, 0, 0) > 0)

		{

			TranslateMessage(&uMsg);

			DispatchMessage(&uMsg);

		}


		return uMsg.wParam;


		// zwracamy kod wyjścia 

}

Program nie wyświetla okna, przy kompilacji w krokach (F11/F10) kompilator po prostu "prześlizguje" się po funkcji ShowWindow nie wywołując okna, a następnie wchodzi w pętlę wiadomości i... trzeba wyłączyć sam proces w menedżerze. Win7 x64, VS C++ 2010 Express. Warunek if przed pętlą while na końcu to tylko mój manualny sposób WM_DESTROY. Aha, MessageBox'y to tylko takie małe "ćwiczenie" logiczne :smiley: Korzystam z megatutoriala Xion'a tylko że nawet jego kod po kompilacji ma błędy o.0 Wyczyszczony kod:

#define WIN32_LEAN_AND_MEAN

#define WINAPI __stdcall

#include 


const char* WndClass;

LRESULT CALLBACK WindowProc(HWND hOkno, UINT uMsg, WPARAM wParam, LPARAM lParam) 

{ 

	switch (uMsg) 

	{ 

		case WM_DESTROY: 

		// kończymy program 

		PostQuitMessage (0); 

		return 0; 

	} 

	return DefWindowProc(hOkno, uMsg, wParam, lParam);

}


int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{	

	WNDCLASSEX hOknoc;

		ZeroMemory(&hOknoc, sizeof(WNDCLASSEX));

		hOknoc.cbSize = sizeof(WNDCLASSEX);

		hOknoc.style = CS_DROPSHADOW;

		hOknoc.lpfnWndProc = WindowProc;

		hOknoc.cbClsExtra = NULL;

		hOknoc.cbWndExtra = NULL;

		hOknoc.hInstance = hinstance;

		hOknoc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

		hOknoc.hCursor = LoadCursor(NULL, IDC_ARROW);

		hOknoc.hbrBackground = (HBRUSH) COLOR_WINDOW;

		hOknoc.lpszMenuName = NULL;

		hOknoc.lpszClassName = WndClass;

		hOknoc.hIconSm = NULL;


		// RegisterClassEx

		RegisterClassEx (&hOknoc); 


												/* tworzymy okno */ 

		// CreateWindowEx 

		HWND hOkno; 

		hOkno = CreateWindowEx(NULL, // rozszerzony styl 

								WndClass, // klasa okna 

								"Main_Window", // tekst na p. tytułu 

								WS_VISIBLE, // styl okna 

								CW_USEDEFAULT, // współrzędna X 

								CW_USEDEFAULT, // współrzędna Y 

								CW_USEDEFAULT, // szerokość

								CW_USEDEFAULT, // wysokość

								NULL, // okno nadrzędne 

								NULL, // menu 

								hinstance, // instancja aplikacji 

								NULL); // dodatkowe dane 

		///////////////////////////////////////// ShowWindow /////////////////////////////////////////////

		ShowWindow (hOkno, nCmdShow); 

												/* pętla komunikatów */  

		MSG uMsg;

		while(GetMessage(&uMsg, NULL, 0, 0))

		{

			TranslateMessage(&uMsg);

			DispatchMessage(&uMsg);

		}


		return uMsg.wParam;


}

Próbowałem też nadać wartość ShowWindow(hOkno, nCmdShow == SW_SHOW) oraz SW_SHOWNORMAL i nic...


(Wojtekbogocki) #2

o.O ale namieszane, może od początku:

  1. odnośnie 'manualnego sposobu na WM_DESTROY' -> http://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx

  2. Sprawdź warunki w blokach if, w szczególności zwróć uwagę na znak równości :stuck_out_tongue_winking_eye:

  3. Polskie nazwy w C++, masakra, strasznie razi

  4. Formatowanie kodu... uh do poprawki

  5. Czemu g_strKlasaOkna jest typu std::string zamiast po prostu const char*

  6. Nawet nie masz tam sprawdzania błędów, wartości zwracanych przez funkcje.... Nic -.-

Przemyśl ten kod jeszcze raz na spokojnie, nie gmatwaj tak, popoprawiaj, usuń zbędne if'y i MessageBox'y, potem poszukaj więcej bugów bo na pewno wszystkiego tu nie wymieniłem

Ps.

Za jakiego tutoriala korzystałeś?


(Rolek0) #3

Ja bym na początek radził nauczyć się C++ albo w ogóle zacząć od czegoś prostszego np. jakiegoś dialektu BASICa :wink:


(Lord Nightmarek) #4

Microsoft nadał WINAPI taka formę, nie ja.

Pcham się tylko w wywołanie okna, ponieważ to potrzebne w DX SDK. :smiley:

Próbowałem w C#, ale myślę, że w C++ jednak mam lepszą przyszłość (na początek).


(Rolek0) #5

WinAPI to tylko zbiór funkcji i struktur. Brzydki i niedziałajacy kod to wyłącznie twoja wina.

Przykład ładnie sformatowanego i działającego kodu:

#include 

#include 


int g_nWndCount = 0;

HINSTANCE g_hInstance;


static const TCHAR WndClass[] = _T("MySimpleWindowClass");


bool RegWndClass();

HWND NewWindow(int nCmdShow);


int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int nCmdShow)

{

	g_hInstance = hInstance;

	if(!RegWndClass())

		return 1;

	if(!NewWindow(nCmdShow))

		return 1;

	MSG msg = {};

	while(GetMessage(&msg, 0, 0, 0))

	{

		TranslateMessage(&msg);

		DispatchMessage(&msg);

	}

	UnregisterClass(WndClass, hInstance);

	return msg.wParam;

}


HWND NewWindow(int nCmdShow)

{

	HWND hWnd = CreateWindowEx(

		WS_EX_APPWINDOW,

		WndClass,

		_T("Kliknij mnie :)"),

		WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX,

		CW_USEDEFAULT, CW_USEDEFAULT,

		256, 128,

		0,

		0,

		g_hInstance,

		0);

	ShowWindow(hWnd, nCmdShow);

	return hWnd;

}


LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);


bool RegWndClass()

{

	WNDCLASSEX wc =

	{

		sizeof wc,

		CS_DROPSHADOW,

		WndProc,

		0, 0,

		g_hInstance,

		(HICON)LoadImage(0, IDI_ASTERISK, IMAGE_ICON, 0, 0, LR_SHARED),

		(HCURSOR)LoadImage(0, IDC_HAND, IMAGE_CURSOR, 0, 0, LR_SHARED),

		(HBRUSH)COLOR_WINDOW,

		0,

		WndClass,

		wc.hIcon

	};

	return RegisterClassEx(&wc) != 0;

}


LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

	switch(uMsg)

	{

	case WM_CREATE:

		++g_nWndCount;

		break;

	case WM_DESTROY:

		if(!--g_nWndCount)

			PostQuitMessage(0);

		break;

	case WM_CLOSE:

		if(MessageBox(hWnd, _T("Napewno chcesz mnie zamknąć?"), _T("Okienko :)"), MB_ICONQUESTION | MB_YESNO) == IDYES)

			DestroyWindow(hWnd);

		return 0;

	case WM_LBUTTONDOWN:

		NewWindow(SW_SHOW);

		return 0;

	}

	return DefWindowProc(hWnd, uMsg, wParam, lParam);

}