Controlling Developer Studio Objects Through Dual Interfaces

Home Page (Add-ins)OverviewHow Do I ... TopicsFAQReference

Each Developer Studio object implements a dual interface through which you can control the object. Each object implements an IDispatch interface for Automation and a COM interface for direct access to object members (properties, methods, and events).

The following table shows the dual interface used by each Developer Studio object.

Object Dual interface
Application Iapplication
Breakpoint Ibreakpoint
Breakpoints Ibreakpoints
BuildProject IbuildProject
Configuration Iconfiguration
Configurations Iconfigurations
Debugger Idebugger
Document IgenericDocument
Documents Idocuments
Project IgenericProject
Projects Iprojects
TextDocument ItextDocument
TextSelection ItextSelection
TextWindow ItextWindow
Window IgenericWindow
Windows Iwindows

Add-ins written in Visual C++ versions 5.0 or later, or in Visual Basic versions 4.0 or later can employ early binding by using the COM interface. Early binding makes all calls into interface members faster at run time.

Alternating Between Dual Interfaces

In Visual C++, you can switch from one dual interface to another by calling QueryInterface. For example, to switch from the COM IGenericDocument interface on a TextDocument object to the COM ITextDocument interface, use the following code:

IGenericDocument* pDoc;
pApplication->get_ActiveDocument(&pDoc);
BSTR bstrType;
pDoc->get_Type(&bstrType)
if (!wcscmp(bstrType, L"Text"))
{
   // It is a text document, 
   // ..so QI for the right interface
   ITextDocument* pTextDoc;
   pDoc->QueryInterface(IID_ITextDocument, &pTextDoc)
   // Now, we can use text-specific
   //   members of pTextDoc
   pTextDoc->Release();
}
SysFreeString(bstrType)
pDoc->Release();

Tip   The ActiveX Template Library (ATL) provides smart COM pointers that can help you. See the CComPtr and CComQIPtr classes for details.

Using Return Values from Dual Interfaces

If a property or method of a Developer Studio object returns a value of type T, then the corresponding dual interface method returns an HRESULT but accepts an additional argument of type "pointer to T" (or T*). This argument is at the end of the argument list. For example, if a property returns a value of type Long, then the corresponding dual interface method accepts an additional argument of type "pointer to Long" (or Long*).

When the method returns, Developer Studio stores the return value where the last parameter points. For example, the Close method of the ITextWindow interface returns a DsSaveStatus value. The dual interface version of this method is declared as HRESULT Close (VARIANT boolSaveChanges, DsSaveStatus* pSaved). The last parameter, which is declared as DsSaveStatus*, is where Developer Studio stores the return value.

The Visual C++ code to do this looks like the following:

DsSaveStatus saveStatus;
if (myTxtWindow->Close(VARIANT_TRUE, &saveStatus) == S_OK)
{
   //code here could check the value of    //saveStatusreturned by Close
}

If the function succeeds, the HRESULT returned by the dual interface method is a success code like S_OK. If the function fails, however, the function returns an error code instead. This error code has the same value as one thrown in a dispatch exception when you call the method through the dispatch interface.

Tip   The Developer Studio error codes are in the *defs.h header files, located in Microsoft Visual Studio\VC98\Include\ObjModel.

Manipulating Properties of Objects Through Dual Interfaces

To get a property of an object, prepend "get_" to the property name. Alternatively, to set the property of an object, prepend "put_" to the property name.

For example, to get the height of the Application object, prepend "get_" to the Height property, as shown in the following code:

long nHeight;
if (pApp->get_Height(&nHeight) == S_OK)
{
   //code here references the Height property through    //nHeight
}

Alternatively, to set the value of the Height property to 40, you would use the following code:

pApp->put_Height(40);

Calling Methods of Dual Interfaces

Some dual interface methods use parameters called "Reserved" of type VARIANT, and other methods use parameters that are optional. With VBScript macros or add-ins authored in Visual Basic, you can omit such parameters. However, with add-ins authored in Visual C++, you must use these parameters, you must pass a VT_ERROR VARIANT for each parameter, and you must specify the scode of the VARIANT as DISP_E_PARAMNOTFOUND.

For example, with MFC you can call the AddToolSettings method of the Configuration object by using the following code:

COleVariant var(0L,VT_ERROR);
var.scode=DISP_E_PARAMNOTFOUND;
pConfig->AddToolSettings(bszTool, bszSettings, var);

Some interfaces have methods called "Reserved1," "Reserved2," and so on. Do not use these methods.