Condividi tramite


Degrading Gracefully in assenza di un'interfaccia

Poiché un controllo potrebbe non supportare alcuna interfaccia diversa da IUnknown, un contenitore deve degradarsi normalmente quando rileva l'assenza di una particolare interfaccia.

Si potrebbe mettere in dubbio l'utilità di un controllo con niente di più di IUnknown. Considerare tuttavia i vantaggi che un controllo riceve dall'ambiente di programmazione visuale di un contenitore (ad esempio VB) quando il contenitore riconosce l'oggetto come controllo:

  • Un pulsante per l'oggetto viene visualizzato in una casella degli strumenti.
  • È possibile creare un oggetto trascinandolo dalla casella degli strumenti in un form.
  • È possibile assegnare all'oggetto un nome riconosciuto nell'ambiente di programmazione visiva.
  • Lo stesso nome in (3) precedente può essere usato immediatamente nella scrittura di qualsiasi altro codice per i controlli nella stessa maschera (o anche in un modulo diverso).
  • Il contenitore può fornire automaticamente punti di ingresso del codice per tutti gli eventi disponibili da tale oggetto.
  • Il contenitore fornisce la propria interfaccia utente di esplorazione delle proprietà per le proprietà disponibili.

Quando un oggetto non viene riconosciuto come controllo, perde potenzialmente tutte queste funzionalità di integrazione molto potenti e vantaggiose. Ad esempio, in Visual Basic 4.0 è molto difficile integrare effettivamente un oggetto casuale che non è un controllo nel senso completo, ma potrebbe comunque avere proprietà ed eventi. Poiché l'idea di visual Basic 4 di un controllo è molto restrittiva, l'oggetto non ottiene alcuna funzionalità di integrazione precedente. Ma anche un controllo con IUnknown, in cui la semplice durata del controllo determina l'esistenza di alcune risorse, dovrebbe essere in grado di ottenere le funzionalità di integrazione descritte in precedenza.

Poiché gli strumenti correnti richiedono un ampio set di interfacce di controllo per ottenere qualsiasi vantaggio, i controlli vengono in genere portati all'over-implementazione, in modo che contengano più codice di quanto effettivamente necessario. I controlli che potrebbero essere 7.000 potrebbero essere 25.000, un problema di prestazioni notevole in aree come Internet. Questo ha anche portato alla percezione che uno può implementare un solo controllo con uno strumento come la chiave CDK a causa della complessità dell'implementazione di tutte le interfacce, e questo ha implicazioni quando una DLL di grandi dimensioni come OC30.DLL è necessaria per un controllo di questo tipo, aumentando il working set. Se non sono necessarie tutte le interfacce, questo consente a molti sviluppatori di scrivere controlli molto piccoli e leggeri con OLE dritto o con altri strumenti, riducendo al minimo l'overhead per ogni controllo.

Questo è il motivo per cui questa appendice riconosce un controllo come qualsiasi oggetto con un CLSID e un'interfaccia IUnknown . Anche con niente di più di IUnknown, un contenitore con un ambiente di programmazione deve essere in grado di fornire almeno le funzionalità #3 e ) voce del Registro di sistema, ottiene #1 e #2. Se l'oggetto fornisce I Connessione ionPointContainer (e IProvideClassInfo in genere) per alcuni set di eventi, ottiene #5 e, se supporta IDispatch per proprietà e metodi, ottiene #6, nonché una migliore integrazione del codice nel contenitore.

In breve, un oggetto deve essere in grado di implementare solo IDispatch e un set di eventi esposto tramite I Connessione ionPointContainer per ottenere tutte le funzionalità visive precedenti.

Tenendo presente questo aspetto, la tabella seguente descrive le operazioni che un contenitore potrebbe eseguire in assenza di qualsiasi interfaccia possibile. Si noti che sono elencate solo le interfacce che il contenitore otterrà direttamente tramite QueryInterface. Altre interfacce, ad esempio IOleInPlaceActiveObject, vengono ottenute tramite altri mezzi.

