Building a Value Replacer for UCSChar
Before we delve into the development of a debugger visualizer, let me point you to a specific situation in which the debugger provides limited information about the values of a type. Consider the following code snippet, which is part of the DebugVisual example which is also used to demonstrate the other debugger visualizers.
procedure TForm39.btnUcs4CharClick(Sender: TObject); var ch: UCS4Char; begin ch := Ord ( 'u');
ShowMessage (Character.ConvertFromUtf32 (ch)); end ;
If you put a breakpoint in the code above and look to the value of ch, you'll see its numerical value, not the character is represents, as shown on the right. It fâ ^ variables
15 Refer to the source code of the TStringsVisualizer for an example of the other type (which is certainly more interesting, but also quite complex).
would be nice to see the accented letter, something we can now do thanks to this new feature.
IB Self Sender di
Name
Value
2-49
IB Self Sender di
Name
Value
2-49
To install a custom visualizer we have to create a design time package that requires the designide.dcp package and add a unit with a class implementing two debugger visualizer interfaces (the base one and the specific one) plus the IOTAThreadNotifier interface.
The class must provide all of the methods (here grouped by interface), even if most of them will have an empty implementation: type
TDebuggerUcs4CharVisualizer = class (
TinterfacedObject, IOTADebuggerVisualizer, IOTADebuggerVisualizerValueReplacer, IOTAThreadNotifier) 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; end ;
The methods implementing the IOTADebuggerVisual izer interface provide information about the debugger visualizer, including the name and description that will be displayed in the Debugger Options | Visualizers page of the Options dialog box, covered earlier:
function TDebuggerUcs4CharVisualizer.
GetVisualizerIdentifier: string; begin
function TDebuggerUcs4CharVisualizer.ù
GetVisualizerName: string; begin
Result := 'Ucs4Char Visualizer for Delphi '; end;
function TDebuggerUcs4CharVisualizer.
GetVisualizerDescription: string; begin
Result := 'Displays the Unicode string for a Ucs4Char'; end;
The last two methods return the number of types the visualizer can be used for, and each of their names (in this case, there is only one type, making the code much simpler):
function TDebuggerUcs4CharVisualizer.
GetSupportedTypeCount: Integer; begin
procedure TDebuggerUcs4CharVisualizer.GetSupportedType( Index: Integer; var TypeName: string; var AllDescendants: Boolean); begin
AllDescendants := False; TypeName := 'UCS4Char'; end;
The other relevant method is GetReplacementVal ue of the specific interface for this type of visualizer, IOTADebuggerVisual izerValueReplacer:
function TDebuggerUcs4CharVisualizer.GetReplacementValue( const Expression, TypeName, EvalResult: string): string; var ch: UCS4Char; begin ch := StrToIntDef (EvalResult, 0); Result := Character.ConvertFromUtf32 (ch); end;
In this specific example, all of the IOTAThreadNotifier methods have an empty body (but if you don't refer to that interface, the IDE will raise a low-level exception, so it is compulsory to have those empty methods).
Now that we have a class implementing our debugger visualizer for the UCS4Char type, we can install it after creating a global object, and clean up when the package is unloaded: var
Ucs4CharVis: IOTADebuggerVisualizer;
Post a comment