2016-07-07 3 views
1

Ich habe ein Problem beim Scrollen großer Bereiche in einem CScrollView festgestellt. Wenn Sie die Bildlaufleiste langsam von oben nach unten bewegen, ist das folgende Verhalten: Zunächst funktioniert das Scrollen gut. Zu einem gewissen Zeitpunkt macht das Scrollen weiter nichts, stattdessen wird das obere Ende des Bereichs angezeigt. Irgendwann beginnt das Scrollen wieder von oben.CScrollView scrollt nur durch Teile eines großen Bereichs

Hier ist ein kleines Beispiel. Ich habe ein neues MFC-Projekt mit dem Dokumentansichtsmodell erstellt und CScrollView als Ansichtsklasse verwendet. Ich habe den folgenden Code einen großen Bereich zu erstellen und einen Text hinzufügen zu zeigen, der Teil zur Zeit angezeigt wird:

void CScrollViewTest2View::OnInitialUpdate() 
{ 
    CScrollView::OnInitialUpdate(); 

    CSize sizeTotal; 
    // TODO: calculate the total size of this view 
    sizeTotal.cx = sizeTotal.cy = 100*1000; 
    SetScrollSizes(MM_TEXT, sizeTotal); 

    for(int i = 0; i < 1000; i++) 
    { 
     CStatic* label = new CStatic(); 
     label->Create(NULL, WS_CHILD | WS_VISIBLE, CRect(10,10 + i*100,100,30 + i*100), this); 
     CString text; 
     text.Format(L"%d",i); 
     label->SetWindowText(text); 
    } 
} 

Wenn ich den folgenden Code, den ich sehen, dass während der Scrollen der Wert ‚nPos‘ scheint zu wickeln um. Dies würde das Verhalten erklären. Aber ich weiß nicht, wie ich das umgehen soll.

BOOL CScrollViewTest2View::OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll) 
{ 
    CString msg; 
    msg.Format(L"nPos = %u\n",nPos); 
    TRACE(msg); 
    return CScrollView::OnScroll(nScrollCode, nPos, bDoScroll); 
} 

und hier ist der Ausgang, wenn es nicht mehr steigt:

nPos = 27826 
nPos = 29190 
nPos = 30281 
nPos = 31372 
nPos = 31645 
nPos = 32464 
nPos = 4294938588 
nPos = 4294939134 
nPos = 4294939407 
nPos = 4294939680 
nPos = 4294940225 
nPos = 4294940771 

So ist es eine Möglichkeit, eine CScrollView zu verwenden komplett mit einer großen Fläche nach unten zu rollen?

Der Code des Beispielprojekts kann here gefunden werden.

+0

'CScrollView' verwendet' SetScrollRange' und andere alte Funktionen, die 16-Bit-Grenze haben, es geht nur bis zu '32767'. Es sollte 'SetScrollInfo/GetScrollInfo' verwenden, aber sie haben sich nicht um die Aktualisierung gekümmert. Sie haben ein zusätzliches Problem beim Erstellen von statischen Steuerelementen, deren Koordinaten außerhalb des 16-Bit-Bereichs liegen. Ich denke nicht, dass es dafür eine Lösung gibt. –

+0

Also, wenn ich meine eigene Version von 'CScrollView' mit 'SetScrollInfo/GetScrollInfo' schreiben würde, würde ich dieses Problem umgehen? Weißt du, ob jemand das schon getan hat und es zur Verfügung stellt? Und was genau ist das Problem mit statischen Kontrollen und Koordinaten aus dem 16-Bit-Bereich? Danke für Ihre Hilfe. – sietschie

+0

Ich glaube nicht, dass etwas getan werden kann, um Fenstersteuerungen außerhalb von 32767 zu platzieren. Ich habe einen Fix für 'CScrollView' hinzugefügt, es ist für normales Zeichnen gedacht, ansonsten solltest du vielleicht HTML Dialog oder eine andere Lösung in Betracht ziehen. –

Antwort

1

