
VSPackage: sapere se siete in “debug mode” o “design mode”
funziona a singhiozzo…this.dte.Events.DTEEvents.ModeChanged += .... this.dte.Events.DebuggerEvents.OnEnterDesignMode += ... this.dte.Events.DebuggerEvents.OnEnterRunMode += ...

Funziona, ma è comunque la strada sbagliata. La documentazione dice chiaro e tondo che tutti quegli eventi sono ad uso interno (punto).var events = this.dte.Events; if( events != null ) { this.dteEvents = events.DTEEvents; if( this.dteEvents != null ) { this.dteEvents.ModeChanged += new _dispDTEEvents_ModeChangedEventHandler( OnDTEModeChanged ); } }
Quindi?
Non è proprio così immediato seguire la strada ufficiale ma si può fare, in primis recuperiamo una reference a un servizio che si chiama IVsMonitorSelection:
Fatto questo possiamo chiedere al servizio di essere notificati quando succede qualcosa all’interno dell’IDE, nello specifico ci interessa sapere quando cambia lo UI Context, purtroppo non è così semplice come agganciare un event handler; la prima cosa che dobbiamo fare è implementare da qualche parte (tipicamente dove abbiamo bisogno di ricevere la notifica) l'interfaccia IVsSelectionEvents:var monitorSelectionService = this.GetService( typeof( IVsMonitorSelection ) ) as IVsMonitorSelection;
L’interfaccia prevede che vengano implementati 3 metodi:public class MyToolWindowViewModel : ..., IVsSelectionEvents { }
A noi interessa solo il primo, quindi gli altri due li lasciamo con la semplice “return OK”.int IVsSelectionEvents.OnCmdUIContextChanged( uint dwCmdUICookie, int fActive ) { return VSConstants.S_OK; } int IVsSelectionEvents.OnElementValueChanged( uint elementid, object varValueOld, object varValueNew ) { return VSConstants.S_OK; } int IVsSelectionEvents.OnSelectionChanged( IVsHierarchy pHierOld, uint itemidOld, IVsMultiItemSelect pMISOld, ISelectionContainer pSCOld, IVsHierarchy pHierNew, uint itemidNew, IVsMultiItemSelect pMISNew, ISelectionContainer pSCNew ) { return VSConstants.S_OK; }
OnCmdUIContextChanged viene chiamato una quantità spaventosa di volte praticamente per ogni minima variazione di contesto all’interno dell’IDE, è potentissimo perché vi permette di sapere pressoché tutto quello che succede, è altrettanto scomodissimo sapere che cosa succede:
Brutto…uint debuggerCookie; var debugging_guid = VSConstants.UICONTEXT.Debugging_guid; ErrorHandler.ThrowOnFailure( this.monitorSelectionService.GetCmdUIContextCookie( ref debugging_guid, out debuggerCookie ) ); if( debuggerCookie == dwCmdUICookie ) { this.OnDTEModeChanged(); }

- per ogni variazione di stato l’IDE ci chiama passandoci:
- un “cookie” che possiamo considerare come un “token” che identifica la cosa che è cambiata;
- il nuovo stato: attivo (1), disattivo (0);
- Recuperiamo un riferimento al GUID che rappresenta lo “UI Context” che interessa a noi, nel nostro caso Debugging;
- Passiamo il GUID in questione a GetCmdUIContextCookie e otteniamo in cambio il cookie/token che rappresenta quel contesto;
- Se il cookie coincide con quello che ci viene passato significa che il contesto che è cambiato è quello che interessa a noi;
Semplice no?void OnDTEModeChanged() { switch( this.dte.Mode ) { case vsIDEMode.vsIDEModeDebug: { //Siamo in debug mode } break; case vsIDEMode.vsIDEModeDesign: { //Siamo in design mode } break; } }
.m