Scroll, zdarzenie podczas przewijania

0

Witam.

Chciałbym, aby podczas przewijania np zawartości listboxa przy użyciu scrolla pionowego wywołała się jakaś procedura. Nie chodzi mi o przewijanie za pomocą kółka myszy, a za klikanie myszą na scrolla i przewijanie ręczne. Bardzo proszę o porady i z góry dziękuję za pomoc :)

0

musisz sobie napisać swojego ListBoxa

z http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_10121449.html<url>

private
FOnScroll : TNotifyEvent;

protected
procedure CMScroll(var Message: TMessage); message CM_SCROLL;

published
property OnScroll: TNotifyEvent read FOnScroll write FOnScroll;

then the procedure...

procedure TListBoxEx.CMScroll(var Message: TMessage);
begin
inherited;
if Assigned (FOnScroll) then FOnScroll(Self);
end;

</url>
0

chyba w pakiecie JEDI jest listbox z taka mozliwoscia.

0

Dziękukę bardzo za odpowiedź. Tak coś myślałem, że będzie trzeba stworzyć własny komponent albo pobawić się komunikatami.
Interesuje mnie jeszcze, jak pobrać np. wartość maksymalną scrolla pionowego w listboxie.
Próbowałem użyć funkcji SetScrollInfo i pochodnych ale niestety z marnym skutkiem. Proszę o wskazówki.

0
Szymonss napisał(a)

Dziękukę bardzo za odpowiedź. Tak coś myślałem, że będzie trzeba stworzyć własny komponent albo pobawić się komunikatami.
Interesuje mnie jeszcze, jak pobrać np. wartość maksymalną scrolla pionowego w listboxie.
Próbowałem użyć funkcji SetScrollInfo i pochodnych ale niestety z marnym skutkiem. Proszę o wskazówki.

napisz dokladnie co rozumiesz przez "marny skutek"? moze napisz co konkretnie chcesz osiagnac, tak chyba bedzie latwiej.
wskazowka to zerkniecie na GetScrollInfo, GetScrollPos, GetScrollRange na MSDN:
http://msdn.microsoft.com/en-us/library/bb787583(VS.85).aspx
sam listbox ma jeszcze cos takiego jak "TopIndex" - zwraca index itema ktory jest wyswietlany na samej gorze listboxa. przy znanej ilosci itemow wiesz juz w ktorym miejscu i jaki fragment calosci jest wyswietlany w listboxie.

0

Chciałbym aby za pomocą komponentu Gaugebar1 (Coś podobnego do Scrollbara z tym, że mogę zmieniać kolory przycisków do przewijania, belki przewijania itp.) istniała możliwość przewijania mojego Listboxa.

Mówiąć krótko: Chcę zastąpić zwykłego scrolla, jaki udostępnia komponent Listbox innym komponentem do przewijania.

Wartości Max i Min Gaugebara ustalam w ten sposób:

var
info: TScrollInfo;
begin
info.cbSize:=SizeOf(SCROLLINFO);
Info.fMask:=SIF_RANGE;
GetScrollInfo(Sectionlistbox1.Handle,SB_VERT,info);
Gaugebar1.Min:=info.nMin;
GaugeBar1.Max:=info.nMax;
end;

W OnChange Gaugebara mam:

SendMessage(SectionListbox1.Handle, WM_VScroll, MakeLParam(SB_THUMBPOSITION, Gaugebar1.Position), 0);

Problem pojawia się w dwóch rzeczach:
Chodzi mi o właściwość HandleSize Gaugebara (dla Scrollbara jest to podajże PageSize)
Gdy chcę pobrać wysokość belki scrolla w Listboxie.
Robię to tak:

info.fMask:=SIF_PAGE;
GetScrollInfo(Sectionlistbox1.Handle,SB_VERT,info);
GaugeBar1.HandleSize:=info.Npage;

Właściwość Height Gaugebara jest identyczna jak scrolla w Listboxie.

Dodam, że w zwykłym Scrollbarze wszystko działa ładnie pięknie. Sam nawet dostosowywuje wysokość belki do właściwości Min i Max.

Właściwości pobrane dzięki GetScrollInfo i zastosowaniu ich w Scrollbarze odzwierciedlają faktyczne dane ze scrolla w Listboxie.
Komponent Gaugebar inne przyjmuje właściwości dla pobranych danych z Listboxa.

Proszę o pomoc

0
Szymonss napisał(a)

Właściwości pobrane dzięki GetScrollInfo i zastosowaniu ich w Scrollbarze odzwierciedlają faktyczne dane ze scrolla w Listboxie.
Komponent Gaugebar inne przyjmuje właściwości dla pobranych danych z Listboxa.

no to musisz sprawdzic dokladnie co Gaugebar rozumie przez HandleSize.
moze to w pixelach?

0

Tak, HandleSize komponentu Gaugebar jest wartością w pikselach a właściwość PageSize jest wartością w innej jednostce. Nie mam pojęcia, jak można to "przekonwertować".
Problem z 'nieskalowaniem' belki Gaugebara do wysokosci belki scrolla w Listboxie rozwiązałbym w OnResize formy (Listbox.Align:=AlClient) gdybym tylko umiał zmienić wysokość belki Gaugebara na taką samą jak ma domyślny scroll Listboxa.

Proszę o rady :)

0

no to musisz pokombinowac jak to wyliczyc...
nie powinno byc trudne tylko trzeba chwile pomyslec ;]
wiesz ile pixeli ma caly gaugebar i ile to jest jednostek...

0

Niestety, ale sprawa nie jest taka łatwa jak się może wydawać.

Przyjmijmy:

 Scrollbar1.Max:=100;
Gaugebar1.Max:=100;

