Как перехватить возвращаемые значения функции в визуализаторе отладчика Delphi?
У меня есть рабочий визуализатор отладчика, который помогает визуализировать переменные типа TIntTime.
TIntTime = тип целое число;
Визуализатор заменяет количество секунд с полуночи на строку времени ЧЧ: ММ: СС. Это прекрасно работает с переменными типа TIntTime во время сеанса отладки, но не с функциями. Например, если я помещу GetiTime в часы
function GetiTime: TIntTime;
begin
Result:=30000;
end;
часы покажут 30000. Ожидаемое замененное значение - "08:20:00". Визуализатор не перехватывает возвращаемые функцией значения типа TIntTime, и это является проблемой.
Я использую Delphi 10 Seattle. Мой визуализатор основан на DateTimeVisualizer.pas, найденном в Delphi 10\source\Visualizers. DateTimeVisualizer предполагает, что возвращаемые значения функции перехватываются с использованием строки имени типа 'function: TIntTime' в GetSupportedType. я пытался
'function: TIntTime'
'function:TIntTime'
'function::TIntTime'
без удачи Я подозреваю, что это вопрос получения правильной строки имени типа, но я не смог найти информацию о форматировании в Интернете.
Если я вместо этого помещу GetDateTime в часы, они показывают '14-02-2018 13:20:30', как и ожидалось. Если я выключаю визуализатор TDateTime/TDate/TTime в настройках, часы показывают 43145.5559... Это говорит мне о том, что можно перехватывать возвращаемые функцией функции с помощью визуализатора.
function GetDateTime: TDateTime;
begin
Result:=EncodeDateTime(2018,2,14,13,20,30,0);
end;
В моем случае это не вариант использовать тип данных TDateTime. Итак, мой вопрос: как я могу заставить мой визуализатор перехватывать возвращаемые функцией значения типа TIntTime?
Ниже приведен источник для визуализатора TIntTime
unit IntTimeVisualizer;
interface
procedure Register;
implementation
uses
Classes, Forms, SysUtils, ToolsAPI;
resourcestring
sIntTimeVisualizerName = 'TIntTime Visualizer for Delphi';
sIntTimeVisualizerDescription = 'Displays TIntTime instances in a human-readable time format rather than as an integer value';
type
TDebuggerIntTimeVisualizer = class(TInterfacedObject, IOTADebuggerVisualizer,
IOTADebuggerVisualizerValueReplacer, IOTAThreadNotifier, IOTAThreadNotifier160)
private
FCompleted: Boolean;
FDeferredResult: string;
public
{ IOTADebuggerVisualizer }
function GetSupportedTypeCount: Integer;
procedure GetSupportedType(Index: Integer; var TypeName: string;
var AllDescendants: Boolean);
function GetVisualizerIdentifier: string;
function GetVisualizerName: string;
function GetVisualizerDescription: string;
{ IOTADebuggerVisualizerValueReplacer }
function GetReplacementValue(const Expression, TypeName, EvalResult: string): string;
{ IOTAThreadNotifier }
procedure EvaluteComplete(const ExprStr: string; const ResultStr: string;
CanModify: Boolean; ResultAddress: Cardinal; ResultSize: Cardinal;
ReturnCode: Integer);
procedure ModifyComplete(const ExprStr: string; const ResultStr: string;
ReturnCode: Integer);
procedure ThreadNotify(Reason: TOTANotifyReason);
procedure AfterSave;
procedure BeforeSave;
procedure Destroyed;
procedure Modified;
{ IOTAThreadNotifier160 }
procedure EvaluateComplete(const ExprStr: string; const ResultStr: string;
CanModify: Boolean; ResultAddress: TOTAAddress; ResultSize: LongWord;
ReturnCode: Integer);
end;
TIntTimeType = (dttIntTime);
TIntTimeVisualizerType = record
TypeName: string;
TimeType: TIntTimeType;
end;
const
IntTimeVisualizerTypes: array[0..1] of TIntTimeVisualizerType =
(
(TypeName: 'TIntTime'; TimeType: dttIntTime;), //<-- This type is working fine
(TypeName: 'function: TIntTime'; TimeType: dttIntTime;) //<-- This type is not working
);
{ TDebuggerIntTimeVisualizer }
procedure TDebuggerIntTimeVisualizer.AfterSave;
begin
// don't care about this notification
end;
procedure TDebuggerIntTimeVisualizer.BeforeSave;
begin
// don't care about this notification
end;
procedure TDebuggerIntTimeVisualizer.Destroyed;
begin
// don't care about this notification
end;
procedure TDebuggerIntTimeVisualizer.Modified;
begin
// don't care about this notification
end;
procedure TDebuggerIntTimeVisualizer.ModifyComplete(const ExprStr,
ResultStr: string; ReturnCode: Integer);
begin
// don't care about this notification
end;
procedure TDebuggerIntTimeVisualizer.EvaluteComplete(const ExprStr,
ResultStr: string; CanModify: Boolean; ResultAddress, ResultSize: Cardinal;
ReturnCode: Integer);
begin
EvaluateComplete(ExprStr, ResultStr, CanModify, TOTAAddress(ResultAddress),
LongWord(ResultSize), ReturnCode);
end;
procedure TDebuggerIntTimeVisualizer.EvaluateComplete(const ExprStr,
ResultStr: string; CanModify: Boolean; ResultAddress: TOTAAddress; ResultSize: LongWord;
ReturnCode: Integer);
begin
FCompleted := True;
if ReturnCode = 0 then
FDeferredResult := ResultStr;
end;
procedure TDebuggerIntTimeVisualizer.ThreadNotify(Reason: TOTANotifyReason);
begin
// don't care about this notification
end;
function TDebuggerIntTimeVisualizer.GetReplacementValue(
const Expression, TypeName, EvalResult: string): string;
var
TimeType: TIntTimeType;
I: Integer;
function IntTimeToStr(s: Integer): string;
var
hh, mm, ss: integer;
begin
hh:=s div 3600;
mm:=(s div 60)-hh*60;
ss:=s mod 60;
Result:=Format('%.2d:%.2d:%.2d',[hh,mm,ss]);
end;
function FormatResult(const LEvalResult: string; DTType: TIntTimeType; out ResStr: string): Boolean;
var
IntValue: integer;
begin
Result := True;
try
if not TryStrToInt(LEvalResult, IntValue) then
Result:=false
else
case DTType of
dttIntTime: ResStr:=IntTimeToStr(IntValue);
end;
except
Result := False;
end;
end;
begin
TimeType := TIntTimeType(-1);
for I := Low(IntTimeVisualizerTypes) to High(IntTimeVisualizerTypes) do begin
if TypeName = IntTimeVisualizerTypes[I].TypeName then begin
TimeType:=IntTimeVisualizerTypes[I].TimeType;
Break;
end;
end;
if not FormatResult(EvalResult, TimeType, Result) then
Result := EvalResult;
end;
function TDebuggerIntTimeVisualizer.GetSupportedTypeCount: Integer;
begin
Result := Length(IntTimeVisualizerTypes);
end;
procedure TDebuggerIntTimeVisualizer.GetSupportedType(Index: Integer; var TypeName: string;
var AllDescendants: Boolean);
begin
AllDescendants := false;
TypeName := IntTimeVisualizerTypes[Index].TypeName;
end;
function TDebuggerIntTimeVisualizer.GetVisualizerDescription: string;
begin
Result := sIntTimeVisualizerDescription;
end;
function TDebuggerIntTimeVisualizer.GetVisualizerIdentifier: string;
begin
Result := ClassName;
end;
function TDebuggerIntTimeVisualizer.GetVisualizerName: string;
begin
Result := sIntTimeVisualizerName;
end;
var
IntTimeVis: IOTADebuggerVisualizer;
procedure Register;
begin
IntTimeVis:=TDebuggerIntTimeVisualizer.Create;
(BorlandIDEServices as IOTADebuggerServices).RegisterDebugVisualizer(IntTimeVis);
end;
procedure RemoveVisualizer;
var
DebuggerServices: IOTADebuggerServices;
begin
if Supports(BorlandIDEServices, IOTADebuggerServices, DebuggerServices) then begin
DebuggerServices.UnregisterDebugVisualizer(IntTimeVis);
IntTimeVis:=nil;
end;
end;
initialization
finalization
RemoveVisualizer;
end.