Witam
Tym razem chciałbym zrobić tak żeby scroll w myszce przesuwał pozycje scrollbara a nie focusa na stringgridzie.
Jest to bardzo nie naturalne.
Czy to bedzie trzeba robić "StringGrid1MouseWheelDown" i "toprow" ? Czy odblokuje to jakos inaczej?
Raczej tego nie odblokujesz, choć nie wiem jakie właściwości i metody są w klasie TStringGrid
w nowszych środowiskach, niż Delphi7; Google też wiele nie wyjaśnia w tej sprawie - najprawdopodobniej nie można tego włączyć/wyłączyć za pomocą jakiejś właściwości, jednak można obsłużyć odpowiednie zdarzenia;
EDIT: Udało się napisać algorytm, który bez względu na wysokość poszczególnych wierszy będzie działał poprawnie (a przynajmniej tak wynika z testów); Stary usunąłem z posta;
Działające rozwiązanie:
procedure TForm1.StringGrid1MouseWheelDown(Sender: TObject;
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
var
intRowsHeightSum, I: Integer;
begin
Handled := True;
with (Sender as TStringGrid) do
begin
intRowsHeightSum := 0;
I := TopRow;
while (I <= RowCount) and (intRowsHeightSum < Height) do
begin
Inc(intRowsHeightSum, RowHeights[I]);
Inc(I);
end;
if intRowsHeightSum > Height then
TopRow := TopRow + 1;
end;
end;
procedure TForm1.StringGrid1MouseWheelUp(Sender: TObject;
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
begin
Handled := True;
with (Sender as TStringGrid) do
if TopRow > FixedRows then
TopRow := TopRow - 1;
end;
Mam nadzieję, że nie tylko u mnie działa bez zarzutu.
Także zrobiłem podobnie.
Źródło : http://www.delphipages.com/forum/showthread.php?t=175685
Zrobiłem coś takiego, załozyłem że 5 wierszy będzie zawsze widoczne.
Wsume wystarczające, ale jeszcze Twój przetestuje :P
procedure TForm1.StringGrid1MouseWheelDown(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
var
toprow : integer;
begin
if (Shift = [ssShift]) then
Handled := false else //StringGrid1.LeftCol := StringGrid1.LeftCol -1;
begin
Handled := true; //scrolls the grid, not the selection
toprow := StringGrid1.topRow;
if StringGrid1.topRow < StringGrid1.RowCount -5 then StringGrid1.topRow := toprow + 1;
end;
end;
procedure TForm1.StringGrid1MouseWheelUp(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
var
toprow : integer;
begin
if (Shift = [ssShift]) then
Handled := false else
begin
Handled := true;
toprow := StringGrid1.topRow;
if toprow > 1 then StringGrid1.topRow := toprow - 1;
end;
end;
Twój dużo lepszy, czasami przycina lekko ostatni wiersz, ale to nic takiego :)
Napisz w jakim przypadku się przycina to postaram się poprawić;
Edit: Do powyższego algorytmu należy dodać także sumowanie wysokości wszystkich FixedRows
oraz za każdym razem GridLineWidth
żeby obliczenia były dokładniejsze; Żeby nie było żadnych pikselowych wątpliwości i niedociągnięć trzeba znać grubość obwódki kontrolki, którą niestety narzuca system; Poprawiona wersja algorytmu poniżej:
procedure TForm1.StringGrid1MouseWheelDown(Sender: TObject;
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
var
intRowsHeightSum, I: Integer;
begin
Handled := True;
with (Sender as TStringGrid) do
begin
intRowsHeightSum := 0;
for I := 0 to FixedRows - 1 do
Inc(intRowsHeightSum, RowHeights[I] + GridLineWidth);
I := TopRow;
while (I < RowCount) and (intRowsHeightSum <= ClientHeight) do
begin
Inc(intRowsHeightSum, RowHeights[I] + GridLineWidth);
Inc(I);
end;
if intRowsHeightSum >= ClientHeight then
TopRow := TopRow + 1;
end;
end;
Algorytm działa niemalże bezbłędnie ale tylko wtedy, gdy BorderStyle
ustawiony jest na bsNone
; Jeśli kontrolka będzie miała jakąś obwódkę, to trzeba jej podwójną wartość (jako ramka górna i dolna) wpisać do zmiennej intRowsHeightSum
przed pętlą sumującą - wtedy nie będzie pomyłek.
EDIT2: @maxiu1989 - algorytm poprawiłem jeszcze raz - nie trzeba znać grubości obwódki kontrolki, bo jest do dyspozycji właściwość ClientHeight
, dzięki której dokładnie wiadomo jaka jest powierzchnia robocza kontrolki; Nie tylko pomijamy grubość ramki kontrolki, ale także grubość poziomego paska przesuwu (Horizontal Scrollbar
), który także mieszałby w obliczeniach; Tak więc po raz ostatni modyfikuję algorytm; No chyba, że trzeba go będzie wyposażyć w obsługę jeszcze innych "przeszkadzających" elementów.
BorderStyle
na bsSingle
znasz szerokość linii obwódki kontrolki - wtedy powinien działać bezbłędnie; Jeśli zaś BorderStyle
jest na bsNone
- powyższy będzie działał bezbłędnie (a przynajmniej tak wynika z testów); Nie ma sprawy :>