- Table of Contents
- Copyright
- About the Authors
- About the Contributors
- Acknowledgments
- Tell Us What You Think!
- Introduction
- How to Use This Book
- What You Need to Use This Book
- What's New in Visual C++ 6.0
- Contacting the Main Author
- Part I: Introduction
- Chapter 1. The Visual C++ 6.0 Environment
- Part II: MFC Programming
- Chapter 2. MFC Class Library Overview
- Chapter 3. MFC Message Handling Mechanism
- Chapter 4. The Document View Architecture
- Chapter 5. Creating and Using Dialog Boxes
- Chapter 6. Working with Device Contexts and GDI Objects
- Chapter 7. Creating and Using Property Sheets
- Chapter 8. Working with the File System
- Chapter 9. Using Serialization with File and Archive Objects
- Part III: Internet Programming with MFC
- Chapter 10. MFC and the Internet Server API (ISAPI)
- Chapter 11. The WinInet API
- Chapter 12. MFC HTML Support
- Part IV: Advanced Programming Topics
- Chapter 13. Using the Standard C++ Library
- Chapter 14. Error Detection and Exception Handling Techniques
- Chapter 15. Debugging and Profiling Strategies
- Chapter 16. Multithreading
- Chapter 17. Using Scripting and Other Tools to Automate the Visual C++ IDE
- The Developer Studio Object Model
- Using VBScript to Write Developer Studio Macros
- Writing Developer Studio Add-Ins
- The SourceInfo Add-In
- Summary
- Part V: Database Programming
- Chapter 18. Creating Custom AppWizards
- Chapter 19. Database Overview
- Chapter 20. ODBC Programming
- Chapter 21. MFC Database Classes
- Chapter 22. Using OLE DB
- Chapter 23. Programming with ADO
- Part VI: MFC Support for COM and ActiveX
- Chapter 24. Overview of COM and Active Technologies
- Chapter 25. Active Documents
- Chapter 26. Active Containers
- Chapter 27. Active Servers
- Chapter 28. ActiveX Controls
- Part VII: Using the Active Template Library
- Chapter 29. ATL Architecture
- Chapter 30. Creating COM Objects Using ATL
- Chapter 31. Creating ActiveX Controls Using ATL
- Chapter 32. Using ATL to Create MTS and COM+ Components
- Part VIII: Finishing Touches
- Chapter 33. Adding Windows Help
- Part IX: Appendix
Writing Developer Studio Add-Ins
A Developer Studio add-in is a COM object that enhances the Developer Studio environment. An add-in has access to the same Developer Studio object model used by the VBScript macros discussed in the first part of this chapter. As you can with a macro, you can use an add-in to implement commands that are accessible via the toolbar, a menu item, or the command line. The main advantage of add-ins over macros is that an add-in is compiled and therefore offers improved performance over a macro.
All Developer Studio add-ins are in-process COM objects implemented in DLLs. The DLL must be placed in the Common\MSDev98\AddIns subdirectory, where it is discovered by Developer Studio when the compiler is launched. Add-ins can be written in Visual Basic or Visual C++, but because this is a book about Visual C++, we'll use C++ for our example.
Using the Developer Studio Add-In Wizard
The simplest way to write an add-in using Visual C++ is to use the Developer Studio Add-In Wizard. This wizard creates a project that includes the necessary source files and resources used to create the skeleton of a Developer Studio add-in.
To use the Developer Studio Add-In Wizard, open the New dialog box by pressing Ctrl+N or choosing New from the File menu. Figure 17.2 shows the New dialog box.
Figure 17.2 Selecting the Add-In Wizard in the New dialog box.
As shown in Figure 17.2, you must select DevStudio Add-In Wizard as the project type. After supplying a project name and clicking OK, you see the one-page Developer Studio Add-In Wizard (see Figure 17.3).
Figure 17.3 The Developer Studio Add-In Wizard.
You can specify the following information in the wizard:
- The name of the add-in. This name will be displayed to the user in the Add-ins and Macros property page in the Developer Studio Options dialog box. By default, the name of the add-in is " [project name] Developer Studio Add-in", where [project name] is the name of your add-in project.
- A description of the add-in. This description also will be displayed in the Options dialog box.
- Whether your add-in includes a toolbar. If your add-in will be accessible through a toolbar, make sure you enable this check box.
- Whether your add-in should be notified of Developer Studio events. If your add-in should be notified about Developer Studio events, such as loading and unloading files or projects, be sure to enable this check box.
As with most projects created using Developer Studio wizards, you can immediately compile the add-in and use it in Developer Studio. To make your add-in useful, you generally need to perform the following actions:
- Modify the toolbar icon, if your add-in is displayed on the toolbar.
- Add command-handling code for your add-in.
- Add event-handling code if your add-in responds to Developer Studio events.
These steps are discussed in the following sections.
The Developer Studio Add-in Architecture
An add-in created with the Developer Studio Add-In Wizard supports two interfaces:
- IDSAddIn is exposed by the add-in to enable connecting and disconnecting from Developer Studio.
- ICommands is exposed by the add-in to enable Developer Studio to invoke commands in the add-in.
If the add-in responds to events from Developer Studio, two additional interfaces are supported:
- IApplicationEvents is exposed by the add-in to receive application events from Developer Studio. Examples of these events include opening and closing documents and workspaces.
- IDebuggerEvents is exposed by the add-in to receive events when breakpoints are hit during a debugging session.
The add-in project consists of both ATL and MFC code. The COM interfaces are supported using ATL, while MFC is used for the DLL framework and user interface. The Add-In Wizard creates three main classes for the project:
- CCommands is an ATL class that implements a COM object derived from the ICommands interface. You add functionality to this class to implement commands for your add-in.
- CDCAddIn is an ATL class that implements a COM object derived from the IDSAddIn class. This COM object manages the connection with Developer Studio.
- C <projectName> App is an MFC class derived from CWinApp that provides the basic framework for the DLL code.
If your add-in responds to Developer Studio events, two nested classes are placed in the CCommands class:
- XApplicationEvents is an ATL class that implements the IApplicationEvents interface. If you're interested in handling Developer Studio events, this is the place to add your code.
- XDebuggerEvents is an ATL class that implements the IDebuggerEvents interface. This is the class that will contain any code you write that interacts with the debugger.
The main COM interface exposed by Developer Studio is IApplication. If your add-in is created by the wizard, a pointer to this interface is available as the CCommands::m_pApplication member variable.
Adding Command-Handling Code
Each command in an add-in has a corresponding function in the add-in's ICommands interface. If the name of your add-in is Bobs File Counter, for example, the ICommands interface includes a function named BobsFileCounterCommandMethod.
Developer Studio imposes a few user-interface restrictions on your add-in:
- Your add-in cannot display any modeless dialog boxes or views.
- Before displaying a modal dialog box, your add-in must disable any modeless dialog boxes by calling the IApplication::EnableModeless member function, passing a parameter value of VARIANT_FALSE.
- After displaying a modal dialog box, your add-in must re-enable modeless dialog boxes by calling the IApplication::EnableModeless member function, passing a parameter value of VARIANT_TRUE.
The Developer Studio object model is available to your add-in, just as with a VBScript macro. Listing 17.3 shows a typical command handler. This command handler displays a modal message box that contains the number of currently open files in Developer Studio.
Example 17.3. A Simple Command Handler for a Developer Studio Add-In
STDMETHODIMP CCommands::BobsLineCounterCommandMethod()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// Retrieve the Documents collection Automation interface
CComPtr<IDispatch> pDocsDisp;
VERIFY_OK(m_pApplication->get_Documents(&pDocsDisp));
// Query for the vtable interface
CComQIPtr<IDocuments, &IID_IDocuments> pDocs(pDocsDisp);
if(!pDocs) return E_FAIL;
// Get the total number of open documents.
long docCount;
VERIFY_OK(pDocs->get_Count(&docCount));
// Format a message to be displayed to the user
TCHAR szMsg[48];
if(docCount != 1)
wsprintf(szMsg, _T("There are %d open documents"), docCount);
else
wsprintf(szMsg, _T("There is one open document"));
// Disable modeless dialog boxes, and display the message
// to the user.
VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
MessageBox(NULL, szMsg, "XSourceInfo", MB_OK | MB_ICONINFORMATION);
VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
return S_OK;
}
Listing 17.3 begins by calling the AFX_MANAGE_STATE macro. You must call this macro in DLL entry points that are exported by DLLs using MFC. For more information about AFX_MANAGE_STATE, see Technical Note 58, "MFC Module State Implementation," in the MSDN Library.
After the AFX_MANAGE_STATE macro is called, the number of open documents is retrieved. This process consists of several actions:
- Them_pApplication interface pointer is used to get the pointer to the Automation interface of the documents collection. This pointer is stored in an instance of CComPtr, an ATL wrapper class for COM interface pointers.
- The ATL CComQIPtr class is used to query for the IDocument interface. CComQIPtr is another ATL smart pointer class that automatically queries for a specific interface. Both CComPtr and CComQIPtr are discussed in more detail in Chapter 29, "ATL Architecture."
- Finally, the number of active documents is retrieved by calling the IDocuments::get_Count function.
Note that before displaying the modal message box dialog, modeless dialog boxes are disabled by calling the EnableModeless function. After the message box is dismissed by the user, EnableModeless is called again to re-enable modeless dialog boxes in Developer Studio.
In Listing 17.3, all functions that return an HRESULT are tested using the VERIFY_OK macro. In debug builds, this macro verifies that the function returns S_OK. If the function returns a different HRESULT value, a debug trace is created. In release builds, this macro has no effect.
A more complete example of an add-in is presented later in this chapter in the section "The SourceInfo Add-In."
Handling Developer Studio Events
In order to enable add-ins to be fully integrated into Developer Studio, the add-in architecture provides for events to be sent from the IDE to an add-in when specific events occur. These events include opening documents, starting project builds, and hitting a debugger breakpoint. There are two types of events: Application events are reported through the IApplicationEvents interface, and Debugger events are reported through the IDebuggerEvents interface.
The following Developer Studio events are provided to add-ins that support the IApplicationEvents interface:
| Event | Sent … |
| BeforeBuildStart | As a build starts. |
| BuildFinish | When a build ends. The number of warnings and errors is passed as parameters with the event. |
| BeforeApplicationShutDown | As Developer Studio is shut down. |
| DocumentOpen | When a document is opened in Developer Studio. A pointer to the document's IDispatch interface is passed as a parameter with the event. |
| BeforeDocumentClose | Just before a document is closed. A pointer to the document's IDispatch interface is passed as a parameter with the event. |
| DocumentSave | After a document is saved. A pointer to the document's IDispatch interface is passed as a parameter with the event. |
| NewDocument | After a new document is created. A pointer to the document's IDispatch interface is passed as a parameter with the event. |
| WindowActivate | After a window has become active. A pointer to the window's IDispatch interface is passed as a parameter with the event. |
| WindowDeactivate | After a window has been deactivated. A pointer to the window's IDispatch interface is passed as a parameter with the event. |
| WorkspaceOpen | When a workspace is opened in Developer Studio. |
| WorkspaceClose | When a workspace is closed in Developer Studio. |
| NewWorkspace | When a new workspace is created in Developer Studio. |
In addition to the preceding events, add-ins that implement the IDebuggerEvents can receive the following event generated by the Developer Studio debugger:
| IDebuggerEvents | Sent after a breakpoint is hit. A pointer to the breakpoint's IDispatch interface is passed as a parameter with the event. |
In order for your add-in to be notified of Developer Studio events, you must select the Responds to Developer Studio events option offered by the Add-In Wizard when your project is created. The wizard inserts the necessary code into your project and provides skeleton implementations for each of the Developer Studio events.
These events are used by add-ins that need to update their internal state when specific events occur. An add-in that tracks the status of project builds, for example, would provide a meaningful implementation for the BuildFinish event.
The default implementation provided by the Add-In Wizard simply returns S_OK for each event. As Listing 17.4 shows, events are handled in two nested classes enclosed in the CCommands class. The XApplicationEvents class handles application events, and the XDebuggerEvents class handles the debugger event.
Example 17.4. An Example of the Skeleton Event-Handling Code Provided By the Add-In Wizard
HRESULT CCommands::XApplicationEvents::BeforeApplicationShutDown()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return S_OK;
}
Event-handling functions have the same restrictions as the command-handling functions discussed in the previous section. You must use the AFX_MANAGE_STATE macro, you cannot use modeless dialog boxes or views, and you must disable Developer Studio's modeless dialog boxes before displaying any of your own modal dialog boxes.
The SourceInfo Add-In | Next Section

Account Sign In
View your cart