Attivazione senza finestra
Il codice di creazione della finestra( ovvero tutto ciò che accade quando si chiama CreateWindow
) è costoso da eseguire. Un controllo che gestisce una finestra sullo schermo deve gestire i messaggi per la finestra. I controlli privi di finestra sono quindi più veloci dei controlli con finestre.
Un ulteriore vantaggio offerto dai controlli privi di finestra è che, a differenza di quelli con finestre, supportano il disegno trasparente e le aree non rettangolari dello schermo. Un esempio comune di un controllo trasparente è un controllo di testo con uno sfondo trasparente. I controlli disegnano il testo ma non lo sfondo, pertanto tutto ciò che si trova sotto il testo è visibile. I nuovi form utilizzano spesso controlli non rettangolari, quali le frecce e i pulsanti rotondi.
Spesso, un controllo non necessita di una finestra propria e, invece, può utilizzare i servizi di finestra del contenitore a cui appartiene, purché il contenitore sia stato scritto per supportare oggetti senza finestra. I controlli privi di finestra sono compatibili con le versioni precedenti di contenitori. Nei contenitori meno recenti non scritti per supportare i controlli privi di finestra, i controlli privi di finestra creano una finestra quando attivi.
Poiché i controlli privi di finestra non dispongono di finestre proprie, il contenitore (che dispone di una finestra) è responsabile di fornire servizi che sarebbero altrimenti forniti dalla finestra propria del controllo. Ad esempio, se il controllo deve eseguire una query sullo stato attivo della tastiera, acquisire il mouse o ottenere un contesto di dispositivo, queste operazioni vengono gestite dal contenitore. Il contenitore indirizza i messaggi di input dell'utente inviati alla finestra al controllo senza finestra appropriato tramite l'interfaccia IOleInPlaceObjectWindowless
. (Vedere il ActiveX SDK per una descrizione di questa interfaccia. COleControl
le funzioni membro richiamano questi servizi dal contenitore.
Per fare in modo che il controllo usi l'attivazione senza finestra, includere il flag windowlessActivate nel set di flag restituiti da COleControl::GetControlFlags. Ad esempio:
DWORD CMyAxOptCtrl::GetControlFlags()
{
DWORD dwFlags = COleControl::GetControlFlags();
// The control can activate without creating a window.
dwFlags |= windowlessActivate;
return dwFlags;
}
Il codice da includere questo flag viene generato automaticamente se si seleziona l'opzione Attivazione senza finestra nella pagina Controllo Impostazioni della Creazione guidata controllo ActiveX MFC.
Se l'attivazione senza finestra è abilitata, il contenitore delegherà i messaggi di input all'interfaccia IOleInPlaceObjectWindowless
del controllo. L'implementazione di COleControl
di questa interfaccia invia i messaggi attraverso la mappa messaggi del controllo, dopo avere modificato le coordinate del mouse in modo appropriato. È possibile elaborare i messaggi come comuni messaggi di finestra, aggiungendo le voci corrispondenti alla mappa messaggi. Nei gestori di questi messaggi evitare di usare la variabile membro m_hWnd (o qualsiasi funzione membro che la usa) senza prima verificare che il relativo valore non sia NULL.
COleControl
fornisce funzioni membro che richiamano la cattura del mouse, lo stato attivo della tastiera e altri servizi della finestra dal contenitore in base alle esigenze, tra cui:
Nei controlli privi di finestra è sempre opportuno utilizzare le funzioni membro COleControl
anziché le funzioni membro CWnd
corrispondenti o le funzioni API Win32 correlate.
È possibile impostare un controllo senza finestra in modo che funga da destinazione di un'operazione di trascinamento della selezione OLE. In genere, ciò richiede che la finestra del controllo sia stata registrata come obiettivo di rilascio. Poiché il controllo non ha una finestra propria, il contenitore utilizza la propria finestra come destinazione di trascinamento. Il controllo fornisce un'implementazione dell'interfaccia IDropTarget
a cui il contenitore può delegare le chiamate al momento giusto. Per esporre questa interfaccia al contenitore, eseguire l'override di COleControl::GetWindowlessDropTarget. Ad esempio:
IDropTarget* CMyAxOptCtrl::GetWindowlessDropTarget()
{
m_DropTarget.m_xDropTarget.AddRef();
return &m_DropTarget.m_xDropTarget;
}