So very, very messy
OK, I admit it. The shim control is a mess. If you don’t know what the shim control
is, it is an sample (AKA unsupported) ActiveX control that hosts .NET user controls
for use in ActiveX control containers. The reason for its miserable existence is in
how .NET user controls are run as ActiveX controls (actually the failure of that).
At one time, early in the development of the .NET Frameworks, user controls were to
act and behave like ActiveX controls when in an ActiveX control container. However,
there were enough differences between .NET and ActiveX that the decision was made
to now allow user controls to be hosted as ActiveX controls except in two cases, when
the container either is Internet Explorer or MFC (I think MFC was added with the 1.1
release of .NET).
This was bad for the Visual Studio automation model because using the method Windows.CreateToolWindow,
you can host an ActiveX control on a tool window just like any other tool window in
VS. But since .NET user controls could not be hosted as an ActiveX control, we needed
a more creative solution and the shim control was born. The shim control (an ActiveX
control written using ATL) has a method that you can call to tell it to host a .NET
user control. It does this by first spinning up an instance of the Framework, then,
using interop, creating an instance of the desired user control, grabbing the HWND
of that control, and using the HWND parenting the control to the ActiveX control.
Great idea, right? In theory, yes, in practice, no. The first problem is distribution.
Currently everybody has to modify the controls’s GUIDs and ProgID before shipping
otherwise they could mess up other Add-ins that use that control. The way I should
have fixed it: create a merge module and distribute the merge module. By the time
I realized this was broken, it was already in the wild and too many people were using
it. The second problem: accelerators. We have always had problems with tool windows,
ActiveX controls, and accelerators. Since VB5 (where some of VS gets its code), we
have had this problem. I fixed some of the problems in subsequent versions, but the
shim control compounds them since it does not redirect accelerator to the correct
place. This was partially fixed in a later version of the control (which was never
very widely distributed), but it was not fixed completely and some special case code
Will this get better? Yes. In the next version of VS we will have a new method, CreateToolWindow2,
which takes as it’s arguments an assembly and a class name. We will then host the
control without the shim. Not only that, but we will host the window more like VS
does and not the way they were hosted in prior versions. When a tool window is created
using CreateToolWindow we host the control using the ActiveX control containment interfaces.
However, tool windows that are built into VS are handled differently. CreateToolWindow2
will use this other method, which uses less code and requires less negotiation between
the container and the control to be displayed.