Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[WinAPI] Scrollbar wraz z kontrolką Static

Ostatnio zmodyfikowano 2013-06-02 14:46
Autor Wiadomość
XONX
Temat założony przez niniejszego użytkownika
[WinAPI] Scrollbar wraz z kontrolką Static
» 2013-06-02 11:10:57
No to tak. Problem jest taki. Mam aplikację okienkową w WinApi. Wszystko pięknie i w ogóle, ale kiedy próbuję dodać scrollbara do okienka potomnego typu static, to scrollbar zwyczajnie się nie przesuwa. Kiedy pozmieniam w całym kodzie związanym ze scrollbarem nazwę mojego okienka static na nazwę mojego głównego okienka, wszystko jest ok, przesuwa się normalnie. Tylko że ja chcę, żeby przesuwał mi się static, a nie całe okno. Mam nadzieję, że zbytnio nie namieszałem i liczę na pomoc :)
P-84610
xevuel
» 2013-06-02 11:22:19
Pokaż kod. W jaki sposób tworzysz scrollbara? Poprzez style WS_*SCROLL, subclassing, czy osobną kontrolkę?
P-84612
XONX
Temat założony przez niniejszego użytkownika
» 2013-06-02 11:29:20
C/C++
#include <windows.h>
#define ID_PRZYCISK1 501
#define ID_PRZYCISK2 502
#define ID_PRZYCISK3 503

LPSTR NazwaKlasy = "Klasa Okienka";
MSG Komunikat;
HWND hPrzycisk1;
HWND hPrzycisk2;
HWND hPrzycisk3;
HWND hStatic;

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    WNDCLASSEX wc;
   
    wc.cbSize = sizeof( WNDCLASSEX );
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground =( HBRUSH )( COLOR_WINDOW + 1 );
    wc.lpszMenuName = NULL;
    wc.lpszClassName = NazwaKlasy;
    wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
   
    if( !RegisterClassEx( & wc ) )
         return 1;
   
    HWND hwnd;
   
    hwnd = CreateWindowEx( WS_EX_WINDOWEDGE, NazwaKlasy, "okno", WS_BORDER | WS_CAPTION | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL );
   
    hPrzycisk1 = CreateWindowEx( 0, "BUTTON", "1", WS_CHILD | WS_VISIBLE, 15, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK1, hInstance, NULL );
    hPrzycisk2 = CreateWindowEx( 0, "BUTTON", "2", WS_CHILD | WS_VISIBLE, 300, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK2, hInstance, NULL );
    hPrzycisk3 = CreateWindowEx( 0, "BUTTON", "3", WS_CHILD | WS_VISIBLE, 580, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK3, hInstance, NULL );
   
    hStatic = CreateWindowEx( 0, "STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_CENTER, 20, 20, 750, 400, hwnd, NULL, hInstance, NULL );
    SetWindowText( hStatic, "" );
   
    RECT okno;
    GetClientRect( hwnd, & okno );
    SCROLLINFO si;
    ZeroMemory( & si, sizeof( si ) );
    si.cbSize = sizeof( SCROLLINFO );
    si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
    si.nMin = 0;
    si.nMax = 1000;
    si.nPage = okno.bottom;
    si.nPos = 0;
   
    SetScrollInfo( hwnd, SB_VERT, & si, TRUE );
   
    int pozycja = si.nPos;
    int dy = -( pozycja - si.nPos );
   
    ScrollWindowEx( hwnd, 0, dy,( CONST RECT * ) NULL,( CONST RECT * ) NULL,( HRGN ) NULL,( LPRECT ) NULL, NULL );
    UpdateWindow( hwnd );
    ShowWindow( hwnd, nCmdShow );
    UpdateWindow( hwnd );
   
    while( GetMessage( & Komunikat, NULL, 0, 0 ) )
    {
        TranslateMessage( & Komunikat );
        DispatchMessage( & Komunikat );
    }
   
    return Komunikat.wParam;
} //WinMain


LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
    case WM_CLOSE:
        DestroyWindow( hwnd );
        break;
       
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
       
        default:
        return DefWindowProc( hwnd, msg, wParam, lParam );
        break;
    case WM_VSCROLL: {
           
            SCROLLINFO si;
            ZeroMemory( & si, sizeof( si ) );
            si.cbSize = sizeof( SCROLLINFO );
            si.fMask = SIF_POS | SIF_PAGE | SIF_TRACKPOS;
            GetScrollInfo( hwnd, SB_VERT, & si );
           
            int pozycja = si.nPos;
           
            switch( LOWORD( wParam ) ) {
            case SB_TOP:
                pozycja = 0;
                break;
            case SB_BOTTOM:
                pozycja = 1000;
                break;
            case SB_LINEUP:
                if( pozycja > 0 ) {
                    pozycja--;
                }
                break;
            case SB_LINEDOWN:
                if( pozycja < 1000 ) {
                    pozycja++;
                }
                break;
            case SB_PAGEUP:
                pozycja -= si.nPage;
                if( pozycja < 0 ) {
                    pozycja = 0;
                }
                break;
            case SB_PAGEDOWN:
                pozycja += si.nPage;
                if( pozycja > 1000 ) {
                    pozycja = 1000;
                }
                break;
            case SB_THUMBPOSITION:
                pozycja = si.nTrackPos;
                break;
            case SB_THUMBTRACK:
                pozycja = si.nTrackPos;
                break;
            }
           
            int dy = -( pozycja - si.nPos );
            ScrollWindowEx( hwnd, 0, dy,( CONST RECT * ) NULL,( CONST RECT * ) NULL,( HRGN ) NULL,( LPRECT ) NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE );
            UpdateWindow( hwnd );
           
            ZeroMemory( & si, sizeof( si ) );
            si.cbSize = sizeof( SCROLLINFO );
            si.fMask = SIF_POS;
            si.nPos = pozycja;
           
            SetScrollInfo( hwnd, SB_VERT, & si, TRUE );
        }
        break;
    case WM_COMMAND:
        switch( wParam )
        {
        case ID_PRZYCISK1:
            SetWindowText( hStatic, "" );
            break;
        case ID_PRZYCISK2:
            SetWindowText( hStatic, "" );
            break;
        case ID_PRZYCISK3:
            SetWindowText( hStatic, "" );
        }
        break;
    } //switch
    return 0;
} // WindProc


Teksty powycinałem, ale jeśli chodzi o te przyciski, to założenie było takie, że naciskasz je i tekst na polu static się zmienia (i to działa :D). Jakby ktoś powiedział jak zrobić tą ramkę dookoła kodu na forum to na pewno byłoby bardziej czytelne.

PS: To jest ta wersja kodu, która przesuwa całe okno.

//Edit: Program tworzyłem w oparciu o kurs w WinApi z tej strony, nie jestem pewien czy wszystko zrozumiałem.
P-84613
xevuel
» 2013-06-02 11:34:44
PS: To jest ta wersja kodu, która przesuwa całe okno.
Wszystko fajnie, tylko po co nam kod który działa? ;) Wklej ten błędny :)

Jakby ktoś powiedział jak zrobić tą ramkę dookoła kodu na forum to na pewno byłoby bardziej czytelne.
[cpp]...[/cpp]
Więcej znaczników: » KursyKurs STC kurs
P-84614
XONX
Temat założony przez niniejszego użytkownika
» 2013-06-02 11:41:19
C/C++
#include <windows.h>
#define ID_PRZYCISK1 501
#define ID_PRZYCISK2 502
#define ID_PRZYCISK3 503

