Jak utworzyć okno w winapi pozwalające użytkownikowi zmienić rozmiar?

0

Chcę utworzyć okno w c++ w winapi pozwalające zmienić rozmiar za pomocą najechania myszą na krawędź i przeciągnięcia. Standardowe okno. Jednak dając w funkcji CreateWindow styl WS_OVERLAPPEDWINDOW nie uzyskuję pożądanego efektu.

Kod tworzący klasę:

hUchwytInstancji = (HINSTANCE)GetModuleHandle(NULL);

	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = stWndHandler;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = (HINSTANCE)GetModuleHandle(NULL);
	wcex.hIcon = LoadIcon(hUchwytInstancji, MAKEINTRESOURCE(IDI_ASTERISK));
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_GRAYTEXT);
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = lpNazwaKlasy;
	wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ASTERISK));

	if (!RegisterClassEx(&wcex))
	{
		APPLICATION_ERROR_CLASSREG;
	} 

Kod tworzący okno

hUchwytOkna = CreateWindow(
		lpNazwaKlasy,
		lpNazwaOkna,
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		x, y,
		NULL,
		NULL,
		hUchwytInstancji,
		lpInneDane
		);

	if (!hUchwytOkna)
	{
		APPLICATION_ERROR_WINDOWREG;
		return 0;

	} 

Jak to zrobić?

0

Problem nieaktualny - posiadałem drobny błąd w procedurze okna ;)

0

Jednak dając w funkcji CreateWindow styl WS_OVERLAPPEDWINDOW nie uzyskuję pożądanego efektu.

A jaki?

    wcex.hbrBackground = (HBRUSH)(COLOR_GRAYTEXT);

To jest źle. Jeśli chcesz podać stałą COLOR to trzeba dodać do niej 1.

wcex.hbrBackground = (HBRUSH)(COLOR_GRAYTEXT+1);

ale i tak dziwne wydaje mi się używanie koloru tekstu jako koloru tła.

0

To było robione na szybko żeby sprawdzić czy mogę modyfikować atrybuty klasy. Poniekąd rozwiązałem problem otóż odkryłem, że gdy przekazuje przez funkcję CreateWindowEx parametr dodatkowy: (void*)this to okno nie reaguje na polecenia powiększania przez użytkownika (inne wiadomości dochodzą do procedury i są przetworzone prawidło jak np. zamknięcie czy przesunięcie okna). Problem nie istnieje gdy nie przekazuje tego parametru (daje domyślnie 0). Jednak bardzo mi zależy żeby mieć do dyspozycji wskaźnik na konkretny obiekt okna gdyż chcę wywoływać dla poszczególnych instancji klas (obiektów okien) własne NIESTATYCZNE procedury.

Pewnie mam coś skopane w procedurze okna więc ją wklejam

Procedura statyczna w klasie Cokno:

LRESULT CALLBACK Cokno::stWndHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
	Cokno* pWnd = 0;                        // Uchwyt do konkretnego obiektu 
	pWnd = ZwrocObjekt(hwnd);          // metoda inline w klasie Cokno zwracająca obiekt funkcją GetWindowLong
	
	if (pWnd == 0)                            // Jeśli GetWindowLong zwróci 0 (co jest domyślne) wykonuje się podstawowa statyczna procedura
	{
		switch (umsg)
		{
		case WM_NCCREATE:                                                        // Przez WM_NCCREATE pobieramy wskaznik na obiekt this
			SetWindowLong(hwnd, GWL_USERDATA,                                     // przekazany w CreateWindowEx jako parametr
				(long)((LPCREATESTRUCT(lparam))->lpCreateParams));       // i odrazu ustawiamy dodatkowe dane okna
			return TRUE;                                                                         // zwracamy TRUE aby otrzymać uchwyt 
			break;                                                                                     
		default:
			return DefWindowProc(hwnd, umsg, wparam, lparam);                // Gdy pWnd == 0 czyli nie znamy adresu obiektu okna
			break;                                                                                 // domyślna procedura windows
		}
	}
	pWnd->ProcOkna(hwnd, umsg, wparam, lparam);                                      // Gdy mamy wskaznik na obiekt robimy przekierowanie
	                                                                                                         // na konkretną procedura dla konkretnej instancji klasy
	return 0;
} 

A oto procedura niestatyczna własna dla każdego obiektu:

 LRESULT CALLBACK Cokno::ProcOkna(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
	switch (umsg)
	{

	case WM_DESTROY:
		PostQuitMessage(0);
	default:
		 return DefWindowProc(hwnd, umsg, wparam, lparam);

	}
	return 0;
}

Wrzucę jeszcze definicję metody w klasie Cokno pozwalającej pobrać wskaźnik na konkretny obiekt klasy

 
private:
	inline static Cokno* ZwrocObjekt(HWND hwnd)       // Metoda statyczna, inline pozwalająca zwrócić adres  obiektu okna
	{
		return (Cokno*)GetWindowLong(hwnd, GWL_USERDATA);
	}

Ogólnie zamysł tego jest taki, że mając procedurę okna indywidualną dla każdego obiektu mogę zrobić ją wirtualną i możliwą do redefinicji
podczas dziedziczenia klasy Cokno. Niestety nie mogę poradzić sobie z tym problemem o którym napisałem w poście. Okno albo tworzy się i nie reaguje na zmianę wielkości (inne wiadomości działają), albo kiedy nie przesyłam wskaźnika this działa prawidłowo niestety za cenę tego, że nie wywołam niestatycznej procedury.

0

WM_NCCREATE trzeba zawsze przekazać do DefWindowProc.

No i pamiętaj by obiekt klasy gdzieś zwolnić, np. w WM_NCDESTROY.

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