O debug vizualizérech v Delphi 2010 jsem již psal. Jen pro zopakování - jsou dva typy: jeden trasformuje datový typ (např. TDateTime) na srozumitelnější text, druhý zobrazuje okno (např. z instalace Delphi je vizualizer pro TStringList).
Implementace druhého je náročnější, jelikož se musí využít ToolsAPI debuggeru a přistupovat do jiného procesu během ladění a navíc příkazy pro zjišťování informací pro zobrazení se za běhu kompilují (stejně jako to dělá IDE ve WatchListu). Osobně vím jen o jedné plnohodnotné implementaci takového vizualizeru pro TBitmap, a o jedné, která je strašně pomalá, až se stydím, že jsem ji vůbec napsal - pro TDataSet.
TBitmap vizualizer
TBitmap vizualizér používá pro slušnou rychlost několik opravdu špinavých triků.
TDataset vizualizer
Problém mého vizualizéru je pomalost - pro trochu větší počet fieldů trvá zobrazení i 10s. A bohužel opravdu nevím jak to zrychlit. Principem takového vizualizéru je, jak již jsem uvedl, využití ToolsAPI Delphi - v tomto případě ToolsAPI debuggeru. Klíčovou metodou je volání ToolsAPI Evaluate, které provede vyhodnocení zadaného výrazu (výraz se interně kompiluje a pak nějak díky meziprocesorové komunikací se vyhodnotí a výsledek vrátí).
Bylo mi poraděno na stackoverflow abych se snažil co nejvíce příkazů sloučit do volání funkce Evaluate, ale zdá se mi, že to moc nepomáhá a navíc to přináší více problémů. Takže jen pro zajímavost a třeba to někomu pomůže - FExpression je výraz, nad kterým byl evaluátor vyvolán - např. Dataset1. Popř. kdyby měl někdo nějaký nápad - tak sem s ním. Ale předem říkám, že získat adresu objektu a tu přetypovat a volat přímo metody TDatasetu nejde, resp. získat adresu a přetypovat samozřejmě lze, ale nelze k nim dále přistupovat.
procedure TDataSetViewerFrame.mFillData;
var
iCount: Integer;
I: Integer;
sw: TStopwatch;
s: string;
begin
sw := TStopwatch.StartNew;
iCount := StrToIntDef(Evaluate(FExpression+'.Fields.Count'), 0);
for I := 0 to iCount - 1 do
begin
s:= s + Format('%s.Fields[%d].FieldName+'',''+', [FExpression, I]);
// FFields.Add(Evaluate(Format('%s.Fields[%d].FieldName', [FExpression, I])));
FValues.Add(Evaluate(Format('%s.Fields[%d].Value', [FExpression, I])));
end;
if s<> '' then
Delete(s, length(s)-4, 5);
s := Evaluate(s);
s:= Copy(s, 2, Length(s) -2);
FFields.CommaText := s;
sw.Stop;
s := sw.Elapsed;
//Application.MessageBox(Pchar(s), '');
end;
Pokud by chtěl někdo psát vlastní vizualizér, doporučuji vycházet z toho pro TBitmap, je tam vytvořena rozumná základní třída. Já to zjistil, až jsem to měl napsané.