[WINAPI] Scrollfenster, Positionierung von Buttons

FBIagent

Erfahrenes Mitglied
Guten Tag,

ich habe mich in den letzten Tagen mit Fenstern die eine Scrollbar beinhalten beschäftigt.
Nun bin ich am Punkt angelangt an dem mit dem eigentlichen Scrollen anfangen könnte,
nur habe ich dabei ein kleines Problem: Ich kann die Buttons im Fenster nicht
positionieren so das ich halt den Scrolleffect habe.
Es geht dabei um das folgende Fenster:
C:
    g_s_ShopEntriesWnd_Handle = CreateWindowEx(    0,
                                                SHOPENTRIESWND_CLASS_NAME, SHOPENTRIESWND_NAME,
                                                WS_CHILDWINDOW | WS_VISIBLE | WS_VSCROLL,
                                                10,
                                                10,
                                                SHOPENTRIESWND_WIDTH,
                                                SHOPENTRIESWND_HEIGHT,
                                                WndParent,
                                                NULL,
                                                g_s_ShopEntriesWnd_Class.hInstance,
                                                NULL );

Defines:
C:
#define SHOPENTRIESWND_WIDTH    ( 227 + 16 )
#define SHOPENTRIESWND_HEIGHT    ( 375 )
//#define SHOPENTRIESWND_WIDTH    ( 100 )
//#define SHOPENTRIESWND_HEIGHT    ( 100 )

#define SHOPENTRIESWND_CLASS_NAME    ( L"UmekoShopEntriesWndClass" )
#define SHOPENTRIESWND_NAME            ( L"Shop Entries" )

#define ICON_WIDTH                ( 32 )
#define ICON_HEIGHT                ( 32 )
#define ICON_BORDER_WND_X        ( 5 )
#define ICON_BORDER_WND_Y        ( 5 )
#define ICON_BORDER_BETWEEN_X    ( 5 )
#define ICON_BORDER_BETWEEN_Y    ( 5 )
#define ICON_STEP_X                ( ICON_HEIGHT + ICON_BORDER_BETWEEN_X )
#define ICON_STEP_Y                ( ICON_HEIGHT + ICON_BORDER_BETWEEN_Y )

#define MAX_COLUMN_INDEX        ( 5 )
#define MAX_COLUMN                ( MAX_COLUMN_INDEX + 1 )

#define NUM_TEST_BUTTONS    ( 61 )

