PaintEventHandler eigenen Parameter mitgeben?

  • C#

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von Artentus.

    PaintEventHandler eigenen Parameter mitgeben?

    Nabend, Jemand eine Ahnung wie man dem Handler einen eigenen Parameter mitgeben kann?

    Quellcode

    1. this.Paint += new System.Windows.Forms.PaintEventHandler(this.PaintGameObjekts);
    2. void PaintGameObjekts(object sender, System.Windows.Forms.PaintEventArgs args){
    3. //Mal ma was
    4. }
    Jou. Eigenes Event, eigene EventParameter, eigener Event-Handler.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Eistee schrieb:

    die aktuelle gameTime
    solltest Du in der Klasse als Property hinterlegen, Paint kann dann einfach drauf zugreifen. :D
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Dann werd ich mal meine Klasse umbasteln.
    Bis jetzt sieht es ~ so aus:

    VB.NET-Quellcode

    1. class Loop{
    2. delegate void MethodInvoker();
    3. private void Draw(){
    4. GameTime gameTime = new GameTime(x,y,z);
    5. while (isRunning)
    6. {
    7. //gameTime-hier-und-da
    8. Program.GameForm.Invoke(new MethodInvoker(mfi_Paint));
    9. //ABC = gameTime irgendwas
    10. //gameTime noch was
    11. }
    12. }
    13. void mfi_Paint(){
    14. Program.GameForm.Invalidate();
    15. }
    16. }


    Wär es jetzt besser die GameTime in die Program.GameForm zu verlegen oder nur aus Loop herraus zugänglich zu machen? Seit neustem tue ich mir mit dem Klassendesign echt schwer :pinch:
    Hi

    VB.NET-Quellcode

    1. Public Class GameTimePaintEventArgs
    2. Inherits PaintEventArgs
    3. Private _gameTime As TimeSpan
    4. Public Sub New(graphics As Graphics, clipRect As Rectangle, gameTime As TimeSpan)
    5. MyBase.New(graphics, clipRect)
    6. Me.GameTime = gameTime
    7. End Sub
    8. Public Property GameTime As TimeSpan
    9. Get
    10. Return _gameTime
    11. End Get
    12. Private Set(value As TimeSpan)
    13. _gameTime = value
    14. End Set
    15. End Property
    16. End Class
    17. Public Class CustomControlBla
    18. Inherits Control
    19. Public Shadows Event Paint As EventHandler(Of GameTimePaintEventArgs)
    20. Protected Overrides Sub OnPaint(e As PaintEventArgs)
    21. MyBase.OnPaint(e)
    22. RaiseEvent Paint(Me, New GameTimePaintEventArgs(e.Graphics, e.ClipRectangle, GameTime))
    23. End Sub
    24. End Class

    Hab' beim Programmieren leider nicht bemerkt, dass es als C# markiert war. Meinst du sowas in der Art? das GameTimePaintEventArgs sollte für dich das interessantere sein.

    Program.GameForm.Invoke(new MethodInvoker(mfi_Paint)); kannst du auch einfach in Program.GameForm.Invoke(new MethodInvoker(rogram.GameForm.Invalidate)); umschreiben.

    GameTime würde ich in einer extra Klasse modellieren und einfach void Advance(TimeSpan) definieren. Die Klasse hat dann eine ICollection<IProgressEntity>, bei der IProgressEntity ein Interface ist, das auf Advance reagiert. Z.B. Physik und Animation sind solche IProgressEntity-Objekte.

    Gruß
    ~blaze~
    @ThuCommix: Was heißt GameEngine, ich möcht eig. nur Rund 10 bis max. 30 Objekte bewegen
    (+ Hintergrund mit ~ 1400 x 900 Pixel).
    Edit: Meinst Du eig. GDI+ selbst oder nur, dass das PaintEvent der Form nicht der richtige Weg ist?

    ~blaze~ schrieb:

    in Program.GameForm.Invoke(new MethodInvoker(rogram.GameForm.Invalidate)); umschreiben.

    :S (Hätt ich selber sehen müssen) Danke.

    GameTime würde ich in einer extra Klasse modellieren und einfach [...]

    Also GameTime als eigene Klasse (ist klar), mit einem void Advance(TimeSpan) und einer ICollection<IProgressEntity>
    wobei die IProgressEntity auf Advance reagiert?
    IProgressEntity gehört zu einzelnen Objekten oder wie? Ich kann dir leider nciht wirklich folgen, würdest Du das eventuell noch einmal etwas weiter ausführen? Eventuell könnt ich dann folgen ^^

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Eistee“ ()

    C#-Quellcode

    1. public interface IProgressEntity
    2. {
    3. void Advance(TimeSpan timeSpan);
    4. }
    5. public class ProgressEntityList<T> : IProgressEntity //quasi composite pattern
    6. where T : IProgressEntity
    7. {
    8. public ICollection<T> Elements { get; private set; }
    9. public ProgressEntityList()
    10. {
    11. Elements = new LinkedList<T>();
    12. }
    13. public virtual void Advance(TimeSpan timeSpan)
    14. {
    15. foreach(T element in Elements)
    16. elements.Advance(timeSpan);
    17. }
    18. }
    19. public class GameClock
    20. {
    21. public ProgressEntityList<IProgressEntity> Elements { get; private set; }
    22. //advance z.b. durch einen Timer getriggert oder sowas Elements. Elements könnte man auch als IProgressEntity festlegen
    23. }
    24. public class Physics : IProgressEntity
    25. {
    26. //Kollision, etc. in Advance durchführen
    27. }

    sowas in der Art.
    Sorry ich war in der Schule und konnte nicht ordentlich schreiben.

    Was ich meinte:

    Die Form hat für dich keine relevanten Events außer eventuell KeyDown, ansonsten ist sie nur eine Oberfläche, und du zeichnest via gdi32 auf diese Oberfläche. Du erstellst dir also eine Buffer Bitmap auf die du erstmal alles deine Objekte zeichnest. Wenn du mit zeichnen fertig bist zeichnest du den Buffer auf die Form, dabei sollte dir helfen:

    Graphics.GetHdc()
    CreateCompatibleDC
    SelectObject
    StretchBlt
    DeleteObject
    DeleteObject
    Graphics.ReleaseHdc()

    Alles zu findet in der gdi32 bzw in Graphics.
    also ich muß nochmal nach dem Plan fragen. "gameTime mitgeben" ist kein Plan - wozu soll man einem Paint eine gameTime mitgeben, was ist das, und wo kommt die her etc.

    streng genommen kann man einem PaintEventHandler keinen anneren Parameter mitgeben, denn ein PaintEventHandler ist halt definiert wie er ist:

    ObjectBrowser schrieb:

    Public Delegate Sub PaintEventHandler(sender As Object, e As System.Windows.Forms.PaintEventArgs)
    Member von System.Windows.Forms

    Und auch das Paint-Event ist bereits fertig definiert:

    ObjectBrowser schrieb:

    Public Event Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs)
    Member von System.Windows.Forms.Control
    Und hinter diesem Instrumentarium steckt das ausgebuffte Konzept des Ownerdrawings in Windows.Forms.
    Ownerdrawing malt ganz gezielt nur dann, wenn sich etwas verändert hat, und auch nur genau das, was sich geändert hat.

    PaintEvent ist also belegt, und wenn du ähnliches coden willst, dann nenne es anders.

    Aber stichwort game deutet drauf hin, dass dir garkein Ownderdrawing vorschwebt.
    Sondern du willst so render-engine-mäßig einen game-loop haben, wo ununterbrochen in sehr kurzen Abständen iwas gemalt wird.

    Dassis ein ganz anneres Konzept als Ownerdrawing, und bei sowas spricht man besser von Rendern.
    Ownerdrawing wird von WinForms unterstützt und ist sehr effektiv und resourcenschonend bei eher statischen Darstellungen (Formulare, "Forms" halt). Deshalb kann Ownerdrawing auf Grafikkarten-Unterstützung verzichten, und die ganze Zeichnerei inne CPU durchführen.

    render-engines rasen ständig im Kreis und bauen jedesmal den ganzen bildschirm neu auf. Dassis vorteilhaft bei film-artigen Bewegungen, wie sie in games häufig auftreten. Dazu verwenden sie Grafikkarten-Unterstützung, weil wenn man das in GDI(+) absolvieren wollte, wäre das System im Ruhezustand wohl zu 80% ausgelastet.

    also nochmal meine Frage nach dem Plan, was das eiglich werden soll?

    jdfs. in keinem Fall kommtes mir sinnvoll vor, iwie ein neues Control zu erfinden, mit einem neuen Paint-Event.
    @ErfinderDesRades: Ok dann möchte ich etwas Rendern.

    Zuerst einmal nur ein Feld aus Rechtecken (z. B. 60*40 mit einer größe von 20*20 Pixel [1200x800 Pixel]).
    Auf dem Feld Werden regelmäßig Objekt bewegt, also wird das gesamte Bild immer wieder neu gerendert.

    Dacht mir die 960.000 Pixel mit 60 oder ehr 30 FPS gehen mit Form.Invalidate klar.
    Wollte nicht extra SharpDX installieren/verwenden.
    also wenn nur so kleine Rechtecke bewegt werden, könnte OwnerDrawing noch ausreichen.

    guggemol Gezieltes OwnerDrawing, was so an Beweglichkeit noch machbar ist.

    Das Prob mittm Rendern ist, dassich davon keine Ahnung hab. Ich hab mich auch an Artentus' "RenderEngine" versucht, aber mehr als eine große schwarze Fläche hat die mir nicht gerendert - also auch damit wird der Umgang vmtl. nicht einfach.
    Ich hab vor langer Zeit auch mal mit DirectX rumgewurstelt, und da konnte ich schließlich Teekannen rotieren lassen, und Objekte herumfliegen, aber das war schon eine irrsinnige Menge Code, und noch nichtmal die einfachste Kollisionsabfrage war dabei.