Interfaccia Significato dell'assenza di interfaccia
IViewObject2
Il controllo non dispone di oggetti visivi da disegnare, pertanto non dispone di extent definito da fornire. In fase di esecuzione, il contenitore non tenta semplicemente di disegnare nulla quando questa interfaccia è assente. In fase di progettazione, il contenitore deve disegnare almeno un tipo di rettangolo predefinito con un nome in esso contenuto per tale controllo, in modo che un utente in un ambiente di programmazione visiva possa selezionare l'oggetto ed estrarre le relative proprietà, metodi ed eventi esistenti. La gestione dell'assenza di IViewObject2 è fondamentale per un buon supporto per la programmazione visiva.
Ioleobject
Il controllo non richiede alcun tipo di sito, né partecipa a alcuna negoziazione del layout di oggetti incorporato. Tutte le informazioni ,ad esempio gli extent di controllo, che un contenitore potrebbe aspettarsi da questa interfaccia devono essere compilate con le impostazioni predefinite fornite dal contenitore.
IOleInPlaceObject
Il controllo non passa sul posto (ad esempio un'etichetta) e quindi non tenta mai di attivarsi in questo modo. L'unica attivazione può essere la relativa pagina delle proprietà.
IOleControl
Il controllo non ha mnemonic e non usa proprietà di ambiente e non importa se il contenitore ignora gli eventi. In assenza di questa interfaccia, il contenitore non chiama solo i relativi metodi.
Idataobject
Il controllo non fornisce alcun set di proprietà né alcun rendering visivo che potrebbe essere memorizzato nella cache, pertanto il contenitore sceglierebbe di memorizzare nella cache una presentazione predefinita in assenza di questa interfaccia (supporto per CF_METAFILEPICT, in particolare) e disabilitare qualsiasi funzionalità correlata al set di proprietà.
IDispatch
Il controllo non dispone di proprietà o metodi personalizzati. Il contenitore non deve provare a visualizzare le proprietà del controllo in questo caso e non deve consentire le chiamate di metodo personalizzate che il contenitore non riconosce come appartenente ai propri controlli estesi (che possono supportare metodi e proprietà). Poiché i controlli estesi delegano in genere determinate chiamate IDispatch al controllo, un controllo esteso non dovrebbe aspettarsi che il controllo disponga di IDispatch .
I Connessione ionPointContainer
Il controllo non ha eventi, quindi il contenitore non deve pensare alla gestione di alcun evento.
IProvideClassInfo
IProvideClassInfo2
Il controllo non dispone di informazioni sul tipo o eventi oppure il contenitore deve accedere alle informazioni sul tipo del controllo tramite le voci del Registro di sistema del controllo. L'esistenza di questa interfaccia è un'ottimizzazione.
ISpecifyPropertyPages
Il controllo non dispone di pagine delle proprietà, quindi se il contenitore include un'interfaccia utente che li richiama, il contenitore deve disabilitare l'interfaccia utente.
IPerPropertyBrowsing
Il controllo non ha alcun nome visualizzato, nessuna stringa e valori predeterminati e nessuna proprietà per il mapping delle pagine. Questa interfaccia viene quasi sempre usata per generare l'interfaccia utente del contenitore, pertanto tali elementi dell'interfaccia utente verranno disabilitati in assenza di questa interfaccia.
IPersist *
Il controllo non ha uno stato permanente di cui parlare, quindi il contenitore non deve preoccuparsi di salvare dati specifici del controllo. Il contenitore salverà naturalmente le proprie informazioni sul controllo nel proprio modulo o documento, ma il controllo stesso non ha nulla da contribuire a tali informazioni.
IOleCache
IOleCache2
L'oggetto non supporta la memorizzazione nella cache. Un contenitore può comunque supportare la memorizzazione nella cache creando semplicemente una cache dei dati usando CreateDataCache.

Contenitori