ABOUT
This plug-in is actually an internal tool that was used by Eagle Software to build CodeRush. As you may guess, this plug-in has incredible power. As such, it should be used with great care. With the Form Explorer, you can analyze the structure of a form or an application, view object hierarchies, check properties, track when events are fired, and much more.
FEATURES
The Form Explorer is a powerhouse utility; actually, it is actually more of a debugging tool than an end-user's productivity enhancement. As stated above, it was used by Mark Miller when Eagle Software was developing CodeRush. This plug-in provides the following abilities:
- Analyze either a form or Delphi itself.
- Inspect any control on the form being analyzed; including details such as lineage, owner, parent, and class name.
- Drill into the assigned properties and events of any component being inspected.
- Hook into events and actually watch them as they fire, optionally creating a CodeSite log file in the process.
- Advanced options such as creating and destroying instances of the object being analyzed.
When the Form Explorer is installed, a new menu item, Form Explorer, will appear on the File Editor's context menu, see below:
Selecting the menu option invokes the Form Explorer dialog, as seen below. The interface of the Form Explorer can be divided into three main sections.
- Options panel - this is where you instruct the Form Explorer what form you wish to analyze.
- Object browser - this is the window on the left side of the Form Explorer dialog. When a form is being analyzed, this will contain a treeview listing all objects associated with the form. It is from here that all of your navigation will occur for more in-depth analysis.
- Inspector pane - this is the tab collection on the right side of the Form Explorer window. Each of the six tabs - Details, Properties, Events, Hooked, Stream, and Advanced - will be described in more detail below.
When the Form Explorer initially appears, the window has very little information populated.
Getting Started
The first thing we must do is select a form to analyze. We do this via the Options panel, as seen below:
As you can see from the screenshot above, we are offered three options:
- Explore Last Form With Focus - This allows us to inspect literally any form we are able to view in Delphi. The only requirement is that the form itself has to have been focused once. If it has not, simply hit F12 to focus the form one time and enough data will have been collected for the plug-in to operate. The Form Explorer is generous enough to allow you to open a window while it is active to change "last focused" forms at will.
- Explore Delphi Application - This option actually inspects Delphi for you.
- Refresh - Refresh is simply an option to refresh the Form Explorer after a form has been selected.
The best way to describe the use of this plug-in is with a series of examples, as below.
Explore Last Form With Focus
Let's say we are interested in exploring a form. All we have to do is make sure we focus the form and click the Explore Last Form With Focus button. We can choose any form, one from our own project or one of Delphi's windows. For this example, I will open the Display tab of the Editor Properties dialog, as seen below:
After the Explore Last Form... button is clicked, the details of the Editor Properties window will be imported into the Form Explorer. Please see below:
Details
Let's say we are interested in checking out the "Margin and gutter" fields. In the Object Browser window, we can navigate down to the Gutter Width combo box. See the screenshot below:
As you can see, the Details window is immediately updated with information about the component we selected in the Object Browser.
The Details window displays the object-level specifics for our Object Browser selection. Included are the Name of the object, the Class Name, the Owner, the Parent, the Unit our object was declared in, and its complete object hierarchy. Looking at the Details window for the Gutter Width checkbox, we can see some rather interesting things.
For instance, while it looks like the Gutter Width is a standard checkbox, evidently it is not. If you notice the Lineage window, you will see that it is a custom type of THistoryPropComboBox. Also, unlike a standard TComboBox which is declared in StdCtrls.PAS, this checkbox is declared in one of the few source units not distributed with Delphi - IDEPropCtrls.PAS.
Exploring other controls, we can see the Visible Gutter checkbox is not a TCheckBox at all, but another custom control. It is actually a TPropCheckBox as is seen in the screenshot below:
The Details tab is discussed in further detail here.
Properties
Okay, we've seen that this plug-in allows us to dig into an object and see what it really is - even if we don't have the source file for it. What else can this do? How about analyze every exposed property of the active object? Yes, by simply turning the page to the Properties tab, we can view the name of every property. In addition, we can discover the kind of property (Integer, String, Enumerated, etc) we are looking at, the property's data type, and its current value.
The screenshot below displays the property settings for the eoGutterWidth checkbox:
Events
So far, we've seen this plug-in analyze an object and return its details and properties. How about some more analysis, you might ask? Want to see a little functionality as well? How's this then? Changing to the Events tab allows you to view a list of all events belonging to an object. In addition, you can see the type of each event (TNotifyEvent, TKeyEvent, etc) and the declaration of each event type. You can also determine which event handlers have been coded and what they are named.
The screenshot below displays the event handler settings for the eoGutterWidth checkbox:
As you can see, there are no event handlers connected to this object. Notice the OnExit event is selected; had there been a handler for this event, the Handler column would contain the name of the event handler, such as eoGutterWidthExit. The OnExit event is a TNotifyEvent type (which you can see in a column named Type if the horizontal scrollbar is moved).
Looking at the bottom of the Form Explorer window you will see the declaration of this event handler type "procedure (Sender: TObject) of object".
Now we have seen you can observe nearly every detail of an object using this plug-in. What else can we do? Lots! From this tab we can also trigger event handlers on demand and set up hooks for tracking our application during execution.
Still using our eoGutterWidth example, if we right click on an event handler in the Events grid, we get an event-tracking pop-up menu, as seen in the screenshot below:
This popup menu contains four options, each of which can be used to further inspect this object.
Trigger Event Handler
As the name implies, selecting this option when there is an associated event handler triggers the handler immediately. As you can see in the above screenshot, if there is no event handler, this option is grayed out.
Delay-Trigger Event Handler
This feature is very similar to the Trigger Event Handler option above. The only difference is when the event handler fires. When this option is selected, the following message dialog appears:
to inform you that this event will be triggered the next time the form being inspected regains focus.
Inspect Method Owner
This option grants you the ability to drill down even further in your analysis. When you select this option, the following dialog appears:
As you can see, if also has Details, Properties, Events, and Stream tabs. These tabs are identical in functionality to the tabs on the main Form Explorer window. The contents of this dialog represent the object that owns the event you clicked on.
In addition, there is a button, Analyze Object Memory that performs a more low-level analysis. The TObject Analyzer window is displayed. Please view the screenshot below:
This dialog consists of three windows:
- Hex Dump window - presents a hexidecimal breakdown of the memory allocated for the object we are inspecting. Right-clicking in this window gives you an option to Inspect Address. The Inspect Address feature analyzes the current memory location and returns the data type referenced there.
- Class Prototype window - presents a Delphi model of the object type we are currently analyzing.
- (unlabeled) Inspect Address window - the content of this window is controlled by the Hex Dump window. The results of the Inspect Address option are displayed here.
In addition, there is a Num Bytes to Analyze option, which defaults to 104. You can change this to any value you would like and click the lightning bolt button to refresh this window. BE VERY CAREFUL WITH THIS FEATURE!!! Peeking into the wrong areas of memory can be enough to bring Delphi crashing down without warning.
Finally, there is an Inspect button. This displays a new instance of the Class Inspector dialog, see above. This instance will be based on the current criteria in the TObject Analyzer window.
Watch This Event
This option introduces us to one of the most powerful and useful features of the Form Explorer plug-in, event tracing. This options allows you to dynamically hook almost any event in any Delphi class and watch it being fired (useful for determining if what you think might be possible really is). For example, you can hook the Application's OnHint event. Then, when you move the mouse over the toolbar buttons you can verify that the OnHint event is triggered and that the hint generated is correct for the button under the mouse.
This option is used as part of a two-step process for hooking and tracing events. Any events selected from this tab appear in a list on the Hooked tab. Please see below:
Hooked
The Hooked tab is a place that lists all events you have "hooked" for tracing. When it first appears, before any events have been hooked, it resembles the screenshot below:
So, how do we use this tab? Like this. First, we switch back to the Events tab. We right-click on the event we wish to view and select the Watch This Event option. As you can see in the screenshot below, the Handler column for the selected event changes slightly. While it still contains the name of the existing event handler, the phrase "(THookedEvent)" is appended to the front of the event handler name.
Now if we return to the Hooked tab we will see there is an event hooked. Since we had right-clicked on the OnExit event of the eoGutterWidth object, we see the event eoGutterWidth.OnExit listed as the hooked event (in the screenshot below):
This tab may look a little familiar to you if you have ever used reAct, the component testing portion of Developer Express' ExpressClassDeveloper product suite. The Hooked tab is basically an embedded version of reAct. As an event is fired, the light glyph changes color to indicate the event has triggered. If the checkbox beside the hooked event is checked, a message will be written to a CodeSite log as well.
Note: Due to the extensive changes between CodeSite versions 2 and 3, this may only properly send messages to a CodeSite 1 or 2 viewer.
Note: This plug-in does not include a copy of CodeSite. If you wish to use the logging feature you must first purchase a copy of CodeSite from Raize Software.
Stream
The Stream tab allows you to view the selected object as you would in Delphi's DFM file. Note that this is pure stream data. You do not need to have the DFM file present on your system to view the object stream on this tab. Please see the screenshot below:
Advanced
The tab appears below; notice that is comes with its own caution window:
Tip: You would do very well to heed this word of caution. Playing with memory allocation is something that can accidentally get you into a lot of trouble if you are not 100% sure what you are doing.
Create
The Create feature gives you the ability to create an instance of an object on-the-fly. You can specify a class type to create, name the object, and choose both a parent and an owner for your new object instance. When this feature is executed, the following dialog appears for you to specify the new component details:
The new component class and name must be entered in free-text mode. The new parent and owner can be specified via an object lookup. Clicking this ellipsis button beside each of these edit boxes displays a tree structure listing all available objects, as follows:
Note: This only lists objects that are available from the form currently being "explored" in this plug-in. In other words, you cannot declare the new owner to be an object that is not accessible.
The screenshot above represents the dialog that appears when selecting a new owner. To see the dialog for a new parent, click here.
Destroy
As the name of this option implies, Destroy allows you to destroy an existing instance of a component being inspected. For an arbitrary example, I opened Delphi as the target inspected object and selected a component for ModelMaker Code Explorer in my Object Browser. When I clicked the Destroy button, the Form Explorer prompts me for verification, as follows:
Selecting Yes would delete this component (and since I was inspecting Delphi itself, quite possibly crash Delphi). Select No cancels the delete operation.
Change Parent
The Change Parent feature gives you the ability to re-parent an object instance on-the-fly. The new parent can be specified via an object lookup. Clicking this button displays a tree structure listing all available objects, as follows:
Note: This only lists objects that are available from the form currently being "explored" in this plug-in. In other words, you cannot declare the new parent to be an object that is not accessible.
Clone
As its name implies, the Clone feature allows you to select an object and create a duplicate instance of it. A form very similar to the Create Component dialog appears with some information pre-populated. See the screenshot below:
You must specify a new name for this cloned object instance. Additionally, you are able to change either the parent or the owner, or both. As with the Create and Change Parent options above, you can perform a lookup for the New Parent and New Owner properties.
Explore Delphi Application
Analyzing Delphi is really no different than inspecting the last form with focus; in fact, in some ways, it is actually easier. For starters, you never have to worry about remembering to focus a window; simply click the Explore Delphi Application button and the Form Explorer populates with details about Delphi itself, as below:
Let's say we wanted to get creative and inspect CodeRush. After all, it is just another set of objects installed in Delphi, right? All we need to do is navigate in the Object Browser down to our desired target, such as CodeRushEngine in the example above. From here, we are free to inspect using the Details, Properties, Events, Hooked, Stream, and Advanced tabs as described above.
Now, let's take some time to delve further into the features the Object Browser offers us. Obviously, it is an object browsing control, displaying components in an ancestral order; opening the component at any tree node displays that component's children.
But what else can we do? If we right click on any node, a pop-up menu will appear, as in the screenshot below:
As you may notice, some of the items on the pop-up menu are named similarly to the features described elsewhere on this web page. That is because, for the most part, this pop-up menu offers you a shortcut; instant point-and-click access to features you would otherwise need to search through a series of tab controls to access.
Let's take a look at each of them, in order:
- Inspect - Just as when we select the Inspect Method Owner option from the Events tab, this option displays the Class Inspector dialog window for immediate inspection of a specified component.
- Inspect Child Control - Inspect child control is similar to the Inspect command, above. The main difference is that is operates on a specified child control of the currently selected component. When this item is selected, the Child Control Picker dialog is displayed. Selecting a control from this window then displays the Class Inspector dialog window for immediate inspection of a specified child component. The Child Control Picker dialog is displayed below:
- Flash Soft - Flash Soft does a quick refresh of the component you selected.
- Flash Hard - Flash Hard unloads the component from memory and reloads it for a more complete refresh.
- Search - This option is akin to the search functionality in Delphi; however, its scope is limited to the names of the items listed in the Object Browser. When this feature is executed, the following dialog appears:
- Search Again - This option simply follows the Microsoft standard of allowing you to press F3 to repeat a current search.
- Reparent - This option allows you to reparent the selected component. It is functionality identical to the Change Parent option discussed above.
- Clone - This option allows you to make a duplicate of the selected component. It is functionality identical to the Clone option discussed above.
- Destroy - This option allows you to destroy the selected component. It is functionality identical to the Destroy option discussed above.
But Wait! There's More!!!!
Mark hid a little more functionality in this control. Rather than right-click on a component in the Object Browser, hold down the Shift key while you right-click. You will see a pop-up that looks like the following:
You will notice there are two additional options:
- Embed Spy - This feature displays a dialog that allows you to create a Windows "spy" and associate it with the selected component. You provide a text string that will be prepended to every Windows message sent to that control. The purpose of this is to spy on the Windows messaging system as it interacts with this control by routing a copy of each message to CodeSite. You have the option of filtering when you want Windows message spying to occur. Please see the screenshot below:
- Remove Spy - This option is initially disabled. The only time it is enabled is when a "spy" has previously been created and associated with the selected component.