Im Fenster Callback erstelle ich bei WM_CREATE zum test NUM_TEST_BUTTONS
Buttons, deren Fenster Handle in einen std::vector gefügt wird und berechne dort auch
direkt in wie fern die Scrollbar angezeigt werden soll. Es sollen maximal 10 Zeilen mit
jeweils 6 Buttons angezeigt werden:
C:
LRESULT CALLBACK ShopEntriesWnd_Proc( HWND WndHandle, UINT Msg, WPARAM wParam, LPARAM lParam ) {
    static HDC DC_Handle = NULL;
    static PAINTSTRUCT PS;
    static SCROLLINFO ScrollInfo;
    static int OldScrollPos = 0;
    static RECT Rect;
    static int i = 0;
    static int Row = 0;
    static int Column = 0;

    switch( Msg ) {
    case WM_CREATE:
        Row = 0;
        Column = 0;

        for ( i = 0;i < NUM_TEST_BUTTONS;++ i ) {

            Buttons.push_back( CreateWindowEx(    0,
                                                L"BUTTON",
                                                L"Test",
                                                WS_CHILD | WS_VISIBLE,
                                                ICON_BORDER_WND_X + ( Column * ICON_STEP_X ) ,
                                                ICON_BORDER_WND_Y + ( Row * ICON_STEP_Y ),
                                                ICON_WIDTH,
                                                ICON_HEIGHT,
                                                WndHandle,
                                                NULL,
                                                g_s_ShopEntriesWnd_Class.hInstance,
                                                NULL ) );

            if ( Column ++ == MAX_COLUMN_INDEX ) {
                Column = 0;
                ++ Row;
            }
        }

        ScrollInfo.cbSize = sizeof ( SCROLLINFO );
        ScrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL;
        ScrollInfo.nMin = 0;
        ScrollInfo.nMax = max( ( NUM_TEST_BUTTONS % MAX_COLUMN == 0 ? Row : Row + 1 ) - 10, 0 );
        ScrollInfo.nPage = 1;
        SetScrollInfo( WndHandle, SB_VERT, &ScrollInfo, TRUE );
        break;

Alles klar bis dahin sieht das Fenster noch in Ordnung aus, jetzt zum WM_VSCROLL
wo der Hund, wie es scheint, begraben zu sein scheint:
C:
    case WM_VSCROLL:
        ScrollInfo.fMask = SIF_ALL;
        GetScrollInfo( WndHandle, SB_VERT, &ScrollInfo );
        OldScrollPos = ScrollInfo.nPos;

        switch ( LOWORD( wParam ) ) {
        case SB_TOP:
            ScrollInfo.nPos = ScrollInfo.nMin;
            break;
        case SB_BOTTOM:
            ScrollInfo.nPos = ScrollInfo.nMax;
            break;
        case SB_LINEUP:
            ScrollInfo.nPos -= 1;
            break;
        case SB_LINEDOWN:
            ScrollInfo.nPos += 1;
            break;
        case SB_PAGEUP:
            ScrollInfo.nPos -= ScrollInfo.nPage;
            break;
        case SB_PAGEDOWN:
            ScrollInfo.nPos += ScrollInfo.nPage;
            break;
        case SB_THUMBPOSITION:
            ScrollInfo.nPos = ScrollInfo.nTrackPos;
            break;
        default:
            break;
        }

        ScrollInfo.fMask = SIF_POS;
        SetScrollInfo( WndHandle, SB_VERT, &ScrollInfo, TRUE );
        // auto range check, so it could be that our new position is not applied
        GetScrollInfo( WndHandle, SB_VERT, &ScrollInfo );

        if ( ScrollInfo.nPos != OldScrollPos ) {
            ScrollWindowEx( WndHandle, 0, ( OldScrollPos - ScrollInfo.nPos ) * ICON_STEP_Y, NULL, NULL, NULL, NULL, SW_INVALIDATE | SW_ERASE );

            for ( i = 0;i < Buttons.size();++ i ) {
                GetWindowRect( Buttons[ i ], &Rect );
                SetWindowPos( Buttons[ i ], HWND_TOPMOST, Rect.left, Rect.top - ( ScrollInfo.nPos > OldScrollPos ? ICON_STEP_Y : -ICON_STEP_Y ), 32, 32, SWP_SHOWWINDOW );
            }
        }

        break;

ScrollWindowEx funktioniert wunderbar, nur ich weis nicht warum ich die Positionen
der Buttons nicht setzen kann, die Positionen bleiben immer gleich. Das automatische
scrollen der Child Fenster mit ScrollWindowEx bring mir hier auch nichts, da beliebig
viele Buttons außerhalb des sichtbaren Bereiches liegen. Könnte jemand abhilfe
schaffen?

Best wishes
FBIagent
 
Zuletzt bearbeitet:
Hallo!

Kann ja sein dass ich auf dem Holzweg bin, aber hast du schonmal in Erwägung gezogen bei Scrolloperationen die Buttons mittels

C++:
MoveWindow(hWnd,x,y,width,height,bRedraw);
zu verschieben? Sollte doch eigentlich funktionieren.

LG,

RaDaZonG
 
Zuletzt bearbeitet von einem Moderator:
Gutn Tag,

nein daran hatte ich noch nicht gedacht. Ich habe es jetzt schon mit dem
automatischem Child Fenster flag von ScrollWindowEx hin bekommen. Da hatte
ich vorher wohl etwas falsch gemacht und bin zu meinem Trugschluss gekommen,
dass man mit ScrollWindowEx nur im sichtbaren bereich scrollen kann.

Best wishes
FBIagent
 

Neue Beiträge

Zurück