windows api: Jak się scrolluje okno ?

0

Moje główne okno programu staje się za małe na pomieszczenie wszystkich rzeczy. Potrzebuję więc dodać pionowy scrollbar by móc przewijać okno i w ten sposób wszystko pomieścić. Zakodowałem 'scrollbar control', program przetwarza WM_VSCROLL messages takie jak np. SB_LINEDOWN i pasek przewijania ładnie przesuwa się. Została ostatnia najtrudniejsza dla mnie rzecz - zakodowanie przesuwania się okna wraz z przesuwaniem paska przewijania.
Próbowałem w ten sposób:

int dy = -( CurrPos - si.nPos );
RECT rctMainWindowArea = { 0, 0, 1000, main_window.bottom };
ScrollWindowEx( hwndMainWindow, 0, dy,( CONST RECT * ) &rctMainWindowArea,( CONST RECT * ) NULL,( HRGN ) NULL,( LPRECT ) NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE );
UpdateWindow( hwndMainWindow );

Wszystko działa ładnie gdy przesuwam okno w dół. Problem jest wtedy gdy wracam do górnej części okna - wszystko rozwala się graficznie. Googlowałem w tym temacie ale nie udało mi się znaleźć konkretnych przykładów jak wykonać podobną rzecz. Z tego co rozumiem należy przerysować okno zaraz po przesunięciu scrollbara tak by uwzględniono przesunięcie nPos. Nie mam jednak pojęcia jak to zrobić. Rzeczy, które trzeba przesuwać na głównym oknie to kilka basic controls, pare napisów narysowanych poprzez TextOut(), ramki RoundRect() itp. Czy ktoś mógłby zaprezentować gotowy przykład przewijania lub przynajmniej wytłumaczyć jak to dokładnie zrobić? Z góry dzięki.

P.S. używam dev-c++ 4.9.9.2

1

Masz obsługę WM_VSCROLL z mojego programu(z jakiegoś tutoriala, troche chyba przerobilem), przez łamacz komunikatów ale to już nie problem.

 

void Cls_OnVScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos)
{
	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( code )
	{
		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 );
}

...
case WM_VSCROLL:HANDLE_WM_VSCROLL(hwnd, wParam, lParam, Cls_OnVScroll);break;
...


Nie wiem jak tworzysz ScrollBar, ja dodałem flagę dla okna WS_VSCROLL. Myślę, że nie potrzebnie pobierasz i ustawiasz obszar do scrollowania, skoro i tak chcesz scrollować całe okno. Pozdro :)

0
arasso12 napisał(a)

Masz obsługę WM_VSCROLL z mojego programu(z jakiegoś tutoriala, troche chyba przerobilem), przez łamacz komunikatów ale to już nie problem.

 

[ ... ]

Nie wiem jak tworzysz ScrollBar, ja dodałem flagę dla okna WS_VSCROLL. Myślę, że nie potrzebnie pobierasz i ustawiasz obszar do scrollowania, skoro i tak chcesz scrollować całe okno. Pozdro :)

Wygląda na to, że korzystamy z tego samego tutorialu. Co do sposobu tworzenia scrollbara masz rację, wystarczy że użyję stylu WS_VSCROLL. Próbowałem użyć kontrolki dlatego że planuję później dodać obszary do przewijania horyzontalnego które nie obejdą się bez scrollbar control. W podany przez ciebie sposób jeśli używamy 'standardowego' scrollbara (flaga przy tworzeniu okna głównego) buttony, pola edit i inne podstawowe kontrolki przesuwają się w miarę dobrze, jednak obiekty graficzne, takie jak napisy narysowane przy pomocy TextOut lub grafika bmp znika lub rozjeżdża, tzn. działa tylko przewijanie w dół.
Jeśli natomiast używam CreateWindowEx() przy tworzeniu scrollbara sposób ten nie działa w ogóle - nawet buttony i inne kontrolki znikają lub rozjeżdżają się.

1

Bo TextOut wyrysowuje text raz, musisz go rysować za każdym razem w obsłudze komunikatu WM_VSCROLL, do tego obszar ten powinien być czyszczony przed rysowaniem. Jestem prawie pewien tego co mówię, ale ręki nie dam ; )

EDIT
Poza tym, według mnie lepiej zrobić kontrolkę-klasę. Tam tworzysz nowe oddzielne okno, jako okno pochodne od okna głównego, dodajesz sobie metody(dla listy kontaktów) AddContact, DeleteContact itp.

0
arasso12 napisał(a)

Bo TextOut wyrysowuje text raz, musisz go rysować za każdym razem w obsłudze komunikatu WM_VSCROLL, do tego obszar ten powinien być czyszczony przed rysowaniem. Jestem prawie pewien tego co mówię, ale ręki nie dam ; )

A co w sytuacji gdy scrollbar będzie w takim położeniu, że widoczne będzie tylko pół napisu? Nie mogę zacząć rysowania od -x wartości, bo winda nie pozwala na rysowanie z obszaru spoza okna... Jak mam to wtedy narysować ?

0
 

     case SB_LINEUP:
                        if( pozycja > 0 ) {
                                pozycja--;
                        }
                        break;
     case SB_LINEDOWN:
                        if( pozycja < 1000 ) {
                                pozycja++;
                                }
                                break;


W SB_LINEUP warunek jest prosty (>0), a przy SB_LINEDOWN chyba będzie trzeba przechowywać jaki obszar okna jest zajęty czyli:

if( pozycja < LastY ) - gdzie LastY=współrzędna Y najdalej wysuniętej kontrolki + wysokość tej kontrolki.

Nie testowałem, tak mi się wydaje.

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