2009-05-06 15 views
16

Ho intenzione di rispondere alla mia domanda qui perché ho trascorso alcune ore a mettere insieme questo pezzo e ho voluto condividere ciò che ho trovato nella speranza che salvassi qualcun altro dallo scavare.Come posso ospitare il contenuto WPF nelle applicazioni MFC?

C'è uno MSDN Walkthrough che ti porta quasi tutto lì, ma ci sono un paio di pezzi chiave che ho trovato altrove. Ad esempio, la procedura dettagliata ti dice di posizionare la linea [System :: STAThreadAttribute] prima della definizione _tWinMain() ma se stai implementando un'applicazione MFC standard non hai _tWinMain() nel tuo codice sorgente.

Se qualcosa non è chiaro, non esitate a fare domande e modificheremo la risposta per rendere le cose più chiare.

risposta

22

Fase 1: Configurare l'applicazione MFC per compilare con il supporto CLR

Il modo migliore per raggiungere l'interoperabilità tra nativo C++ e il codice .NET gestito è quello di compilare l'applicazione come gestita C++ piuttosto che C++ nativo. Questo viene fatto andando alle Proprietà di configurazione del progetto. Sotto Generale esiste un'opzione "Supporto Common Language Runtime". Impostare su "Common Language Runtime Support/clr".

Fase 2: Aggiungi gli assembly WPF al progetto

fare clic destro sul progetto in Solution Explorer e scegliere "Riferimenti". Fai clic su "Aggiungi nuovo riferimento". Nella scheda .NET, aggiungi WindowsBase, PresentationCore, PresentationFramework e System. Assicurati di ricostruire Tutto dopo aver aggiunto dei riferimenti per poterli raccogliere.

Passo 3: Impostare STAThreadAttribute sull'applicazione MFC

WPF richiede che STAThreadAttribute essere impostato sul thread principale dell'interfaccia utente. Impostalo andando su Proprietà di configurazione del progetto. Sotto Linker-> Advanced c'è un'opzione chiamata "Attributo Thread CLR". Impostalo su "Attributo di thread STA".

Fase 4: Creare un'istanza HwndSource per avvolgere la componente WPF

System :: di Windows :: :: Interop HwndSource è una classe .NET che gestisce l'interazione tra i componenti MFC e .NET. Creare uno che utilizza la seguente sintassi:

System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew  System::Windows::Interop::HwndSourceParameters("MyWindowName"); 
sourceParams->PositionX = x; 
sourceParams->PositionY = y; 
sourceParams->ParentWindow = System::IntPtr(hWndParent); 
sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD; 

System::Windows::Interop::HwndSource^ source = gcnew System::Windows::Interop::HwndSource(*sourceParams); 
source->SizeToContent = System::Windows::SizeToContent::WidthAndHeight; 

Aggiungere una variabile membro HWND alla classe finestra di dialogo e quindi assegnare in questo modo: m_hWnd = (HWND) source-> Handle.ToPointer();

L'oggetto di origine e il contenuto WPF associato rimarrà in esistenza finché non si chiama :: DestroyWindow (m_hWnd).

Fase 5: Aggiungere il controllo WPF per l'involucro HwndSource

System::Windows::Controls::WebBrowser^ browser = gcnew System::Windows::Controls::WebBrowser(); 

browser->Height = height; 
browser->Width = width; 
source->RootVisual = browser; 

Passo 6: Tenere un riferimento all'oggetto WPF

Poiché la variabile del browser andrà fuori portata dopo usciamo dalla funzione facendo la creazione, dobbiamo in qualche modo mantenere un riferimento ad essa.Gli oggetti gestiti non possono essere membri di oggetti non gestiti, ma puoi utilizzare un modello di wrapper chiamato gcroot per portare a termine il lavoro.

Aggiungere una variabile membro alla classe finestra di dialogo:

#include <vcclr.h> 
gcroot<System::Windows::Controls::WebBrowser^> m_webBrowser; 

quindi aggiungere la seguente riga al codice nel passaggio 5:

m_webBrowser = browser; 

Ora possiamo accedere a proprietà e metodi sul componente WPF attraverso m_webBrowser.

+0

molto bello. grazie per la pubblicazione – Gishu

+1

source-> SizeToContent = System :: Windows :: SizeToContent :: WidthAndHeight; Questo era quello che mi mancava! +1 –

+2

Un'ulteriore informazione, se non si imposta lo StaThreadModel, si romperà in modo misteriosamente profondo all'interno di MFC. Ed è necessario impostare il modello di thread sull'app eseguibile principale. Se tu, come me, avevi la finestra di dialogo che vuoi sostituire in un'altra DLL, non ** ti aiuterà se imposti l'attributo thread CLR sulla DLL non ancora eseguita. Potrebbe essere ovvio per gli altri, ma non era per me. – Dervall

Problemi correlati