Wow, what you can learn by perusing someone else’s code…
Cool Code: Managed Stack Explorer
- It’s got a two-panel layout for (a) Processes and (b) the Threads in each Process
- More importantly, it’s got auto-resizing of these panels when the whole app window is resized (much like I want to have a panel for Applications and another for the Documents open in each Application). Very slick-looking.
- Whenever you click on a Process in the left-hand panel, it updates a lower display of detailed information about the Process (much like I’d wanted to put in tooltips in CacheMyWork, but this might be even better).
- It has another panel that is initially collapsed, but that can be opened/expanded by the user, and possibly by the app in response to certain events (much like I’d wanted the Documents panel to initially be hidden and/or hideable, but able to be opened by the user or in response to certain events e.g. (a) click on a Process; (b) if the Process has Documents open, automatically open the Documents panel).
- When a new .NET application starts, the list of Processes in this application is automatically updated!
Makes me want to do it all now, but there are some questions to which I don’t know the answers right yet:
- Is there such a thing (i.e. a native or custom Class available) to create a CheckListBox (as I have right now) that has multiple Columns? Could the Columns be resizeable and resortable?
- Does the auto-update of the Processes list require multi-threaded coding?
Reverse-engineering the code
It turns out that, for some unknown reason, when I download the source code and try to open the Design View on any of the WinForms classes (e.g. MainGui.cs, InfoSelect.cs), Visual Studio throws an error and won’t show me the visual design view. That sucks, ’cause it’s a heckuva lot easier to explore the code by selecting the control(s) you’re interested in and jumping right to the relevant entry point.
Instead, I’ve spent a couple of hours poring over the MainGui.Designer.cs class, assembling a picture for myself of which components relate to which. It was very instructive, but it felt kind of like trying to build a Lego model of a Tie Fighter in a pitch-black room:
- I found out that the SplitContainer control class is what’s used to implement (1) and (2)
- There are multiple SplitContainer objects in this application, nested one inside the other like those carved Russian dolls.
- The SplitContainer object hierarchy appears to be like this (I’ve colour-coded the object names to show where they are in the UI below):
- listsSplitData > ptSplitInfo & FixedPanel.Panel1
- ptSplitInfo > processSplitThread & groupBox2
- processSplitThread > processView & threadView
- The other objects encapsulated in the SplitContainers are arranged:
- groupBox2 > processDataLayout
- processDataLayout > label1 – label 12
- processView > ProcessName column, PID column
- threadView > tid column, threadState column
This means the application’s UI is more or less constructed as follows:
I think I’ve done a decent job mimic’ing the SplitContainer usage demonstrated here, so all I’d like to do at this point is figure out how to create that right-column expand/contract control. [I’ll leave the auto-update with new Processes behaviour for later.]
After jumping back & forth through the code a few times, it appears that:
- The control I’m after is labeled viewStackTraceToolStripMenuItem.
- It appears be to an instance of ToolStripItem and a child of a ContextMenuStrip, and has a single Click() Event Handler.
- That event handler calls a routine threadview_DoubleClick(), which calls ShowSelectedThreadStackTraces().
- The former routine calls ExpandAndCollapse(), which appears to be the magic behind the whole thing.
If I were to implement this routine or similar, then all I have to figure out is how they created the “>” control that expands & collapses the FixedPanel.