Laden...

XNA + Windows Forms

Erstellt von sbertl000 vor 16 Jahren Letzter Beitrag vor 16 Jahren 2.706 Views
sbertl000 Themenstarter:in
822 Beiträge seit 2005
vor 16 Jahren
XNA + Windows Forms

Hy

Ist es möglich, XNA in ein Control zu rendern und nebenbei auch noch Controls auf meinem Formular zu haben? So, wie in dem angehängten Bild. Es soll in das blaue Panel gerendert werden.

sbertl

5.942 Beiträge seit 2005
vor 16 Jahren

Hallo sbertl000

Mit Managed DirectX ist das auf jeden Fall möglich, auch mit XNA sollte das gehen.
Du benutzt dazu das Handle des Controls.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

sbertl000 Themenstarter:in
822 Beiträge seit 2005
vor 16 Jahren

Und wo weiß ich das Handle zu? Und wo muss ich dann:

using (Game1 game = new Game1())
            {
                game.Run();
            }

plazieren, damit auch Form Events geworfen werden und die GUI nicht einfriert?

sbertl

228 Beiträge seit 2006
vor 16 Jahren

das hilft dir evt.

XNA - WinForms

MfG MEt45

Medieval Fantasy Online - ORPG Projekt
.NET - Try and Error - Blog - Gemeinschaftsblog
MEt45's Dev Garage - Eigener Blog

sbertl000 Themenstarter:in
822 Beiträge seit 2005
vor 16 Jahren

Ok, so funktioniert das, aber dadurch muss ich doch wieder alles manuell machen. Das Game-Loop... Und ich hab auch dann keine Klasse mehr, die von Game erbt. Kann man das nicht anders realisieren?

sbertl

sbertl000 Themenstarter:in
822 Beiträge seit 2005
vor 16 Jahren

Ich hab auch noch eine andere Möglichkeit gefunden, so kann man direkt in ein Control rendern:

graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);
private void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs eventargs)
        {
eventargs.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = handle; //handle ist ein IntPtr Handle eines Controls
        }

Allerdings ist die Performance mehr als grausig, so krieg ich gerade mal 20 fps zusammen mit einem einfachen Dreieck...

Es geht auch noch anders, indem man die Controls über das gerenderte Fenster legt. Im Konstruktor des Spiels z.B. folgendes hinzufügen:

System.Windows.Forms.Control gameWindow = System.Windows.Forms.Control.FromHandle(this.Window.Handle);
            panel = new System.Windows.Forms.Panel();
            panel.Bounds = new System.Drawing.Rectangle(700, 0, 100, 600);
            panel.Parent = gameWindow;

Dann liegt das Panel allerdings wieder über dem zu zeichnenden Bereich, was auch nicht ideal ist.

sbertl

148 Beiträge seit 2006
vor 16 Jahren

Hi sbertl,

vielleicht hab ich das Problem falsch verstanden oder stells mir auch zu einfach vor.. Aber ich hätte jetzt einfach gesagt, dass du beim Rendern am Schluss einfach sagst

device.Present(myControl);

dann rendert er nur in dem Control.. wenn du ein Label übergibst, dann eben in deinem Label.. das erscheint mir nu allerdings zu einfach, also hab ich wohl was falsch verstanden? 🤔

greetz..

I cna tpye 300 wrods pre mnuite!

sbertl000 Themenstarter:in
822 Beiträge seit 2005
vor 16 Jahren

Ja, das stimmt schon, aber das hat genau die selbe Auswirkung wie

eventargs.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = panel.Handle;

sbertl

5.942 Beiträge seit 2005
vor 16 Jahren

Hallo zusammen

Ich benutze folgender Code, um mit Managed DirectX in eine Form zu zeichnen.
(Form ist auch ein Control):


this._device = new Device(0, DeviceType.Hardware, this,
                CreateFlags.SoftwareVertexProcessing, pres);

Evt. http://www.zaknafein.hjcrusaders.com/?p=21

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

sbertl000 Themenstarter:in
822 Beiträge seit 2005
vor 16 Jahren

Du hast schon recht, aber würde ich das bei XNA so machen könnte ich den vorgefertigten GraphicsDeviceManager und ContentManager nicht mehr verwenden. Dein Link beschreibt eh das, was ich oben schon gepostet habe:

graphics.PreparingDeviceSettings Event abfangen und dann

eventargs.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = BeliebigesControl.Handle;

Wie gesagt, es funktioniert, allerdings verliere ich Performance und ganz besonders, was bei MDX nicht passiert: Meine FPS Anzeige von Fraps oder anderen wird sehr klein und passt sich der AspectRation nicht an.

sbertl

sbertl000 Themenstarter:in
822 Beiträge seit 2005
vor 16 Jahren

Ein Problem bleibt jedoch. Die Größe des Backbuffers muss ja auf die Größe des Forms eingestellt werden, sonst wird das Form kleiner. Mein Panel ist aber kleiner (z.B.: 320x240) doch der Backbuffer hat z.B.: 800x600...

sbertl

228 Beiträge seit 2006
vor 16 Jahren

ich verweise ma auf meine andere antwort:

http://www.mycsharp.de/wbb2/thread.php?threadid=39398

Medieval Fantasy Online - ORPG Projekt
.NET - Try and Error - Blog - Gemeinschaftsblog
MEt45's Dev Garage - Eigener Blog

sbertl000 Themenstarter:in
822 Beiträge seit 2005
vor 16 Jahren

Ok, das war mir klar, wie man die Größe des Forms verändert...

Aber: Ich habe ein Form mit 800x600, demnach muss auch der BackBuffer auf 800x600 eingestellt werden, sonst wird das Form kleiner.

Jetzt hab ich aber ein Panel mit z.B.: 320x240 in das ich rendere, allerdings hat der BackBuffer immer noch 800x600 und somit werden diese 800x600 in das 320x240 Panel gerendert

sbertl

R
344 Beiträge seit 2006
vor 16 Jahren

Ist zwar schon etwas her, aber vielleicht wäre das etwas:

http://www.nuclex.org/downloads/developers/kits/xna-usercontrol

Gruß Robert

5.658 Beiträge seit 2006
vor 16 Jahren

Du hast zwei Möglichkeiten. Entweder veränderst du die Größe des Backbuffers im Resize-Ereignishandler oder du benutzt eine eigene SwapChain.

Wenn du den Backbuffer vergrößerst, mußt du das Device resetten (das bezieht sich übrigens alles Managed DirectX, dürfte aber bei XNA zumindest ähnlich ablaufen).

Wenn du eine eigene SwapChain benutzt, kannst du jedesmal, wenn das Fenster vergrößert/verkleinert wird, die alte SwapChain einfach löschen und eine neue erstellen:



// SwapChain erstellen:
PresentParameters presentParams = device.PresentationParameters.Clone() as PresentParameters;
presentParams.DeviceWindow = this;
presentParams.BackBufferCount = 1;
presentParams.BackBufferWidth = this.Width;
presentParams.BackBufferHeight = this.Height;
presentParams.Windowed = true;
// ... (andere Einstellungen)
SwapChain swapChain = new SwapChain(device, presentParams);

// Löschen:
swapChain.Dispose();

// Anstatt device.Present(this)
swapChain.Present();


Die Backbuffer-Größe für das Device kannst du beim Erstellen einfach auf 1x1 setzen, um den Speicher zu sparen.

Schöne Grüße,
Christian

Weeks of programming can save you hours of planning