LPSTR NazwaKlasy = "Klasa Okienka";
MSG Komunikat;
HWND hPrzycisk1;
HWND hPrzycisk2;
HWND hPrzycisk3;
HWND hStatic;

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    WNDCLASSEX wc;
   
    wc.cbSize = sizeof( WNDCLASSEX );
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground =( HBRUSH )( COLOR_WINDOW + 1 );
    wc.lpszMenuName = NULL;
    wc.lpszClassName = NazwaKlasy;
    wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
   
    if( !RegisterClassEx( & wc ) )
         return 1;
   
    HWND hwnd;
   
    hwnd = CreateWindowEx( WS_EX_WINDOWEDGE, NazwaKlasy, "okno", WS_BORDER | WS_CAPTION | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL );
   
    hPrzycisk1 = CreateWindowEx( 0, "BUTTON", "1", WS_CHILD | WS_VISIBLE, 15, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK1, hInstance, NULL );
    hPrzycisk2 = CreateWindowEx( 0, "BUTTON", "2", WS_CHILD | WS_VISIBLE, 300, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK2, hInstance, NULL );
    hPrzycisk3 = CreateWindowEx( 0, "BUTTON", "3", WS_CHILD | WS_VISIBLE, 580, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK3, hInstance, NULL );
   
    hStatic = CreateWindowEx( 0, "STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | SS_CENTER, 20, 20, 750, 400, hwnd, NULL, hInstance, NULL );
    SetWindowText( hStatic, "" );
   
    RECT okno;
    GetClientRect( hStatic, & okno );
    SCROLLINFO si;
    ZeroMemory( & si, sizeof( si ) );
    si.cbSize = sizeof( SCROLLINFO );
    si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
    si.nMin = 0;
    si.nMax = 1000;
    si.nPage = okno.bottom;
    si.nPos = 0;
   
    SetScrollInfo( hStatic, SB_VERT, & si, TRUE );
   
    int pozycja = si.nPos;
    int dy = -( pozycja - si.nPos );
   
    ScrollWindowEx( hStatic, 0, dy,( CONST RECT * ) NULL,( CONST RECT * ) NULL,( HRGN ) NULL,( LPRECT ) NULL, NULL );
    UpdateWindow( hStatic );
    ShowWindow( hwnd, nCmdShow );
    UpdateWindow( hwnd );
   
    while( GetMessage( & Komunikat, NULL, 0, 0 ) )
    {
        TranslateMessage( & Komunikat );
        DispatchMessage( & Komunikat );
    }
   
    return Komunikat.wParam;
} //WinMain


LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
    case WM_CLOSE:
        DestroyWindow( hwnd );
        break;
       
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
       
        default:
        return DefWindowProc( hwnd, msg, wParam, lParam );
        break;
    case WM_VSCROLL: {
           
            SCROLLINFO si;
            ZeroMemory( & si, sizeof( si ) );
            si.cbSize = sizeof( SCROLLINFO );
            si.fMask = SIF_POS | SIF_PAGE | SIF_TRACKPOS;
            GetScrollInfo( hStatic, SB_VERT, & si );
           
            int pozycja = si.nPos;
           
            switch( LOWORD( wParam ) ) {
            case SB_TOP:
                pozycja = 0;
                break;
            case SB_BOTTOM:
                pozycja = 1000;
                break;
            case SB_LINEUP:
                if( pozycja > 0 ) {
                    pozycja--;
                }
                break;
            case SB_LINEDOWN:
                if( pozycja < 1000 ) {
                    pozycja++;
                }
                break;
            case SB_PAGEUP:
                pozycja -= si.nPage;
                if( pozycja < 0 ) {
                    pozycja = 0;
                }
                break;
            case SB_PAGEDOWN:
                pozycja += si.nPage;
                if( pozycja > 1000 ) {
                    pozycja = 1000;
                }
                break;
            case SB_THUMBPOSITION:
                pozycja = si.nTrackPos;
                break;
            case SB_THUMBTRACK:
                pozycja = si.nTrackPos;
                break;
            }
           
            int dy = -( pozycja - si.nPos );
            ScrollWindowEx( hStatic, 0, dy,( CONST RECT * ) NULL,( CONST RECT * ) NULL,( HRGN ) NULL,( LPRECT ) NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE );
            UpdateWindow( hStatic );
           
            ZeroMemory( & si, sizeof( si ) );
            si.cbSize = sizeof( SCROLLINFO );
            si.fMask = SIF_POS;
            si.nPos = pozycja;
           
            SetScrollInfo( hStatic, SB_VERT, & si, TRUE );
        }
        break;
    case WM_COMMAND:
        switch( wParam )
        {
        case ID_PRZYCISK1:
            SetWindowText( hStatic, "" );
            break;
        case ID_PRZYCISK2:
            SetWindowText( hStatic, "" );
            break;
        case ID_PRZYCISK3:
            SetWindowText( hStatic, "" );
        }
        break;
    } //switch
    return 0;
} // WindProc
P-84615
xevuel
» 2013-06-02 11:55:36
Kontrolka Static jest kontrolką, która w zasadzie praktycznie w ogóle nie reaguje na działania użytkownika. Także na pewno nie wyśle Ci komunikatu WM_VSCROLL do procedury okna (w zasadzie większość kontrolek rzadko kiedy wysyła komunikaty WM_* do głównej procedury).

