Stringgrid i przewijanie Scrolla zamiast focusa

0

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?

2

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.

0

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;
1

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.

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