ScrollBar i Srollwindows - niepoprawne przewijanie

0

Witam,
Załóżmy , że chciałbym wyrzuć na ekran jakąś tam tabelkę składającą sie z 100 wierszy. Jej zawartośc nie mieści sie na ekranie wiec należałoby wykorzystać ScrollBara.
Wrzuciłem z Petzolda programik , który pokazuje jak to robić .
Wyświetlam 100 liczb ( 1 do 100) - na ekranie mieści sie np. 20 liczb. (Jeden wiersz to 20 unit device)
1
2
3
4
...
20

Wszysko ładnie się przewija , dopóki nie pomyślałem o dodaniu nad wyświetlanymi liczbami coś w rodzaju tytułu tabelki.
To oznacza, że same liczby powinny się niżej wyświetlać o jakiś tam margines górny ( załóżmy o 100 unit device) i Scrollbar powinien to uwzględniać.
W tym celu wprowadziłem kilka uzupełnień w procedurze okna :

  • utworzyłem obiekt RECT rect
  • zdefiniowałem zm. statyczną **iMargines_Y **= 100, o tyle przesunę zawartość tabelki w dół ekranu;
  • w WM_CREATE skopiowałem dane mojego okna do rect oraz ustawiłem rect.top
    rect.top = iMargines_Y ;
  • przedostatni parametr funkcji ScrollWindow , którym był NULL zamieniłem na &rect

Program zachowuje sie niezrozumiale przy pierwszym wybraniu LINEDOWN lub LINEUP .
Teoretycznie powinien wyświetlać liczby tabeli od rect.tp =100. ( 20 liczb od 1 do 20).
I tak jest po uruchomieniu programu, ale pierwsze użycie LINEDOWN powoduje przesunięcie wyświetlanych liczb o jeden wiersz, czyli górny margines zmniejsza sie z 100 do rect.top=80.
To powoduje , że na ekranie pojawia sie 21 wierszy i a nie 20 wierszy kosztem zmniejszenia marginesu górnego .

** 1**
2
3
4
...
20
21

Wiersz z cyfrą jeden w ogóle nie powinien się pojawić !

Następne wybieranie LINEDOWN już jest OK. oczywiście za wyjątkiem tego , że zmiany obejmują cały czas 21 wierszy

Podobnie jest w przypadku wybrania LINEUP.
Nie mam pojęcie dlaczego tak jest i nie wiem jak to rozwiązać. Czy ktoś z Was spotkał się z tym problemem?

0