Rozwiązanie: Kod właściwie wydaje się być prawie dobrym :) Musisz tylko utworzyć osobną kontrolkę (» Kurs WinAPI, C++ » KontrolkiScrollBar lekcja), która wyśle Ci ten komunikat, i pozmieniać uchwyty przekazywane do funkcji GetScrollInfo/SetScrollInfo na te prowadzące do scrollbara. Daj znać, czy Ci się udało ;)
P-84616
XONX
Temat założony przez niniejszego użytkownika
» 2013-06-02 12:09:05
Chyba coś źle zrobiłem, bo dalej nie działa :/
Z tego co zrozumiałem powinno być tak:

C/C++
#include <windows.h>
#define ID_PRZYCISK1 501
#define ID_PRZYCISK2 502
#define ID_PRZYCISK3 503

LPSTR NazwaKlasy = "Klasa Okienka";
MSG Komunikat;
HWND hPrzycisk1;
HWND hPrzycisk2;
HWND hPrzycisk3;
HWND hStatic;
HWND hScroll;

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    WNDCLASSEX wc;
   
    wc.cbSize = sizeof( WNDCLASSEX );
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground =( HBRUSH )( COLOR_WINDOW + 1 );
    wc.lpszMenuName = NULL;
    wc.lpszClassName = NazwaKlasy;
    wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
   
    if( !RegisterClassEx( & wc ) )
         return 1;
   
    HWND hwnd;
   
    hwnd = CreateWindowEx( WS_EX_WINDOWEDGE, NazwaKlasy, "okno", WS_BORDER | WS_CAPTION | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL );
   
    hPrzycisk1 = CreateWindowEx( 0, "BUTTON", "1", WS_CHILD | WS_VISIBLE, 15, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK1, hInstance, NULL );
    hPrzycisk2 = CreateWindowEx( 0, "BUTTON", "2", WS_CHILD | WS_VISIBLE, 300, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK2, hInstance, NULL );
    hPrzycisk3 = CreateWindowEx( 0, "BUTTON", "3", WS_CHILD | WS_VISIBLE, 580, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK3, hInstance, NULL );
   
    hStatic = CreateWindowEx( 0, "STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | SS_CENTER, 20, 20, 750, 400, hwnd, NULL, hInstance, NULL );
    SetWindowText( hStatic, "" );
   
    RECT okno;
    GetClientRect( hStatic, & okno );
    SCROLLINFO si;
    ZeroMemory( & si, sizeof( si ) );
    si.cbSize = sizeof( SCROLLINFO );
    si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
    si.nMin = 0;
    si.nMax = 1000;
    si.nPage = okno.bottom;
    si.nPos = 0;
   
    SetScrollInfo( hScroll, SB_VERT, & si, TRUE );
   
    int pozycja = si.nPos;
    int dy = -( pozycja - si.nPos );
   
    ScrollWindowEx( hStatic, 0, dy,( CONST RECT * ) NULL,( CONST RECT * ) NULL,( HRGN ) NULL,( LPRECT ) NULL, NULL );
    UpdateWindow( hStatic );
    ShowWindow( hwnd, nCmdShow );
    UpdateWindow( hwnd );
   
    while( GetMessage( & Komunikat, NULL, 0, 0 ) )
    {
        TranslateMessage( & Komunikat );
        DispatchMessage( & Komunikat );
    }
   
    return Komunikat.wParam;
} //WinMain


LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
    case WM_CLOSE:
        DestroyWindow( hwnd );
        break;
       
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
       
        default:
        return DefWindowProc( hwnd, msg, wParam, lParam );
        break;
    case WM_VSCROLL: {
           
            SCROLLINFO si;
            ZeroMemory( & si, sizeof( si ) );
            si.cbSize = sizeof( SCROLLINFO );
            si.fMask = SIF_POS | SIF_PAGE | SIF_TRACKPOS;
            GetScrollInfo( hScroll, SB_VERT, & si );
           
            int pozycja = si.nPos;
           
            switch( LOWORD( wParam ) ) {
            case SB_TOP:
                pozycja = 0;
                break;
            case SB_BOTTOM:
                pozycja = 1000;
                break;
            case SB_LINEUP:
                if( pozycja > 0 ) {
                    pozycja--;
                }
                break;
            case SB_LINEDOWN:
                if( pozycja < 1000 ) {
                    pozycja++;
                }
                break;
            case SB_PAGEUP:
                pozycja -= si.nPage;
                if( pozycja < 0 ) {
                    pozycja = 0;
                }
                break;
            case SB_PAGEDOWN:
                pozycja += si.nPage;
                if( pozycja > 1000 ) {
                    pozycja = 1000;
                }
                break;
            case SB_THUMBPOSITION:
                pozycja = si.nTrackPos;
                break;
            case SB_THUMBTRACK:
                pozycja = si.nTrackPos;
                break;
            }
           
            int dy = -( pozycja - si.nPos );
            ScrollWindowEx( hStatic, 0, dy,( CONST RECT * ) NULL,( CONST RECT * ) NULL,( HRGN ) NULL,( LPRECT ) NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE );
            UpdateWindow( hStatic );
           
            ZeroMemory( & si, sizeof( si ) );
            si.cbSize = sizeof( SCROLLINFO );
            si.fMask = SIF_POS;
            si.nPos = pozycja;
           
            SetScrollInfo( hScroll, SB_VERT, & si, TRUE );
        }
        break;
    case WM_COMMAND:
        switch( wParam )
        {
        case ID_PRZYCISK1:
            SetWindowText( hStatic, "" );
            break;
        case ID_PRZYCISK2:
            SetWindowText( hStatic, "" );
            break;
        case ID_PRZYCISK3:
            SetWindowText( hStatic, "" );
        }
        break;
    } //switch
    return 0;
} // WindProc
P-84617
xevuel
» 2013-06-02 12:16:05
Nigdzie nie tworzysz kontrolki o klasie Scrollbar.

Twój kod:
C/C++
hPrzycisk1 = CreateWindowEx( 0, "BUTTON", "1", WS_CHILD | WS_VISIBLE, 15, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK1, hInstance, NULL );
hPrzycisk2 = CreateWindowEx( 0, "BUTTON", "2", WS_CHILD | WS_VISIBLE, 300, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK2, hInstance, NULL );
hPrzycisk3 = CreateWindowEx( 0, "BUTTON", "3", WS_CHILD | WS_VISIBLE, 580, 500, 200, 50, hwnd,( HMENU ) ID_PRZYCISK3, hInstance, NULL );

hStatic = CreateWindowEx( 0, "STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | SS_CENTER, 20, 20, 750, 400, hwnd, NULL, hInstance, NULL );
SetWindowText( hStatic, "" );
Wstaw niżej kod z kursu (możesz zmienić wymiary i pozycje; jeśli wkleisz tak jak jest, scrollbar pojawi się przy prawej krawędzi głównego okna, a nie przy kontrolce):
C/C++
RECT okno;
GetClientRect( hwnd, & okno );
int iVThumb = GetSystemMetrics( SM_CYVTHUMB );
hScroll = CreateWindowEx( 0, "SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE | SBS_VERT,
okno.right - 16, okno.top, 16, okno.bottom - iVThumb,
hwnd, NULL, hInstance, NULL );

Aha, trzeba będzie jeszcze zmienić SB_VERT na SB_CTL (
SetScrollInfo( hScroll, SB_VERT, & si, TRUE );
 i podobne) i wyrzucić WS_VSCROLL z kontrolki hStatic.
P-84619
« 1 » 2
  Strona 1 z 2 Następna strona