Wartość PageSize Scrolla: 10 => dla Gaugera belka jest równa belce ze scrollbara, gdy Handlesize: 17

PageSize: 10 => HandleSize: 17    (HandleSize:=HandleSize+7)
PageSize: 20 => HandleSize: 34    (+14)(2*7)
PageSize: 30 => HandleSize: 51    (+21)(3*7)
PageSize: 40 => HandleSize: 68    (+28)(4*7)

Ale już:

PageSize:  5 => HandleSize: 7 (+2)
PageSize:  50 => HandleSize: 86 (+36);

Dla:

 Scrollbar1.Max:=200;
Gaugebar1.Max:=200;
PageSize: 10 => HandleSize: 6    (-4)
PageSize: 20 => HandleSize: 16    (-4)
PageSize: 30 => HandleSize: 26    (-4)

ale:

PageSize: 40 => HandleSize: 34    (-6)
PageSize: 50 => HandleSize: 44    (-6)
PageSize: 60 => HandleSize: 52    (-8)

Wnioski:
Nie istnieje stała wartość, jaką mogę dodać do HandleSize, by Scroll w Gaugebarze wyrównał się ze Scrollem w Scrollbarze.

Pytania: Czy istnieje możliwość pobrania height samej belki w Scrollbarze?
Próbowałem tak: (Wysokosc belki=ScrollBar1.Height-2*17-x)
gdzie: 17 -> height jednego przycisku na scrollu, x-> pozostała wartość w pixelach(po której przesuwa się button). Potrzebuję albo wartość x, albo wysokość belki.

Przypominam: Jednostki w Scrollbarze wyglądają tak:

Scrollbar1.Max:=100;
Scrollbar1.PageSize:=50; //wysokosc belki

Wtedy PageSize zajmuje 1/2 miejsca na scrollu.

Gaugebar.HandleSize jest wysokością belki w pixelach.

Zależy mi na Gaugebarze, bo istnieje w tym komponencie możliwość kolorowania przycisków, belki, cieni, tła itp., ale nie istnieje niestety możliwość zmiany właściwości z pixeli na wartości Scrollbara.

Proszę o wskazówki i rady. Pozdrawiam :)

0

trzeba kombinowac a nie sie poddawac! ;]
nie wiem jak z tym Twoim Gaugebar'em ale ja to z ciekawosci zrobilem na zwyklych shape'ach i dziala (dokladnasc rzedu +/- 1px, powinno wystarczyc ;] )

pagePx:=round(  (page*shape2.Height)/(max-min+1)  );

gdzie:
        page - wartosc z info.Npage;
        shape2.Height - wysokosc (w px) pola po ktorym moze sie poruszac suwak;
        max,min - wartosci z info.nMin/nMax;

jeszcze tylko daj warunek zeby nie liczylo gdy (max-min+1)=0, bo dostaniesz blad o dzieleniu przez 0.
chociaz... hmm... chyba mozna sobie odpuscic bo raczej min nigdy nie bedzie wieksze od max?

0

Dziękuję, jesteś genialny :)

if (Gaugebar1.Max-Gaugebar1.Min+1)<>0 then
GaugeBar1.HandleSize:=round((info.nPage*(Gaugebar1.Height-34))/(Gaugebar1.max-Gaugebar1.min+1)  );

Taki kod działa jak marzenie :)

Jeszcze tylko wartość Position Gaugebara nie odpowiada wartości Scrolla w Listboxie. Też jest ona wyrażona w pixelach :/ Popróbuję coś wykombinować, jak się uda to dam znać :)
Własność LargeChange i SmallChange też jest identyczna, więc to nie od tego.

Jeszcze raz dziękuję.

Edit:

Myliłem się, wartość Position Gaugebara jest tej samej jednostki co Scrollbara.
Dowód: Wartość Min i Max przecież jest taka sama jak Scrollbara.
Problem przedstawię na screenie:

http://img140.imageshack.us/i/gaugev.jpg/

Jak widzimy, wartość position Gaugebara jest opóźniona z wartością scrollbara.
Na podglądzie formy, gdy ustawię w object inspectorze wartość max na takie same i position na takie same problem jest ten sam. Dodam, że belka i wysokość komponentów jest taka sama.

Próbowałem ustawiać pozycję suwaka też tak:

Info.fMask:=SIF_POS;
GetScrollInfo(SectionListbox1.Handle,SB_VERT,info);
Gaugebar1.Position:=Info.nPos;

Ale problem jest ten sam.

Proszę o wskazówki i pomysły, czym to może być spowodowane :)

0

Witam.

Przepraszam, że post pod postem, ale mam nowe pytanie odnośnie Scrolla :)

Dzięki uprzejmości użytkownika o nicku cimak udało mi się przekonwertować również pozycję belki z jednostki z oryginalnego Scrolla (tym razem w Scrollboxie) na pixele:

PX:=round((info.nPos*(ScrollBox1.Height-34))/(info.nMax -info.nMin+1));

Czyli zyskałem pozycję belki scrolla w pixelach. Ale mam teraz pytanie, zapewne rozwiązanie jest banalne, ale proszę o pomoc.

Jak uzyskać efekt odwrotny? Tzn, znam wartość w pixelach pozycji scrolla ze scrollboxa i chcę to przekonwertować na oryginalną jednostkę scrollboxa zależną od Info.nMax oraz Info.nMin.

Czyli:

Scrollbox1.VertScrollbar.Position:=przekonwertowana wartość z pixeli

Proszę o pomoc.

Edit: Problem rozwiązany:

round( (PozWPX-17)/(ScrollBox1.Height-34)*(info.nMax -info.nMin+1) );

od PozWPX odejmuję 17, ponieważ uwzględniam górny przycisk suwaka.

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