Finding the Orchestration Viewer Controller II

Jason Birth has released a new version of his BizTalk Server 2004 Documentor program that handles (you guessed it) BizTalk Server 2006. The download is available from gotdotnet here; the project page can be found here. It is a great little program that generates a handy CHM file which, unlike groups of HTML files, are easy to print. When you run the program and check out the output, one of the things included (unlike the Minty Fresh Documentor) is a picture of each orchestration:

Jason's Documentor program has orch pix

Beautiful (you do detect a bit of envy). I wonder if Jason used the ODViewCtrl from the Microsoft.BizTalk.BRMAControls assembly we found in part I? I don't think he would mind if we sniff through the code a bit. Using Reflector, I took a quick look at the source:

Jason uses Microsoft.VisualStudio.EFT.ProcessView

Following the arrow you will see that it does not use ODViewCtrl; it uses Microsoft.VisualStudio.EFT.ProcessView. As Scooby says, rrrrrrruuuuhhhh? ProcessView must have special mojo that the ODViewCtrl doesn't have, or is it just a matter of personal preference.

(ProcessView is used internally by ODViewCtrl. I decided to stick with the functionality of ODViewCtrl becase I like the idea of using it both for interactive applications and for dumping images to disk.)

Notice the code next to the squiggle on the disassambly pane of the Reflector output above. This code generates a bitmap of the orchestration by fabricating PrintPageEventArgs, then calling OnPrint. Nifty code that obviously does the trick, but it seems like the .Net framework is making us do a lot of work. All we really want to do is tell the control to paint itself into our bitmap instead of to a "bitmap" headed for the screen.

Enter DrawToBitmap(). This method causes the target control to be rendered into a bitmap and works by performing tricks similar to those performed by the UK Documentor behind the scenes. It does not reliably work with ActiveX controls but it performs flawlessly with our friend ODViewCtrl. Turns out it is trivial to modify our last sample to render directly to a file using our newfound method:

static void Foo(string path, string xsym)
{
Microsoft.BizTalk.Tracking.ODViewCtrl odViewControl = new ODViewCtrl();

odViewControl = new ODViewCtrl();
odViewControl.BackColor = Color.AliceBlue;
odViewControl.Enabled = true;
odViewControl.Name = "odViewControl";
odViewControl.PermanentBreakpoints = true;
odViewControl.RightToLeft = RightToLeft.No;
odViewControl.TrackedArrows = true;

// Remove the title label control
odViewControl.Controls.RemoveAt(0);

// Readjust the panel control containing the orch view to
// accomodate missing title label
Control c = odViewControl.Controls[0];
int y = c.Location.Y;
// Offset voodoo to make clean pic
c.Location = new Point(-5, -10);
c.Size = new Size(c.Size.Width, c.Size.Height + y);

odViewControl.Visible = true;
odViewControl.ShowSchedule(xsym);

// This makes sure the whole orch is in view prior to save
Microsoft.VisualStudio.EFT.ProcessView pv = (ProcessView)odViewControl.Controls[0].Controls[0];
Size s = pv.PreferredSize;
odViewControl.Size = s;

// Call, save, done!
Rectangle rect1 = new Rectangle(0, 0, s.Width, s.Height);
Bitmap bitmap1 = new Bitmap(rect1.Width, rect1.Height);
odViewControl.DrawToBitmap(bitmap1, rect1);
bitmap1.Save(path);
}

There is a little hocus-pocus in there but overall a painless process. If you want to use this function, grab the bits for a simple helper assembly here. I will be migrating this code into the Minty Fresh Documentor in the near future.