i jeszcze kod.


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;


     static int  cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth ;    
     int         i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd ;   
     SCROLLINFO  si ;
     TCHAR       szBuffer[10] ;
     TEXTMETRIC  tm ;

	 //
	 static RECT rect ;
	 static int iMargines_Y;
	 static int iRozmiar;

	switch (message)
	{

     case WM_CREATE:
         //----------------- wprowadzone zmiany ---------------------
		  iMargines_Y = 100; // Górny margines - o tyle powinny sie niżej wyświetlać dane tabelki
							// a wartośc 100 powinna być miejscem na Tytuł tabelki, który nie będzie sie przewijał
		  iRozmiar	 = 100; // liczba elementów tabelki
		  GetClientRect( hWnd, &rect );
          rect.top = iMargines_Y;  // Ustawiam górny margines ( na 100)

		 //----------------- koniec ---------------------------------
		 
		  hdc    = GetDC (hWnd) ;
          GetTextMetrics (hdc, &tm) ;
          cxChar = tm.tmAveCharWidth ;
          cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
          cyChar = tm.tmHeight + tm.tmExternalLeading ;
          
          ReleaseDC (hWnd, hdc) ;
          
          iMaxWidth = 40 * cxChar + 22 * cxCaps ;
          return 0 ;
          
     case WM_SIZE:
          cxClient = LOWORD (lParam) ;
          cyClient = HIWORD (lParam) ;

          // Set vertical scroll bar range and page size

          si.cbSize = sizeof (si) ;
          si.fMask  = SIF_RANGE | SIF_PAGE ;
          si.nMin   = 0 ;
          si.nMax   = iRozmiar - 1 ;

          //si.nPage  = cyClient / cyChar ;
          //----------------- wprowadzone zmiany ---------------------
		  si.nPage  = (cyClient - iMargines_Y)/cyChar;
		  //----------------- koniec ---------------------------------
		  SetScrollInfo (hWnd, SB_VERT, &si, TRUE) ;

          return 0 ;
          
     case WM_VSCROLL:

          si.cbSize = sizeof (si) ;
          si.fMask  = SIF_ALL ;
          GetScrollInfo (hWnd, SB_VERT, &si) ;
          iVertPos = si.nPos ;

          switch (LOWORD (wParam))
          {
               
			  case SB_LINEUP:
				   si.nPos -= 1 ;
				   break ;
               
			  case SB_LINEDOWN:
				   si.nPos += 1 ;
				   break ;
                              
			  default:
				   break ;         
          }
 
          si.fMask = SIF_POS ;
          SetScrollInfo (hWnd, SB_VERT, &si, TRUE) ;
          GetScrollInfo (hWnd, SB_VERT, &si) ;

          // If the position has changed, scroll the window and update it

          if (si.nPos != iVertPos)
          {                    
               //----------------- wprowadzone zmiany ------------------------------
			   //ScrollWindow (hWnd, 0, cyChar * (iVertPos - si.nPos), NULL, NULL) ;
			     ScrollWindow (hWnd, 0, cyChar * (iVertPos - si.nPos), &rect, NULL) ;                                  
               //-----------------  koniec zmian ------------------------------------
			   UpdateWindow (hWnd) ;
          }
          return 0 ;
  /*        
     case WM_HSCROLL:
               // Get all the vertical scroll bar information

          si.cbSize = sizeof (si) ;
          si.fMask  = SIF_ALL ;

               // Save the position for comparison later on

          GetScrollInfo (hwnd, SB_HORZ, &si) ;
          iHorzPos = si.nPos ;

          switch (LOWORD (wParam))
          {
          case SB_LINELEFT:
               si.nPos -= 1 ;
               break ;
               
          case SB_LINERIGHT:
               si.nPos += 1 ;
               break ;
               
          case SB_PAGELEFT:
               si.nPos -= si.nPage ;
               break ;
               
          case SB_PAGERIGHT:
               si.nPos += si.nPage ;
               break ;
               
          case SB_THUMBPOSITION:
               si.nPos = si.nTrackPos ;
               break ;
               
          default:
               break ;
          }
               // Set the position and then retrieve it.  Due to adjustments
               //   by Windows it might not be the same as the value set.

          si.fMask = SIF_POS ;
          SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
          GetScrollInfo (hwnd, SB_HORZ, &si) ;
          
               // If the position has changed, scroll the window 

          if (si.nPos != iHorzPos)
          {
               ScrollWindow (hwnd, cxChar * (iHorzPos - si.nPos), 0, 
                             NULL, NULL) ;
          }
          return 0 ;

*/
/*
     case WM_KEYDOWN:
          switch (wParam)
          {
          case VK_HOME:
               SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0) ;
               break ;
               
          case VK_END:
               SendMessage (hwnd, WM_VSCROLL, SB_BOTTOM, 0) ;
               break ;
               
          case VK_PRIOR:
               SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0) ;
               break ;
               
          case VK_NEXT:
               SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0) ;
               break ;
               
          case VK_UP:
               SendMessage (hwnd, WM_VSCROLL, SB_LINEUP, 0) ;
               break ;
               
          case VK_DOWN:
               SendMessage (hwnd, WM_VSCROLL, SB_LINEDOWN, 0) ;
               break ;
               
          case VK_LEFT:
               SendMessage (hwnd, WM_HSCROLL, SB_PAGEUP, 0) ;
               break ;
               
          case VK_RIGHT:
               SendMessage (hwnd, WM_HSCROLL, SB_PAGEDOWN, 0) ;
               break ;
          }
          return 0 ;
*/

	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// Parse the menu selections:
		switch (wmId)
		{
			case IDM_ABOUT:
				DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
				break;
			case IDM_EXIT:
				DestroyWindow(hWnd);
				break;
			default:
				return DefWindowProc(hWnd, message, wParam, lParam);
			}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		
         // Get vertical scroll bar position

          si.cbSize = sizeof (si) ;
          si.fMask  = SIF_POS ;
          GetScrollInfo (hWnd, SB_VERT, &si) ;
          iVertPos = si.nPos ;

          // Get horizontal scroll bar position

          GetScrollInfo (hWnd, SB_HORZ, &si) ;
          iHorzPos = si.nPos ;

           // Find painting limits
		  //----------------- wprowadzone zmiany ------------------------------
          iPaintBeg = max (0, iVertPos + (ps.rcPaint.top - iMargines_Y) / cyChar) ;
          iPaintEnd = min (iRozmiar - 1, iVertPos + (ps.rcPaint.bottom - iMargines_Y) / cyChar) ;
          //-----------------  koniec zmian ------------------------------------                
          
          for (i = iPaintBeg ; i <= iPaintEnd ; i++)
          {
               x = cxChar * (1 - iHorzPos) ;
               //-----------------  koniec zmian ------------------------------------
			   //y = cyChar * (i - iVertPos) ;
			   y = (cyChar * (i - iVertPos)) + iMargines_Y; // uwzględniam górny margines =100
			   //-----------------  koniec zmian ------------------------------------
               TextOut (hdc, x+2  , y, szBuffer,wsprintf (szBuffer, TEXT ("%5d"),  i +1));
           }

 

		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
 

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