TN040: ridimensionamento sul posto e zoom MFC/OLE
Nota
La seguente nota tecnica non è stata aggiornata da quando è stata inclusa per la prima volta nella documentazione online. Di conseguenza, alcune procedure e argomenti potrebbero essere non aggiornati o errati. Per le informazioni più recenti, è consigliabile cercare l'argomento di interesse nell'indice della documentazione online.
Questa nota illustra i problemi relativi alla modifica sul posto e al modo in cui un server deve eseguire correttamente lo zoom e il ridimensionamento sul posto. Con l'attivazione sul posto, il concetto WYSIWYG viene eseguito un ulteriore passo avanti nel fatto che i contenitori e i server collaborano tra loro e in particolare interpretano la specifica OLE nello stesso modo.
A causa dell'interazione ravvicinata tra un contenitore e un server che supporta l'attivazione sul posto, l'utente finale deve mantenere una serie di aspettative:
La visualizzazione della presentazione (il metafile disegnato nell'override
COleServerItem::OnDraw
) dovrebbe essere esattamente uguale a quando viene disegnata per la modifica (ad eccezione del fatto che gli strumenti di modifica non sono visibili).Quando il contenitore esegue lo zoom, anche la finestra del server dovrebbe essere completata.
Sia il contenitore che il server devono visualizzare gli oggetti per la modifica usando le stesse metriche. Questo significa usare una modalità di mapping basata sul numero di pixel logici per pollice, non sui pixel fisici per pollice, durante il rendering nel dispositivo di visualizzazione.
Nota
Poiché l'attivazione sul posto si applica solo agli elementi incorporati (non collegati), lo zoom si applica solo agli oggetti incorporati. Verranno visualizzate le API in e COleServerDoc
COleServerItem
usate per lo zoom. Il motivo di questa dicotomia è che solo le funzioni valide per gli elementi collegati e incorporati si trovano in COleServerItem
(ciò consente di avere un'implementazione comune) e le funzioni valide solo per gli oggetti incorporati si trovano nella COleServerDoc
classe (dal punto di vista del server, è il documento incorporato).
La maggior parte del carico è posta sull'implementatore del server, in quanto il server deve essere a conoscenza del fattore di zoom del contenitore e modificare l'interfaccia di modifica in base alle esigenze. Ma come fa il server a determinare il fattore di zoom usato dal contenitore
Supporto MFC per lo zoom
Il fattore di zoom corrente può essere determinato chiamando COleServerDoc::GetZoomFactor
. La chiamata a questa operazione quando il documento non è attivo sul posto comporterà sempre un fattore di zoom del 100% (o un rapporto di 1:1). Chiamandolo mentre attivo sul posto può restituire qualcosa di diverso dal 100%.
Per un esempio di zoom corretto, vedere l'esempio OLE MFC HIERSVR. Lo zoom in HIERSVR è complicato dal fatto che visualizza testo e testo, in generale, non si ridimensiona in modo lineare (hint, convenzioni tipografiche, larghezze di progettazione e altezze complicano la questione). Comunque, HIERSVR è un riferimento ragionevole per implementare correttamente lo zoom, quindi è l'esercitazione MFC SCRIBBLE (passaggio 7).
COleServerDoc::GetZoomFactor
determina il fattore di zoom basato su una serie di metriche diverse disponibili dal contenitore o dall'implementazione delle COleServerItem
classi e COleServerDoc
. In breve, il fattore di zoom corrente è determinato dalla formula seguente:
Position Rectangle (PR) / Container Extent (CE)
Il rettangolo POSITION è determinato dal contenitore. Viene restituito al server durante l'attivazione sul posto quando COleClientItem::OnGetItemPosition
viene chiamato e viene aggiornato quando il contenitore chiama il server COleServerDoc::OnSetItemRects
(con una chiamata a COleClientItem::SetItemRects
).
L'EXTENT CONTENITORE è leggermente più complesso da calcolare. Se il contenitore ha chiamato COleServerItem::OnSetExtent
(con una chiamata a COleClientItem::SetExtent
), l'EXTENT CONTENITORE è questo valore convertito in pixel in base al numero di pixel per pollice logico. Se il contenitore non ha chiamato SetExtent (che in genere è il caso), l'EXTENT CONTENITORE corrisponde alla dimensione restituita da COleServerItem::OnGetExtent
. Pertanto, se il contenitore non ha chiamato SetExtent, il framework presuppone che se il contenitore lo avesse chiamato con il 100% dell'extent naturale (il valore restituito da COleServerItem::GetExtent
). Dichiarato in un altro modo, il framework presuppone che il contenitore visualizzi il 100% (non più, non meno) dell'elemento.
È importante notare che anche se COleServerItem::OnSetExtent
e COleServerItem::OnGetExtent
hanno nomi simili, non modificano lo stesso attributo dell'elemento. OnSetExtent
viene chiamato per informare il server della quantità di oggetto visibile nel contenitore (indipendentemente dal fattore di zoom) e OnGetExtent
viene chiamato dal contenitore per determinare le dimensioni ideali dell'oggetto.
Esaminando ognuna delle API coinvolte, è possibile ottenere un'immagine più chiara:
COleServerItem::OnGetExtent
Questa funzione deve restituire le "dimensioni naturali" nelle unità HIMETRIC dell'elemento. Il modo migliore per considerare le "dimensioni naturali" è definirlo come le dimensioni che potrebbe apparire quando viene stampato. La dimensione restituita qui è costante per un particolare contenuto dell'elemento (molto simile al metafile, che è costante per un determinato elemento). Questa dimensione non cambia quando viene applicato lo zoom all'elemento. In genere non cambia quando il contenitore assegna all'elemento più o meno spazio chiamando OnSetExtent
. Un esempio di modifica potrebbe essere quello di un semplice editor di testo senza funzionalità "margin" che ha eseguito il wrapping del testo in base all'ultimo extent inviato dal contenitore. Se un server cambia, il server dovrebbe probabilmente impostare il bit OLEMISC_RECOMPOedizione Standard ONRESIZE nel Registro di sistema (vedere la documentazione di OLE SDK per altre informazioni su questa opzione).
COleServerItem::OnSetExtent
Questa funzione viene chiamata quando il contenitore mostra "più o meno" dell'oggetto . La maggior parte dei contenitori non lo chiamerà affatto. L'implementazione predefinita archivia l'ultimo valore ricevuto dal contenitore in "m_sizeExtent", che viene usato in durante COleServerDoc::GetZoomFactor
il calcolo del valore EXTENT CONTENITORE descritto in precedenza.
COleServerDoc::OnSetItemRects
Questa funzione viene chiamata solo quando il documento è attivo sul posto. Viene chiamato quando il contenitore aggiorna la posizione dell'elemento o il ritaglio applicato all'elemento. Il RETTANGOLO DI POSIZIONE, come illustrato in precedenza, fornisce il numeratore per il calcolo del fattore di zoom. Un server può richiedere che la posizione dell'elemento venga modificata chiamando COleServerDoc::RequestPositionChange
. Il contenitore può rispondere o meno a questa richiesta chiamando OnSetItemRects
(con una chiamata a COleServerItem::SetItemRects
).
COleServerDoc::OnDraw
È importante tenere presente che il metafile creato eseguendo l'override di COleServerItem::OnDraw
produce esattamente lo stesso metafile, indipendentemente dal fattore di zoom corrente. Il contenitore ridimensiona il metafile in base alle esigenze. Si tratta di una distinzione importante tra la visualizzazione e OnDraw
l'elemento del OnDraw
server. La visualizzazione gestisce lo zoom, l'elemento crea solo un metafile zoomabile e lo lascia al contenitore per eseguire lo zoom appropriato.
Il modo migliore per assicurarsi che il server si comporti correttamente consiste nell'usare l'implementazione di COleServerDoc::GetZoomFactor
se il documento è attivo sul posto.
Supporto MFC per il ridimensionamento sul posto
MFC implementa completamente l'interfaccia di ridimensionamento sul posto come descritto nella specifica OLE 2. L'interfaccia utente è supportata dalla COleResizeBar
classe , da un messaggio personalizzato WM_SIZECHILD e dalla gestione speciale di questo messaggio in COleIPFrameWnd
.
È possibile implementare una gestione diversa di questo messaggio rispetto a quella fornita dal framework. Come descritto in precedenza, il framework lascia i risultati del ridimensionamento sul posto fino al contenitore, ovvero il server risponde alla modifica nel fattore di zoom. Se il contenitore reagisce impostando sia CONTAINER EXTENT che POSITION RECTANGLE durante l'elaborazione del relativo COleClientItem::OnChangeItemPosition
(chiamato come risultato di una chiamata a COleServerDoc::RequestPositionChange
), il ridimensionamento sul posto comporterà la visualizzazione di "più o meno" dell'elemento nella finestra di modifica. Se il contenitore reagisce impostando semplicemente POSITION RECTANGLE durante l'elaborazione di , il fattore di COleClientItem::OnChangeItemPosition
zoom cambierà e l'elemento verrà visualizzato "zoom avanti o indietro".
Un server può controllare (in qualche modo) cosa accade durante questa negoziazione. Un foglio di calcolo, ad esempio, potrebbe scegliere di visualizzare più o meno celle quando l'utente ridimensiona la finestra durante la modifica dell'elemento sul posto. Un elaboratore di testo potrebbe scegliere di modificare i "margini della pagina" in modo che corrispondano alla finestra e riscrivano il testo nel nuovo margine. I server implementano questa impostazione modificando l'extent naturale (le dimensioni restituite da COleServerItem::OnGetExtent
) al termine del ridimensionamento. In questo modo, sia POSITION RECTANGLE che CONTAINER EXTENT cambiano in base alla stessa quantità, determinando lo stesso fattore di zoom, ma un'area di visualizzazione più grande o più piccola. Inoltre, più o meno del documento saranno visibili nel metafile generato da OnDraw
. In questo caso, il documento stesso cambia quando l'utente ridimensiona l'elemento, anziché solo l'area di visualizzazione.
È possibile implementare il ridimensionamento personalizzato e sfruttare comunque l'interfaccia utente fornita COleResizeBar
eseguendo l'override del messaggio di WM_SIZECHILD nella COleIPFrameWnd
classe. Per altre informazioni sulle specifiche di WM_SIZECHILD, vedere La nota tecnica 24.