Die statischen Steuerungen werden nicht dort platziert, wo Sie sie erwarten. Um das Problem zu sehen, führen Sie den folgenden Code ein:

static CStatic test; 
CRect r(0, 0, 100, 30); 
r.MoveToY(40000); 
test.Create(0, WS_CHILD | WS_VISIBLE, r, this); 

test.GetWindowRect(r); 

TRACE("%d\n", r.top); 

r.top32767 sein sollte. Dies liegt an 16-Bit-Limits in Windows. Alle Steuerungen, deren x/y-Position diese Grenze überschreitet, werden in diese Position zurückgeschoben.

OnScroll Funktion von einem ähnlichen Problem leidet, jedoch kann dies durch GetScrollInfo mit

ON_WM_VSCROLL hinzufügen Nachricht Karte und dem folgenden OnVScroll Überschreibung Ihrer Klasse

void CScrollViewTest2View::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{ 
    CView::OnVScroll(nSBCode, nPos, pScrollBar); 
    SCROLLINFO info; 
    GetScrollInfo(SB_VERT, &info, SIF_ALL); 

    int pos = info.nPos; 
    int save = pos; 
    switch (nSBCode) 
    { 
    case SB_LEFT: pos = info.nMin; break; 
    case SB_RIGHT: pos = info.nMax; break; 
    case SB_LINELEFT: pos--; break; 
    case SB_LINERIGHT: pos++; break; 
    case SB_PAGELEFT: pos -= info.nPage; break; 
    case SB_PAGERIGHT: pos += info.nPage; break; 
    case SB_THUMBPOSITION: pos = info.nTrackPos; break; 
    case SB_THUMBTRACK: pos = info.nTrackPos; break; 
    } 

    //make sure the new position is within range 
    if (pos < info.nMin) pos = info.nMin; 
    int max = info.nMax - info.nPage + 1; 
    if (pos > max) pos = max; 

    OnScrollBy(CSize(0, pos - save), 1); 

    //EDIT: moved this line after OnScrollBy and added condition 
    if (info.nPos != pos) 
    { 
     info.nPos = pos; 
     SetScrollInfo(SB_VERT, &info, FALSE); 
    } 
    UpdateWindow(); 
} 

löst Dies wird das Problem nicht behoben werden mit Windows-Steuerelementen, deren x/y-Position größer als 32.000 ist, aber zumindest wird es den DC wie erwartet durchlaufen.

Zum Testen entfernen Sie die statischen Kontrollen. Sie können die Zeichenfunktion verwenden unter das Bild zu testen:

void CScrollViewTest2View::OnInitialUpdate() 
{ 
    CScrollView::OnInitialUpdate(); 
    CSize sizeTotal(0, 100 * 1000); 
    SetScrollSizes(MM_TEXT, sizeTotal); 
} 

void CScrollViewTest2View::OnDraw(CDC* pDC) 
{ 
    for (int i = 0; i < 1000; i++) 
    { 
     int y = i * 100; 
     CString s; 
     s.Format(L"%d    ", y); 
     pDC->TextOutW(200, y, s); 
    } 
} 
+0

Ich musste die Reihenfolge von OnScrollBy und SetScrollInfo ändern, damit es funktioniert. Ansonsten würde sich der Daumen nach Loslassen der Maustaste immer etwas bewegen.Anscheinend ändert 'OnScrollBy' den' SCROLLINFO' irgendwie? Ist das die richtige Lösung oder breche ich etwas anderes, wenn ich das mache? – sietschie

+0

Sie haben Recht. Ich habe den Auftrag bearbeitet und geändert. –

+0

Und es gibt absolut keine Möglichkeit, das 'CStatic' irgendwie zu funktionieren? In meinem realen Projekt zeichne ich mehr als nur Zahlen und es wäre etwas Arbeit, alles zu konvertieren (und höchstwahrscheinlich neue Bugs einzuführen). Ich hätte gehofft, dass auch andere diese Grenze kennen und irgendwie irgendwie gelöst hätten? – sietschie

Verwandte Themen