Bitmap scrollen - problem



  • hi Leute
    Ich habe in meinem Hauptfenster ein Childfenster ("Scroller"), das mit Scrollbars ausgestattet ist. Ich blitte das Bild dort hinein (BitBlt) und scrolle herum.

    Problem:
    - Beim Scrollen flackert es, aber: nur im Bereich, der am Anfang ins Fenster passt.
    D.h. wenn das Fenster die Grösse 400x300 hat, dann flackert beim Scrollen nur die 400x300px links oben, der Rest wird schön gescrollt.

    Aufbau: (ich benutze die SimpleWndClassIV von FoosYerDoos)

    HauptFenster (hAppWnd)

    BOOL CppAppWnd::OnCreate(CREATESTRUCT *cs)
    {
        // ..
        hScroll = CreateWindow( "Scroller", NULL,
                         WS_CHILD | WS_BORDER | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL,
                         0,0,0,0, hAppWnd, NULL, hInst, NULL);
        // ..
    }
    

    ScrollFenster (hScroll)

    BOOL CScrollWnd::OnSize(LPARAM lParam)
    {
        // Grösse des Fensters und maximale Scrollpositionen berechnen
        xMapScroll = LOWORD(lParam);
        yMapScroll = HIWORD(lParam);
        xMax = xBmp - xMapScroll + iRand;  // Bildbreite - Anzeigebreite + Scrollbar
        yMax = yBmp - yMapScroll + iRand; // Bildhöhe - Anzeigehöhe + Scrollbar 
    
        // nun noch die daten in der ScollInfo ändern und setzen  
        si.cbSize = sizeof(si);
        si.fMask  = SIF_RANGE | SIF_POS;
        si.nMin   = 0;
        si.nMax   = xMax; // Bildbreite - Anzeigebreite + Scrollbar
        si.nPos   = xPos; // vorherige Scrollposition beibehalten
        SetScrollInfo(hScroll, SB_HORZ, &si, TRUE);
        si.nMax   = yMax;
        si.nPos   = yPos; // vorherige Scrollposition beibehalten
        SetScrollInfo(hScroll, SB_VERT, &si, TRUE);
        UpdateWindow(hScroll);
    return 0;
    }
    //----------
    BOOL CScrollWnd::OnPaint()
    { 
    InvalidateRect(hScroll,NULL,true);
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hScroll, &ps);
    HDC hdcMem = CreateCompatibleDC(NULL);
    
    // Male das bitmap ins Map-Feld
    SelectObject(hdcMem, hBmp);
    BitBlt(hdc, 0, 0, xMapScroll, yMapScroll, hdcMem, xPos, yPos, SRCCOPY);
    
    DeleteDC(hdcMem);
    EndPaint(hScroll, &ps);
    
    return 0;
    }
    //----------
    BOOL CScrollWnd::OnHScroll(WPARAM wParam)
    {
        int xBackup = xPos;
         //nun ermitteln wir die H-Position, bzw. setzen diese 
         switch (LOWORD(wParam)) 
         { 
             case SB_PAGEUP: 
                 xPos = xPos - 50; 
                 break; 
             case SB_PAGEDOWN: 
                 xPos = xPos + 50; 
                 break; 
             case SB_LINEUP: 
                 xPos = xPos - 5; 
                 break; 
             case SB_LINEDOWN: 
                 xPos = xPos + 5; 
                 break; 
             case SB_THUMBPOSITION: 
                 xPos = HIWORD(wParam); 
                 break;
             case SB_THUMBTRACK: 
                 xPos = HIWORD(wParam); 
                 break;
             default: 
                 xPos = xPos;
         }
         // prüfen ob nicht kleiner 0 
         if (xPos < 0) xPos = 0;
         // und nicht größer maximale Scrollposition
         if (xPos > xMax) xPos = xMax;
    
         if (xBackup != xPos) //falls sich etwas verändert hat
         {
         // nun noch die daten in der ScollInfo ändern und setzen  
         si.cbSize = sizeof(si);
         si.fMask  = SIF_POS | SIF_DISABLENOSCROLL;
         si.nPos   = xPos;
         SetScrollInfo(hScroll, SB_HORZ, &si, TRUE);
         // Window schieben 
         ScrollWindowEx(hScroll, -xPos, -yPos, (CONST RECT *) NULL, 
             (CONST RECT *) NULL, (HRGN) NULL, (LPRECT) NULL, SW_INVALIDATE); 
         UpdateWindow(hScroll);
         }       
    
    return 0;
    }
    // dito für VSCROLL
    

    Ach ja.. die Frage: Wieso tritt der oben genannten Fehler auf und wie kann ich ihn beheben?
    Vielen Dank im Voraus

    [Den kompletten Quellcode findet sich unter: http://ultinate.100free.com/Debugging/sourcecode_all.htm]



  • was mir so auffällt: bei BildFenster (hMap):
    InvalidateRect in der onpaint routine?
    Weiterhin benutze ich immer GetDC umd die aktuelle hDC zu bekommen (nachher natürlich ReleaseDC um die wieder freizugeben).Ok, ich arbeite auch sonst mit "original" windowsnachrichten (also anstatt onpaint ein WM_PAINT 🙂 und da sind als behandlungsroutine drin erstmals ein BeginPaint und EndPaint und danach erst die eigentliche zeichnungsroutine: GetClientRect,
    GetDC,
    CreateCompatibleDC,
    StretchBlt,
    DeleteDC,(=>compatibleDC)
    ReleaseDC
    vielleicht etwas umständlch, funktioniert aber ohne probleme (einsatz in einem Skinmaker =>zoomen und objekte positionieren)



  • - InvalidateRect: falsch, oder einfach nur unnötig?

    - das mit dem OnPaint() ist ja nur kosmetik.. 😉

    - naja.. die methode mit BeginPaint und EndPaint müsste ja auch funktionieren.
    ich vermute, dass das problem irgendwo im OnHScroll() drin steckt.. den teil hab ich nämlich geklaut (http://www.c-plusplus.net/forum/viewtopic.php?t=89773) *schäm* 😉


Anmelden zum Antworten