Mam komponent DBGrid.
Na zdarzeniach AfterScroll or onCalcFields dataseta wykonuje się dużo obliczeń.
Przechodzenie myszką między zaznaczonymi rekordami trwa około pół sekundy.
Ale jeśli przeciągnę suwakiem na sam dół to wtedy te pół sekundy razy ilość rekordów daje długie czekanie.
W innych pętlach które przelatują po datasecie robię
Dataset.OnAfterScroll := nil
Dataset.OnCalcFields := nil
Skoro to tyle trwa, to co Ty tam obliczasz?
Używasz zdarzeń AfterScoll
i OnCalcFields
- obu? Ale po co?
Oba w/w zdarzenia wykonują się często, a OnCalcFields nawet bardzo często.
Opisz możliwie dokładnie co chcesz uzyskać i jak to realizujesz, bo pewnie jest lepszy sposób na to...
Nie zapomnij o:
- Wersja Delphi
- Komponenty bazodanowe
- Jaka baza danych
a na po pętli przywracam te zdarzenia. I wszystko działa szybko.
I tu moje pytanie.
Jak wyłączyć te zdarzenia gdy przeciągam suwak.
0,5s na zmianę rekordu to nie jest szybko.
Jak wyłączyć?
Nadpisać DBGrida, nadpisując metodę obsługi zdarzenia WM_VSCROLL
, która odpowiada za interakcję z pionowym paskiem przewijania.
//MMWIN:CLASSCOPY
unit _MM_Copy_Buffer_;
interface
type
TMyDBGrid = class(TDBGrid)
private
type
TmyGridDataLink = class(TGridDataLink);
private
function AcquireFocus: Boolean;
procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
end;
implementation
procedure TMyDBGrid.WMVScroll(var Message: TWMVScroll);
var
lDataLink : TmyGridDataLink;
SI : TScrollInfo;
lAfterScroll,
lBeforeScroll,
lOnCalcFields : TDataSetNotifyEvent;
begin
if not AcquireFocus then Exit;
lDataLink := TmyGridDataLink(DataLink);
lAfterScroll := lDataLink.DataSet.AfterScroll;
lBeforeScroll := lDataLink.DataSet.BeforeScroll;
lOnCalcFields := lDataLink.DataSet.OnCalcFields;
lDataLink.DataSet.AfterScroll := nil;
lDataLink.DataSet.BeforeScroll := nil;
lDataLink.DataSet.OnCalcFields := nil;
try
if lDataLink.Active then
with Message, lDataLink.DataSet do
case ScrollCode of
SB_LINEUP: lDataLink.MoveBy(-lDataLink.ActiveRecord - 1);
SB_LINEDOWN: lDataLink.MoveBy(lDataLink.RecordCount - lDataLink.ActiveRecord);
SB_PAGEUP: lDataLink.MoveBy(-VisibleRowCount);
SB_PAGEDOWN: lDataLink.MoveBy(VisibleRowCount);
SB_THUMBPOSITION:
begin
if IsSequenced then
begin
SI.cbSize := sizeof(SI);
SI.fMask := SIF_ALL;
GetScrollInfo(Self.Handle, SB_VERT, SI);
if SI.nTrackPos <= 1 then First
else if SI.nTrackPos >= RecordCount then Last
else RecNo := SI.nTrackPos;
end
else
case Pos of
0: First;
1: lDataLink.MoveBy(-VisibleRowCount);
2: Exit;
3: lDataLink.MoveBy(VisibleRowCount);
4: Last;
end;
end;
SB_BOTTOM: Last;
SB_TOP: First;
end;
finally
lDataLink.DataSet.AfterScroll := lAfterScroll;
lDataLink.DataSet.BeforeScroll := lBeforeScroll;
lDataLink.DataSet.OnCalcFields := lOnCalcFields;
end;
end;
function TMyDBGrid.AcquireFocus: Boolean;
begin
Result := True;
if CanFocus and not (csDesigning in ComponentState) then
begin
SetFocus;
Result := Focused or (InplaceEditor <> nil) and InplaceEditor.Focused;
end;
end;
end.
Oczywiście musisz posługiwać się tak zmodyfikowanym DBGridem - możesz go sobie zarejestrować jako własny komponent... Jeżeli nie wiesz jak, to takie rozwiązania zdecydowanie nie są dla Ciebie.
I na koniec - zdecydowanie nie jest to dobry pomysł na rozwiązanie Twojego problemu, a przynajmniej wg mnie - i to z wielu powodów.
Pewnie inni mają lepsze pomysły, zwłaszcza mistrzowie w temacie "jak powinno się pisać aplikacje bazodanowe w Delphi" ;-)