Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Windows Presentation Foundation (WPF) bietet eine umfangreiche Umgebung zum Erstellen von Anwendungen. Wenn Sie jedoch eine erhebliche Investition in Win32-Code haben, ist es möglicherweise effektiver, Ihrer Anwendung WPF-Funktionen hinzuzufügen, anstatt den ursprünglichen Code neu zu schreiben. WPF bietet einen einfachen Mechanismus zum Hosten von WPF-Inhalten in einem Win32-Fenster.
In diesem Lernprogramm wird beschrieben, wie Sie eine Beispielanwendung schreiben, WPF-Inhalt in einem Win32-Fensterbeispiel hosten, das WPF-Inhalte in einem Win32-Fenster hostet. Sie können dieses Beispiel erweitern, um ein beliebiges Win32-Fenster zu hosten. Da die Anwendung verwalteten und nicht verwalteten Code mischen muss, wird die Anwendung in C++/CLI geschrieben.
Anforderungen
In diesem Lernprogramm wird eine grundlegende Vertrautheit mit der Programmierung von WPF und Win32 vorausgesetzt. Eine grundlegende Einführung in die WPF-Programmierung finden Sie unter "Erste Schritte". Für eine Einführung in die Win32-Programmierung sollten Sie auf eines der zahlreichen Bücher zum Thema verweisen, insbesondere auf die Programmierung von Windows von Charles Petzold.
Da das Beispiel, das dieses Lernprogramm begleitet, in C++/CLI implementiert wird, wird in diesem Lernprogramm davon ausgegangen, dass sie mit der Verwendung von C++ vertraut sind, um die Windows-API zu programmieren, sowie ein Verständnis der Programmierung von verwaltetem Code. Vertrautheit mit C++/CLI ist hilfreich, aber nicht unbedingt erforderlich.
Hinweis
Dieses Lernprogramm enthält eine Reihe von Codebeispielen aus dem zugehörigen Beispiel. Aus Gründen der Lesbarkeit enthält sie jedoch nicht den vollständigen Beispielcode. Den vollständigen Beispielcode finden Sie unter Hosten von WPF-Inhalten in einem Win32-Fensterbeispiel.
Grundlegendes Verfahren
In diesem Abschnitt wird das grundlegende Verfahren beschrieben, das Sie zum Hosten von WPF-Inhalten in einem Win32-Fenster verwenden. In den verbleibenden Abschnitten werden die Details der einzelnen Schritte erläutert.
Der Schlüssel zum Hosten von WPF-Inhalten in einem Win32-Fenster ist die HwndSource Klasse. Diese Klasse umschließt den WPF-Inhalt in einem Win32-Fenster, sodass er als untergeordnetes Fenster in die Benutzeroberfläche (UI) integriert werden kann. Der folgende Ansatz kombiniert win32 und WPF in einer einzigen Anwendung.
Implementieren Sie Ihre WPF-Inhalte als verwaltete Klasse.
Implementieren Sie eine Windows-Anwendung mit C++/CLI. Wenn Sie mit einem vorhandenen Anwendungs- und nicht verwalteten C++-Code beginnen, können Sie es in der Regel aktivieren, um verwalteten Code aufzurufen, indem Sie Die Projekteinstellungen so ändern, dass es das
/clr
Compilerflagge enthält.Legen Sie das Threading-Modell auf Single-Threaded Apartment (STA) fest.
Behandeln Sie die WM_CREATE-Benachrichtigungin Ihrem Fensterverfahren, und gehen Sie wie folgt vor:
Erstellen Sie ein neues HwndSource Objekt mit dem übergeordneten Fenster als
parent
Parameter.Erstellen Sie eine Instanz Ihrer WPF-Inhaltsklasse.
Weisen Sie der Eigenschaft der WPF-Inhaltsobjekt einen Verweis auf das RootVisualHwndSourceWPF-Inhaltsobjekt zu.
Rufen Sie den HWND für den Inhalt ab. Die Handle Eigenschaft des HwndSource Objekts enthält das Fensterhandle (HWND). Um einen HWND zu erhalten, den Sie im nicht verwalteten Teil Ihrer Anwendung verwenden können, wandeln Sie
Handle.ToPointer()
in ein HWND um.
Implementieren Sie eine verwaltete Klasse, die ein statisches Feld enthält, um einen Verweis auf Den WPF-Inhalt zu speichern. Mit dieser Klasse können Sie einen Verweis auf den WPF-Inhalt aus dem Win32-Code erhalten.
Weisen Sie den WPF-Inhalt dem statischen Feld zu.
Benachrichtigungen vom WPF-Inhalt erhalten, indem Sie einen Handler an eines oder mehrere WPF-Ereignisse anhängen.
Kommunizieren Sie mit dem WPF-Inhalt mithilfe des Verweises, den Sie im statischen Feld gespeichert haben, um Eigenschaften festzulegen usw.
Hinweis
Sie können auch WPF-Inhalte verwenden. Sie müssen sie jedoch separat als Dynamic Link Library (DLL) kompilieren und von Ihrer Win32-Anwendung aus auf diese DLL verweisen. Der Rest des Verfahrens ähnelt dem oben beschriebenen Verfahren.
Implementieren der Hostanwendung
In diesem Abschnitt wird beschrieben, wie WPF-Inhalte in einer einfachen Win32-Anwendung gehostet werden. Der Inhalt selbst wird in C++/CLI als verwaltete Klasse implementiert. In den meisten Fällen ist die WPF-Programmierung einfach. Die wichtigsten Aspekte der Inhaltsimplementierung werden in der Implementierung des WPF-Inhalts erläutert.
Die Standardanwendung
Der Ausgangspunkt für die Hostanwendung war das Erstellen einer Visual Studio 2005-Vorlage.
Öffnen Sie Visual Studio 2005, und wählen Sie im Menü "Datei" die Option "Neues Projekt" aus.
Wählen Sie Win32 aus der Liste der Visual C++-Projekttypen aus. Wenn Ihre Standardsprache nicht C++ ist, finden Sie diese Projekttypen unter "Andere Sprachen".
Wählen Sie eine Win32-Projektvorlage aus, weisen Sie dem Projekt einen Namen zu, und klicken Sie auf "OK ", um den Win32-Anwendungs-Assistenten zu starten.
Übernehmen Sie die Standardeinstellungen des Assistenten, und klicken Sie auf "Fertig stellen ", um das Projekt zu starten.
Die Vorlage erstellt eine einfache Win32-Anwendung, einschließlich:
Ein Einstiegspunkt für die Anwendung.
Ein Fenster mit einer zugeordneten Fensterprozedur (WndProc).
Ein Menü mit Den Überschriften "Datei" und "Hilfe ". Das Menü "Datei " verfügt über ein Exit-Element , das die Anwendung schließt. Das Hilfemenü enthält ein Element "Info ", das ein einfaches Dialogfeld startet.
Bevor Sie mit dem Schreiben von Code zum Hosten des WPF-Inhalts beginnen, müssen Sie zwei Änderungen an der Basisvorlage vornehmen.
Als Erstes wird das Projekt als verwalteter Code kompiliert. Standardmäßig wird das Projekt als nicht verwalteter Code kompiliert. Da WPF jedoch in verwaltetem Code implementiert ist, muss das Projekt entsprechend kompiliert werden.
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektnamen, und wählen Sie " Eigenschaften" im Kontextmenü aus, um das Dialogfeld "Eigenschaftenseiten " zu starten.
Wählen Sie "Konfigurationseigenschaften " in der Strukturansicht im linken Bereich aus.
Wählen Sie die Unterstützung für Common Language Runtime in der Liste " Project-Standardwerte " im rechten Bereich aus.
Wählen Sie im Dropdown-Listenfeld die Unterstützung für Common Language Runtime (/clr) aus.
Hinweis
Mit diesem Compilerflagge können Sie verwalteten Code in Ihrer Anwendung verwenden, der nicht verwaltete Code wird jedoch weiterhin wie zuvor kompiliert.
WPF verwendet das Single-Threaded Apartment (STA)-Threadingmodell. Um mit dem WPF-Inhaltscode ordnungsgemäß zu arbeiten, müssen Sie das Threadingmodell der Anwendung auf STA festlegen, indem Sie ein Attribut auf den Einstiegspunkt anwenden.
[System::STAThreadAttribute] //Needs to be an STA thread to play nicely with WPF
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
Hosten des WPF-Inhalts
Der WPF-Inhalt ist eine einfache Adresseintragsanwendung. Es besteht aus mehreren TextBox Steuerelementen, um Benutzernamen, Adresse usw. entgegenzunehmen. Es gibt auch zwei Button Steuerelemente, OK und Cancel. Wenn der Benutzer auf "OK" klickt, sammelt der Ereignishandler der Schaltfläche Click die Daten aus den TextBox Steuerelementen, weist sie den entsprechenden Eigenschaften zu und löst ein benutzerdefiniertes Ereignis OnButtonClicked
aus. Wenn der Benutzer auf Abbrechen klickt, löst der Handler einfach aus OnButtonClicked
. Das Ereignisargumentobjekt OnButtonClicked
enthält ein boolesches Feld, das angibt, auf welche Schaltfläche geklickt wurde.
Der Code zum Hosten des WPF-Inhalts wird in einem Handler für die WM_CREATE-Benachrichtigung im Hostfenster implementiert.
case WM_CREATE :
GetClientRect(hWnd, &rect);
wpfHwnd = GetHwnd(hWnd, rect.right-375, 0, 375, 250);
CreateDataDisplay(hWnd, 275, rect.right-375, 375);
CreateRadioButtons(hWnd);
break;
Die GetHwnd
-Methode akzeptiert Informationen zu Größe und Position sowie das übergeordnete Fenster-Handle und gibt das Fenster-Handle des gehosteten WPF-Inhalts zurück.
Hinweis
Sie können keine #using
Direktive für den System::Windows::Interop
Namespace verwenden. Dadurch wird ein Namenskonflikt zwischen der MSG Struktur in diesem Namespace und der in winuser.h deklarierten MSG-Struktur erstellt. Sie müssen stattdessen vollqualifizierte Namen verwenden, um auf den Inhalt dieses Namespaces zuzugreifen.
HWND GetHwnd(HWND parent, int x, int y, int width, int height)
{
System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew System::Windows::Interop::HwndSourceParameters(
"hi" // NAME
);
sourceParams->PositionX = x;
sourceParams->PositionY = y;
sourceParams->Height = height;
sourceParams->Width = width;
sourceParams->ParentWindow = IntPtr(parent);
sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD; // style
System::Windows::Interop::HwndSource^ source = gcnew System::Windows::Interop::HwndSource(*sourceParams);
WPFPage ^myPage = gcnew WPFPage(width, height);
//Assign a reference to the WPF page and a set of UI properties to a set of static properties in a class
//that is designed for that purpose.
WPFPageHost::hostedPage = myPage;
WPFPageHost::initBackBrush = myPage->Background;
WPFPageHost::initFontFamily = myPage->DefaultFontFamily;
WPFPageHost::initFontSize = myPage->DefaultFontSize;
WPFPageHost::initFontStyle = myPage->DefaultFontStyle;
WPFPageHost::initFontWeight = myPage->DefaultFontWeight;
WPFPageHost::initForeBrush = myPage->DefaultForeBrush;
myPage->OnButtonClicked += gcnew WPFPage::ButtonClickHandler(WPFButtonClicked);
source->RootVisual = myPage;
return (HWND) source->Handle.ToPointer();
}
Sie können den WPF-Inhalt nicht direkt in Ihrem Anwendungsfenster hosten. Stattdessen erstellen Sie zuerst ein HwndSource Objekt, um den WPF-Inhalt umzuschließen. Dieses Objekt ist im Grunde ein Fenster, das zum Hosten eines WPF-Inhalts konzipiert ist. Sie hosten das HwndSource Objekt im übergeordneten Fenster, indem Sie es als untergeordnetes Element eines Win32-Fensters erstellen, das Teil Ihrer Anwendung ist. Die HwndSource Konstruktorparameter enthalten viel die gleichen Informationen, die Sie beim Erstellen eines untergeordneten Win32-Fensters an CreateWindow übergeben würden.
Als Nächstes erstellen Sie eine Instanz des WPF-Inhaltsobjekts. In diesem Fall wird der WPF-Inhalt mithilfe von C++/CLI als separate Klasse WPFPage
implementiert. Sie können auch den WPF-Inhalt mit XAML implementieren. Dazu müssen Sie jedoch ein separates Projekt einrichten und den WPF-Inhalt als DLL erstellen. Sie können ihrem Projekt einen Verweis auf diese DLL hinzufügen und diesen Verweis verwenden, um eine Instanz des WPF-Inhalts zu erstellen.
Sie zeigen den WPF-Inhalt in Ihrem Kindfenster an, indem Sie der RootVisual-Eigenschaft einen Verweis auf den HwndSource WPF-Inhalt zuweisen.
Die nächste Codezeile fügt dem WPF-Inhaltsereignis WPFButtonClicked
einen Ereignishandler anOnButtonClicked
. Dieser Handler wird aufgerufen, wenn der Benutzer auf die Schaltfläche "OK " oder "Abbrechen " klickt. Weitere Informationen zu diesem Ereignishandler finden Sie im communicating_with_the_WPF-Inhalt.
Die letzte Codezeile gibt das Fensterhandle (HWND) zurück, das dem HwndSource Objekt zugeordnet ist. Sie können dieses Handle aus Ihrem Win32-Code verwenden, um Nachrichten an das gehostete Fenster zu senden, obwohl das Beispiel dies nicht tut. Das HwndSource Objekt löst jedes Mal ein Ereignis aus, wenn es eine Nachricht empfängt. Rufen Sie zum Verarbeiten der Nachrichten die AddHook Methode auf, um einen Nachrichtenhandler anzufügen, und verarbeiten Sie dann die Nachrichten in diesem Handler.
Halten eines Verweises auf den WPF-Content
Für viele Anwendungen möchten Sie später mit dem WPF-Inhalt kommunizieren. Sie können beispielsweise die WPF-Inhaltseigenschaften ändern oder den HwndSource Objekthost für unterschiedliche WPF-Inhalte verwenden. Dazu benötigen Sie einen Verweis auf das HwndSource Objekt oder den WPF-Inhalt. Das HwndSource Objekt und dessen zugeordneter WPF-Inhalt verbleiben im Arbeitsspeicher, bis Sie das Fensterhandle zerstören. Die Variable, die Sie dem HwndSource Objekt zuweisen, wird jedoch den Gültigkeitsbereich verlassen, sobald Sie von der Fensterprozedur zurückkehren. Die übliche Möglichkeit, dieses Problem mit Win32-Anwendungen zu behandeln, besteht darin, eine statische oder globale Variable zu verwenden. Leider können Sie diesen Variablentypen kein verwaltetes Objekt zuweisen. Sie können das dem HwndSource Objekt zugeordnete Fensterhandle einer globalen oder statischen Variablen zuweisen, die jedoch keinen Zugriff auf das Objekt selbst ermöglicht.
Die einfachste Lösung für dieses Problem besteht darin, eine verwaltete Klasse zu implementieren, die eine Reihe statischer Felder enthält, die Verweise auf alle verwalteten Objekte enthalten, auf die Sie zugreifen müssen. Im Beispiel wird die WPFPageHost
Klasse verwendet, um einen Verweis auf den WPF-Inhalt sowie die Anfangswerte einer Reihe seiner Eigenschaften zu speichern, die später vom Benutzer geändert werden können. Dies wird in der Kopfzeile definiert.
public ref class WPFPageHost
{
public:
WPFPageHost();
static WPFPage^ hostedPage;
//initial property settings
static System::Windows::Media::Brush^ initBackBrush;
static System::Windows::Media::Brush^ initForeBrush;
static System::Windows::Media::FontFamily^ initFontFamily;
static System::Windows::FontStyle initFontStyle;
static System::Windows::FontWeight initFontWeight;
static double initFontSize;
};
Der letzte Teil der GetHwnd
-Funktion weist diesen Feldern Werte für die spätere Verwendung zu, während myPage
noch im Geltungsbereich ist.
Kommunikation mit dem Inhalt von WPF
Es gibt zwei Arten der Kommunikation mit dem WPF-Inhalt. Die Anwendung empfängt Informationen vom WPF-Inhalt, wenn der Benutzer auf die Schaltflächen "OK " oder "Abbrechen " klickt. Die Anwendung verfügt auch über eine Benutzeroberfläche, mit der der Benutzer verschiedene WPF-Inhaltseigenschaften ändern kann, z. B. die Hintergrundfarbe oder den Standardschriftgrad.
Wie bereits erwähnt, löst der WPF-Inhalt ein OnButtonClicked
Ereignis aus, wenn der Benutzer auf eine der Schaltflächen klickt. Die Anwendung fügt einen Handler an dieses Ereignis an, um diese Benachrichtigungen zu empfangen. Wenn auf die Schaltfläche "OK " geklickt wurde, ruft der Handler die Benutzerinformationen aus dem WPF-Inhalt ab und zeigt sie in einer Reihe statischer Steuerelemente an.
void WPFButtonClicked(Object ^sender, MyPageEventArgs ^args)
{
if(args->IsOK) //display data if OK button was clicked
{
WPFPage ^myPage = WPFPageHost::hostedPage;
LPCWSTR userName = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("Name: " + myPage->EnteredName).ToPointer();
SetWindowText(nameLabel, userName);
LPCWSTR userAddress = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("Address: " + myPage->EnteredAddress).ToPointer();
SetWindowText(addressLabel, userAddress);
LPCWSTR userCity = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("City: " + myPage->EnteredCity).ToPointer();
SetWindowText(cityLabel, userCity);
LPCWSTR userState = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("State: " + myPage->EnteredState).ToPointer();
SetWindowText(stateLabel, userState);
LPCWSTR userZip = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("Zip: " + myPage->EnteredZip).ToPointer();
SetWindowText(zipLabel, userZip);
}
else
{
SetWindowText(nameLabel, L"Name: ");
SetWindowText(addressLabel, L"Address: ");
SetWindowText(cityLabel, L"City: ");
SetWindowText(stateLabel, L"State: ");
SetWindowText(zipLabel, L"Zip: ");
}
}
Der Handler empfängt ein benutzerdefiniertes Ereignisargumentobjekt aus dem WPF-Inhalt. MyPageEventArgs
Die Eigenschaft des Objekts IsOK
wird auf true
festgelegt, wenn auf die Schaltfläche "OK" geklickt wurde, oder auf false
, wenn auf die Schaltfläche "Abbrechen" geklickt wurde.
Wenn auf die Schaltfläche "OK " geklickt wurde, erhält der Handler einen Verweis auf den WPF-Inhalt aus der Containerklasse. Anschließend sammelt es die von den zugehörigen WPF-Inhaltseigenschaften gespeicherten Benutzerinformationen und verwendet statische Steuerelemente, um die Informationen im übergeordneten Fenster anzuzeigen. Da sich die WPF-Inhaltsdaten in Form einer verwalteten Zeichenfolge befinden, muss sie für die Verwendung durch ein Win32-Steuerelement gemarshallt werden. Wenn auf die Schaltfläche "Abbrechen " geklickt wurde, löscht der Handler die Daten aus den statischen Steuerelementen.
Die Anwendungsbenutzeroberfläche bietet eine Reihe von Optionsfeldern, mit denen der Benutzer die Hintergrundfarbe des WPF-Inhalts und mehrere schriftartbezogene Eigenschaften ändern kann. Das folgende Beispiel ist ein Auszug aus der Fensterprozedur der Anwendung (WndProc) und der zugehörigen Nachrichtenbehandlung, die verschiedene Eigenschaften für verschiedene Nachrichten festlegt, einschließlich der Hintergrundfarbe. Die anderen sind ähnlich und werden nicht angezeigt. Details und Kontext finden Sie im vollständigen Beispiel.
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
//Menu selections
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
//RadioButtons
case IDC_ORIGINALBACKGROUND :
WPFPageHost::hostedPage->Background = WPFPageHost::initBackBrush;
break;
case IDC_LIGHTGREENBACKGROUND :
WPFPageHost::hostedPage->Background = gcnew SolidColorBrush(Colors::LightGreen);
break;
case IDC_LIGHTSALMONBACKGROUND :
WPFPageHost::hostedPage->Background = gcnew SolidColorBrush(Colors::LightSalmon);
break;
Um die Hintergrundfarbe festzulegen, holen Sie sich einen Verweis auf den WPF-Inhalt (hostedPage
) von WPFPageHost
und legen Sie die Hintergrundfarbeigenschaft auf die entsprechende Farbe fest. Im Beispiel werden drei Farboptionen verwendet: die Originalfarbe, hellgrün oder der helle Lachs. Die ursprüngliche Hintergrundfarbe wird als statisches Feld in der WPFPageHost
Klasse gespeichert. Um die anderen beiden festzulegen, erstellen Sie ein neues SolidColorBrush Objekt und übergeben den Konstruktor einen statischen Farbwert aus dem Colors Objekt.
Implementieren der WPF-Seite
Sie können den WPF-Inhalt ohne Kenntnis der tatsächlichen Implementierung hosten und verwenden. Wenn der WPF-Inhalt in einer separaten DLL verpackt wurde, könnte er in einer beliebigen Sprache für die Common Language Runtime (CLR) erstellt worden sein. Nachfolgend finden Sie eine kurze exemplarische Vorgehensweise der C++/CLI-Implementierung, die im Beispiel verwendet wird. Dieser Abschnitt enthält die folgenden Unterabschnitte.
Gestaltung
Die UI-Elemente im WPF-Inhalt bestehen aus fünf TextBox Steuerelementen mit zugeordneten Label Steuerelementen: Name, Adresse, Ort, Bundesland und ZIP. Es gibt auch zwei Button Steuerelemente, OK und Cancel
Der WPF-Inhalt wird in der WPFPage
Klasse implementiert. Das Layout wird mit einem Grid Layoutelement behandelt. Die Klasse erbt von Grid, wodurch sie effektiv zum WPF-Inhaltsstammelement wird.
Der WPF-Inhaltskonstruktor verwendet die erforderliche Breite und Höhe und passt entsprechend an Grid . Anschließend wird das grundlegende Layout definiert, indem eine Gruppe von ColumnDefinition Objekten RowDefinition erstellt und der Grid Objektbasis ColumnDefinitions bzw RowDefinitions . Auflistungen hinzugefügt wird. Dadurch wird ein Raster mit fünf Zeilen und sieben Spalten definiert, wobei die Dimensionen durch den Inhalt der Zellen bestimmt werden.
WPFPage::WPFPage(int allottedWidth, int allotedHeight)
{
array<ColumnDefinition ^> ^ columnDef = gcnew array<ColumnDefinition ^> (4);
array<RowDefinition ^> ^ rowDef = gcnew array<RowDefinition ^> (6);
this->Height = allotedHeight;
this->Width = allottedWidth;
this->Background = gcnew SolidColorBrush(Colors::LightGray);
//Set up the Grid's row and column definitions
for(int i=0; i<4; i++)
{
columnDef[i] = gcnew ColumnDefinition();
columnDef[i]->Width = GridLength(1, GridUnitType::Auto);
this->ColumnDefinitions->Add(columnDef[i]);
}
for(int i=0; i<6; i++)
{
rowDef[i] = gcnew RowDefinition();
rowDef[i]->Height = GridLength(1, GridUnitType::Auto);
this->RowDefinitions->Add(rowDef[i]);
}
Als Nächstes fügt der Konstruktor die UI-Elemente hinzu Grid. Das erste Element ist der Titeltext, bei dem es sich um ein Label Steuerelement handelt, das in der ersten Zeile des Rasters zentriert ist.
//Add the title
titleText = gcnew Label();
titleText->Content = "Simple WPF Control";
titleText->HorizontalAlignment = System::Windows::HorizontalAlignment::Center;
titleText->Margin = Thickness(10, 5, 10, 0);
titleText->FontWeight = FontWeights::Bold;
titleText->FontSize = 14;
Grid::SetColumn(titleText, 0);
Grid::SetRow(titleText, 0);
Grid::SetColumnSpan(titleText, 4);
this->Children->Add(titleText);
Die nächste Zeile enthält das Name-Steuerelement Label und das zugehörige TextBox Steuerelement. Da derselbe Code für jedes Bezeichnungs-/Textfeld-Paar verwendet wird, wird er in ein Paar privater Methoden eingefügt und für alle fünf Bezeichnungs-/Textfeld-Paare verwendet. Die Methoden erstellen das entsprechende Steuerelement, und rufen Sie die Grid Klasse statisch SetColumn und SetRow Methoden auf, um die Steuerelemente in der entsprechenden Zelle zu platzieren. Nachdem das Steuerelement erstellt wurde, ruft das Beispiel die Add Methode für die Children Eigenschaft des Grid Steuerelements auf, um das Steuerelement zum Raster hinzuzufügen. Der Code zum Hinzufügen der verbleibenden Beschriftungs-/Textfeld-Paare ist ähnlich. Ausführliche Informationen finden Sie im Beispielcode.
//Add the Name Label and TextBox
nameLabel = CreateLabel(0, 1, "Name");
this->Children->Add(nameLabel);
nameTextBox = CreateTextBox(1, 1, 3);
this->Children->Add(nameTextBox);
Die Implementierung der beiden Methoden lautet wie folgt:
Label ^WPFPage::CreateLabel(int column, int row, String ^ text)
{
Label ^ newLabel = gcnew Label();
newLabel->Content = text;
newLabel->Margin = Thickness(10, 5, 10, 0);
newLabel->FontWeight = FontWeights::Normal;
newLabel->FontSize = 12;
Grid::SetColumn(newLabel, column);
Grid::SetRow(newLabel, row);
return newLabel;
}
TextBox ^WPFPage::CreateTextBox(int column, int row, int span)
{
TextBox ^newTextBox = gcnew TextBox();
newTextBox->Margin = Thickness(10, 5, 10, 0);
Grid::SetColumn(newTextBox, column);
Grid::SetRow(newTextBox, row);
Grid::SetColumnSpan(newTextBox, span);
return newTextBox;
}
Schließlich fügt das Beispiel die Schaltflächen "OK " und "Abbrechen " hinzu und fügt einen Ereignishandler an ihre Click Ereignisse an.
//Add the Buttons and atttach event handlers
okButton = CreateButton(0, 5, "OK");
cancelButton = CreateButton(1, 5, "Cancel");
this->Children->Add(okButton);
this->Children->Add(cancelButton);
okButton->Click += gcnew RoutedEventHandler(this, &WPFPage::ButtonClicked);
cancelButton->Click += gcnew RoutedEventHandler(this, &WPFPage::ButtonClicked);
Zurückgeben der Daten an das Hostfenster
Wenn auf eine der Schaltflächen geklickt wird, wird das Click Ereignis ausgelöst. Das Hostfenster kann einfach Handler an diese Ereignisse anfügen und die Daten direkt aus den TextBox Steuerelementen abrufen. Das Beispiel verwendet einen etwas weniger direkten Ansatz. Er behandelt den Click WPF-Inhalt und löst dann ein benutzerdefiniertes Ereignis OnButtonClicked
aus, um den WPF-Inhalt zu benachrichtigen. Dadurch kann der WPF-Inhalt eine Parameterüberprüfung durchführen, bevor der Host benachrichtigt wird. Der Handler ruft den Text aus den TextBox Steuerelementen ab und weist ihn öffentlichen Eigenschaften zu, aus denen der Host die Informationen abrufen kann.
Die Ereignisdeklaration in WPFPage.h:
public:
delegate void ButtonClickHandler(Object ^, MyPageEventArgs ^);
WPFPage();
WPFPage(int height, int width);
event ButtonClickHandler ^OnButtonClicked;
Der Click Ereignishandler in WPFPage.cpp:
void WPFPage::ButtonClicked(Object ^sender, RoutedEventArgs ^args)
{
//TODO: validate input data
bool okClicked = true;
if(sender == cancelButton)
okClicked = false;
EnteredName = nameTextBox->Text;
EnteredAddress = addressTextBox->Text;
EnteredCity = cityTextBox->Text;
EnteredState = stateTextBox->Text;
EnteredZip = zipTextBox->Text;
OnButtonClicked(this, gcnew MyPageEventArgs(okClicked));
}
Festlegen der WPF-Eigenschaften
Der Win32-Host ermöglicht es dem Benutzer, mehrere WPF-Inhaltseigenschaften zu ändern. Von Der Win32-Seite ist es einfach eine Frage der Änderung der Eigenschaften. Die Implementierung in der WPF-Inhaltsklasse ist etwas komplizierter, da es keine einzelne globale Eigenschaft gibt, die die Schriftarten für alle Steuerelemente steuert. Stattdessen wird die entsprechende Eigenschaft für jedes Steuerelement in den Set-Accessoren der Eigenschaften geändert. Das folgende Beispiel zeigt den Code für die DefaultFontFamily
Eigenschaft. Durch Festlegen der Eigenschaft wird eine private Methode aufgerufen, die wiederum die FontFamily Eigenschaften für die verschiedenen Steuerelemente festlegt.
Von WPFPage.h:
property FontFamily^ DefaultFontFamily
{
FontFamily^ get() {return _defaultFontFamily;}
void set(FontFamily^ value) {SetFontFamily(value);}
};
Von WPFPage.cpp:
void WPFPage::SetFontFamily(FontFamily^ newFontFamily)
{
_defaultFontFamily = newFontFamily;
titleText->FontFamily = newFontFamily;
nameLabel->FontFamily = newFontFamily;
addressLabel->FontFamily = newFontFamily;
cityLabel->FontFamily = newFontFamily;
stateLabel->FontFamily = newFontFamily;
zipLabel->FontFamily = newFontFamily;
}
Siehe auch
.NET Desktop feedback