Preface
To preempt those who may complain that this is not a new project (for whatever reason) I have the following three points to make:
- I agree that it is not an entirely new project (see the original article)
- However, if I don't repost it to the 'Tools' section the very people who requested it (.NET, Delphi, C++ Builder, etc users) will not find it.
- If you take to time to read the article you will see that there are aspects of it that are entirely diffrent from those of the original article.
If you do not think that it is original enough to (re)vote for it then I'm cool with that, but please take a moment to reflect if you're tempted to vote it down for the same reasons.
Introduction
When I first wrote CodePlotter as a VC6 addin I was very aware that .NET users might also be interested in a similar tool.
At the time however I did not see an easy way to resolve this except by writing a .NET specific addin.
So in the best tradition of ostrichs I ignored the issue and waited until I was forced to deal with it.
In due time one or two .NET users posted comments expressing an interest in a CodePlotter addin for VC7/.NET and I knew that I would have to deal with it, especially since so many people were voting it up.
Now, I had already made a short foray into VC7 addins when I tried to port ProjectZip to .NET and wasn't that a scary experience!
I don't know what Microsoft thought they were up to when they redesigned the plugin architecture for VC7 but it certainly was not portability of VC6 addins - I could not make head nor tail of the object model in the short time that I tried.
Fortunately, a C++ Builder coder who also dabbles in VB and Delphi came to my rescue and asked for a standalone executable .
This, I thought, smells like an opportunity not to be missed; and may yet save me from having to write a .NET port.
Still another poster asked for the modal dialog in the CodePlotter addin to be made modeless so that he could scroll his code as he drew the diagram. This however generates another problem because the addin relied on the selection not changing so that it could paste the edited diagram over the top of the original diagram.
An executable was therefore beginning to look like an excellent solution, since although it would lose its tight coupling with VC6, this would more than be made up for by the considerably greater flexibility of a standalone application.
CodePlotter Remoded
The first design to take form would have the user:
- copy and paste the diagram in their code into the CodePlotter interface
- edit the diagram
- copy (somehow) and paste the diagram back into their code.
This was okay I thought but lacked some of the finesse of the VC6 addin which was much slicker in how it used the selection mechanism of the object model to both select and replace the code diagram (a feature that in retrospect, was also its greatest constraint since the user has no scope for inserting the diagram at any other place in the code except by manually copying and pasting it afterwards) .
I left it for a bit and later when I got to thinking about it some more I found that my brain had made the link between 'copying and pasting' and the 'clipboard'.
Not a tremendously exciting or impressive leap but a valuable one nonetheless since it allowed me to postulate the programmatic use of the clipboard as the final piece in the puzzle; the piece that would possibly give it the slickness it was so far missing.
So I searched back through all my old code to see if I had something to get me started and I came across the following fragment:
OpenClipboard();
CString sText((LPCTSTR)::GetClipboardData(CF_TEXT));
CloseClipboard();
Gee, I though, surely it can't be this easy (and I'm sure some of you will be itching to tell me just how difficult it really should be), but it was.
So all I had to do then was ensure CodePlotter was notified whenever the clipboard contents changed, via SetClipboardViewer(),
and I was set.
One final matter that was not discovered until I had the basic implementation up and running was how to prevent the user from having to run CodePlotter manually every time they wanted to edit a diagram, whilst at the same time not having it take up valuable space in the taskbar.
You've guessed it - our friend the system tray to the rescue.
So the way it works is this:
- The first time you want to use CodePlotter each session requires a manual start, unless you add it to your startup folder.
- Thereafter it resides as an icon in the system tray until it detects that you've just copied a diagram to the clipboard, whereupon it shows itself with the diagram already parsed.
- When you're done editing, the diagram is automatically copied back to the clipboard for you to paste back into your code.
Installing CodePlotter is as easy as...
- drop the executable into your "...\program files\microsoft visual studio\common\tools" folder
- Create a new tool for CodePlotter from the 'Tools|Customize...|Tools' tab
- Add the tool to your toolbar for easy access
Using CodePlotter
For a short tutorial on using CodePlotter I will refer you to this same section in the original article.
Other features only present in the standalone version include:
- A 'Copy' button for copying the current diagram to the clipboard without having to dismiss the dialog.
- A system tray context menu for exiting or displaying CodePlotter.
Inside CodePlotter
This section too is essentially unchanged from the original article except that in order not to have to copy the code, the CodePlotter exe borrows heavily from the Addin project.
This is more significant than it sounds because I also use Visual SourceSafe (VSS) at home.
The beef here is that VC6 when integrated with VSS does not allow more than one project to reside in the same hard drive directory (I had anticipated simply having two .dsp files in the same folder and share the code freely).
So I had to have two distinct project folder.
I know, I thought, I'll be really tricky and use VSS's share functionality to have a copy of the shared code in each of the project folders. That way each project will appear to have its own copy whilst in fact they are the same VSS file.
Half an hour later I remembered why this is a really bad idea � if the file is checked out to one folder and you check it back in from the other then it really easy to lose changes and end up completely b****red (that's 'battered' to you folk out there who were wondering if I was swearing).
So after about 3 false starts I decided for the KISS (keep it simple, stupid) approach � the CodePlotter executable project would share files from the addin project by including them in the Workspace|Files tab in VC6.
What's so significant about that?
Well, standard source files are ok, we do that all the time, but it was the first time I'd tried sharing an .rc file.
I knew already that VC6, except under considerable duress and with much incanting of spells and funny handshakes, will not let you have two .rc files in the same project so I just checked away the default one and added the addin's .rc file just as I had the other shared source files.
But then I hit another snag, the .rc2 file (just what is the point of that file anyway. I know what its intention is but I swear I have never seen an app use it � please someone show me a bonafide use for it).
The problem is that the .rc file includes this by relative path � relative to the project root that is � so although i was compiling the addin's .rc file in its original location the preprocessor wanted to locate CodePlotterAddin.rc2 in the standalone's folder.
So I did what any good hacker does. That's right, I simply deleted it to make it go away, and surprisingly enough it worked. More or less.
A bit more bodging of the .rc file to remove all references to it was required, as was a dummy .tlb file to stop the preprocessor from spitting the dummy (the .tlb file is the type library without which the addin would not export the necessary interfaces to communicate with VC6 � I know this because I tried deleting it too!)
Further Work
- Keyboard editing
- Better path finding when starting from the side opposite to the target box (the current implementation produces some very counter-intuitive solutions)
- Diamond shaped boxes
Copyright
The code is supplied here for you to use and abuse without restriction, except that you may not modify it and pass it off as your own.
History
- 1.0 Initial Release
- 1.1
- In-place editing of box text (thanks to =[ Abin ]=)
- Improved path finding (thanks to to_be_unknown)
- fixed bug relating to boxes resizing when moved (thanks to to_be_unknown)
- 1.2
- improved diagram verification (thanks to sunil_g7)
- context menus added for all non-drag'n'drop editing
- Enter/Escape keys can be used when editing box text
- 1.3
- reworked UI
- resizeable (and remembered between sessions) (thanks to Anonymous)
- Alternative comment styles for coder's wishing to working VB, NSBasic or C (thanks to Adrian Nicolaiev)
- 1.4
- 'Flip Connecton' added to context menu to reverse a connection's direction (thanks to Ralph Wetzel)
- press <F2> to edit the selected box's text (thanks to Anonymous)
- 1.6
- 'Copy' button bug fixed (thanks to Robert Etheridge)
- 'Resize box to fit' command removed for now (thanks to Robert Etheridge)
- '*' and '#' replaced by arrows at both the start and end of a connection (suggested by Robert Etheridge)
- user can define visual page width for guidance on line length (automatically takes any preceding comment length into account) (suggested by Robert Etheridge)
- some minor speed improvements