Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Creating an Add-in to host a GUI inside the Developer Studio IDE

0.00/5 (No votes)
5 Jun 2002 1  
An article on hosting your own custom window inside of Microsoft Developer Studio

Sample Image - DevStudioHost.gif

Introduction

This article offers a possible solution to the problem of hosting your own GUI inside of MS Developer Studio 6.x, as an Developer Studio Add-In, without crashing the app and behaving well with such add-ins as WndTabs. 

I have seen several people ask questions on how to do this, and I have wanted to do this myself, in order to host the visual development tool I have been working on using the VCF. So a while ago I spent a couple of weekends fighting with Developer Studio, and came up with this solution, initially making it work for hosting the VCF Builder, and then rewriting a bit of it to make the project more general for this article.

While this is probably not the only solution, it is the only way I was able to accomplish the following:

  • As a Developer Studio Add-In, host a window, to which other child window could be added, inside of Developer Studio, and specifically map it's resizing to the area that is used for MDI Child windows.
  • Not have any dependencies on any of the advanced Add-in lib's that are typically required for doing Developer Studio integration. These cost a great deal of money for membership dues ( I believe at the time I looked it up the cost was around $50,000 USD a year for membership with a minimum of 5 years), and require the signing of an NDA.
  • Cooperate with existing GUI add-ins like WndTabs

Initial issues

Initially I thought I could simply add a new Document Type, since Developer Studio is based on MFC Doc-View. This unfortunately cannot be done safely. You can get the document type to register, and you may even succeed in having your MDI Child window appear, but once you close the workspace it is attached to, all hell breaks loose and you crash Developer Studio. Sigh...

So then I though I could just get tricky and capture an existing MDI Child window and simply add my own windows to the view - once again, while I was able to attach my child window to the view, the moment I closed the MDI Child, or the workspace - BOOM - Developer Studio crashed. Grrrrr.

So then I thought maybe I can attach a child window to the MDI Client window - the parent window for all the MDI Child windows that get created. I tested this in a simple MFC MDI app, and sure enough it worked OK, no crashes. Cool, so hack, hack, hack, and I was ready to test it with Developer Studio. Once again, no dice - the window would appear correctly, and I could control it, but when I closed a workspace, things would crash again.

The reasons for the above crashes are related to not having the special extension lib's that are needed to safely extend the IDE GUI, such as adding in custom Doc Templates. And since these libraries are not available without getting into the special Developer Studio "club", as mentioned above, it is impossible to do this.

So the final thing to try was to create a child window that was parented not to the MDI Client, or another MDI Child window, but directly to the main Developer Studio window itself, just like all the toolbar docks are. Essentially the same thing that Oz Solomonovich does with his WndTabs add-in (damn - kinda makes you feel stupid at this point!). This host window is then able to be switched on and off, allowing you to easily go from the Developer Studio MDI interface to the host view. 

Once the host works you can pretty much do whatever you want. You could even embed a CMDIFrameWnd in the host and have your own MDI Child windows ! If you trap the events that the IApplicationEvents interface exposes, you can get notified for most of the major GUI events, like opening a new project, and saving or creating a new document. With this you could even mirror many of the editor types already in existence or make new ones. Or do something entirely different, such as host a cool Win-Diff display, or hosting a cool UML Modeling tool inside of this.

How the Host works

The hosting works by sub-classing the Developer Studio main window, and by setting up a Windows Hook procedure to trap certain messages. Once the hook is established it, the procedure traps WM_SIZE and WM_MOVE messages intended for the MDI Client window and adjusts our host window accordingly. The nitty-gritty details follow below.

When I built the add-in I used the default Developer Studio Add-in wizard, and accepted the defaults. An add-in has several parts, the first, which manages some of the startup and shut down routines, is the CDSAddIn. The CDSAddIn::OnConnection() method is called when the add-in is first initialized by Developer Studio, and it is here that the window sub classing and message hook installation takes place.  

To sub class the window I used a little class I found in the WndTabs source code called CSubClassWnd, which I altered just a tad. Basically you create an instance and pass it an HWND, and then it has another method that you can call to hook up the rest of the sub classing magic, part of which is done through a call to CWnd::SubclassWindow(). By sub classing an existing window handle you can get access to the WndProc and replace or enhance it with your own message handling. 

So, once in the CDSAddIn::OnConnection() method we store off the current CWinApp's hinstance and threadID. Then the AFX_MANAGE_STATE macro is used to switch the state so that our add-ins access to it's resource's will function correctly. Note that the manage state macro is done after the storing of the hinstance and threadID - if we had switched state before, then the values would be different - what we want is to have the hinstance and threadID for the Developer Studio app. 

The next thing is to grab the active window and then walk up the parent child chain (using GetParent() ), until we get to the Developer Studio main window. Then using the main window handle, we create an instance of our CDevStudioMainWnd. This class is the part that performs the magic of sub classing the main wnd, and from this we can get, and hold on to, a handle to the MDI Client window (this is achieved in the CDevStudioMainWnd::GetMDIClientHWND() method). 

Once we have the MDI Client handle, we can go ahead and create the host view - this is a simple class that is derived from CView. The host view is created and parented to the main window that we have wrapped in the CDevStudioMainWnd instance. 

The final step in all of this is the creation of our windows hook - this is accomplished by calling SetWindowsHookEx() and passing in the type of callback (in our case WH_CALLWNDPROC for general windows messages), our call back procedure ( in the CDSAddIn code ), and the hinstance and threadID we stored off earlier. This will now route these messages to our callback as well as to the regular WndProc for which they are intended, and allow us to "peek" into the message loop. Once messages do get to our callback, we can check the window handle the message is intended for, and if it is the MDI Client handle, and the message types are WM_SIZE or WM_MOVE, we just resize our host view, and voila!, we have a working host child window inside of Developer Studio!

The clean up for all of this takes place in the CDSAddIn's CDSAddIn::OnDisconnection() where the CDevStudioMainWnd instance is deleted and the UnhookWindowsHookEx() method is called to detach our windows hook callback.

The Add-in itself has two commands to allow switching from the Developer Studio Environment, in other words making the host view invisible and displaying the normal MDI client area, to the Host Environment, which makes the host view re-positioned so it is on top of the MDI Client area and visible.

Any suggestions on how to either improve this or develop it further would be greatly appreciated !

Credits

The original CSubClassWnd code was done by Oz Solomonovich, as was the technique used for getting at the MDI Client window handle.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here