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

Odpowiedz Nowy wątek
2014-12-26 18:14
Kawka
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ć?

Pozostało 580 znaków

2014-12-26 19:11
Kawka
0

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

Pozostało 580 znaków

2014-12-26 19:12
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.

Pozostało 580 znaków

2014-12-26 20:32
Kawka
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.

Pozostało 580 znaków

2014-12-27 16:06
0

WM_NCCREATE trzeba zawsze przekazać do DefWindowProc.

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

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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