Implementation
The code below shows a simple implementation of an XMLSpy IDE plug-in. It adds a menu item and a separator (available with XMLSpy) to the Tools menu. Inside the OnUpdateCommand() method, the new command is only enabled when the active document is displayed using the Grid View. The command searches for the XML element which has the current focus, and opens any URL starting with "http://", from the textual value of the element.
/////////////////////////////////////////////////////////////////////////////
// CXMLSpyIDEPlugIn
#import "XMLSpy.tlb"
using namespace XMLSpyLib;
HRESULT CXMLSpyIDEPlugIn::OnCommand(long nID, IDispatch* pXMLSpy)
{
USES_CONVERSION;
if(nID == 1) {
IApplicationPtr ipSpyApp;
if(pXMLSpy) {
if(SUCCEEDED(pXMLSpy->QueryInterface(__uuidof(IApplication),(void **)&ipSpyApp))) {
IDocumentPtr ipDocPtr = ipSpyApp->ActiveDocument;
// we assume that grid view is active
if(ipDocPtr) {
IGridViewPtr ipGridPtr = ipDocPtr->GridView;
if(ipGridPtr) {
IXMLDataPtr ipXMLData = ipGridPtr->CurrentFocus;
CString strValue = W2T(ipXMLData->TextValue);
if(!strValue.IsEmpty() && (strValue.Left(7) == _T("http://")))
::ShellExecute(NULL,_T("open"),W2T(ipXMLData->TextValue),NULL,NULL,SW_SHOWNORMAL);
}
}
}
}
}
return S_OK;
}
HRESULT CXMLSpyIDEPlugIn::OnUpdateCommand(long nID, IDispatch* pXMLSpy, SPYUpdateAction* pAction)
{
*pAction = spyDisable;
if(nID == 1) {
IApplicationPtr ipSpyApp;
if(pXMLSpy) {
if(SUCCEEDED(pXMLSpy->QueryInterface(__uuidof(IApplication),(void **)&ipSpyApp))) {
IDocumentPtr ipDocPtr = ipSpyApp->ActiveDocument;
// only enable if grid view is active
if((ipDocPtr != NULL) && (ipDocPtr->CurrentViewMode == spyViewGrid))
*pAction = spyEnable;
}
}
}
return S_OK;
}
HRESULT CXMLSpyIDEPlugIn::OnEvent(long nEventID, SAFEARRAY **arrayParameters, IDispatch* pXMLSpy, VARIANT* pReturnValue)
{
return S_OK;
}
HRESULT CXMLSpyIDEPlugIn::GetUIModifications(BSTR* pModificationsXML)
{
CComBSTR bstrMods = _T(" \
<ConfigurationData> \
<Modifications> ");
// add "Open URL..." to Tools menu
bstrMods.Append (_T(" \
<Modification> \
<Action>Add</Action> \
<UIElement type=\"MenuItem\"> \
<ID>1</ID> \
<Name>Open URL...</Name> \
<Place>0</Place> \
<MenuID>129</MenuID> \
<Parent>:Tools</Parent> \
</UIElement> \
</Modification> "));
// add Seperator to Tools menu
bstrMods.Append (_T(" \
<Modification> \
<Action>Add</Action> \
<UIElement type=\"MenuItem\"> \
<ID>0</ID> \
<Place>1</Place> \
<MenuID>129</MenuID> \
<Parent>:Tools</Parent> \
</UIElement> \
</Modification> "));
// finish modification description
bstrMods.Append (_T(" \
</Modifications> \
</ConfigurationData>"));
return bstrMods.CopyTo(pModificationsXML);
}
HRESULT CXMLSpyIDEPlugIn::GetDescription(BSTR* pDescription)
{
CComBSTR bstrDescr = _T("ATL C++ XMLSpy IDE PlugIn;This PlugIn demonstrates the implementation of a simple ATL DLL as a IDE PlugIn for XMLSpy.");
return bstrDescr.CopyTo(pDescription);
}