Laden...

GDI32 fehler bei Invalidate

Erstellt von TNDAri vor 16 Jahren Letzter Beitrag vor 16 Jahren 1.406 Views
TNDAri Themenstarter:in
139 Beiträge seit 2006
vor 16 Jahren
GDI32 fehler bei Invalidate

Moin!

Ist wahrscheinlich nur eine simple sache, aber ich komm einfach auf keine Lösung.
Spiele zur zeit ein wenig mit der GDI API rum. Ich hab ein Panel, das komplett von der GDI gezeichnet wird (nicht GDI+).
Ich habe einen BackBuffer (Memory DC) auf dem alles vorgezeichnet wird und danach mit BitBlt aufs Panel übertragen wird.
Funzt auch alles wunderbar, nur nachdem ich jetzt von der variante, das ganze Panel neu zu "bezeichnen", auf die variante mit UpdateRects umgestiegen bin, hab ich ein paar Probleme.
Das UpdateRect wird ja immer bei der BeginPaint funktion in der PAINTSTRUCT mit geliefert. Wenn das Panel nun stumpf mit InvalidateRect geupdatet wird, ist kein Problem vorhanden.
Sobal ich aber mit einem anderen Fenster drüber "fahre" oder das Panel zur Runtime vergrößere, malt er mit hässliche linen mit aufs Panel und ausserdem wird nicht mehr alle korekt dargestellt. Ich häng mal ein Bild mit dran.

Vielleicht weiss ja jemand ne lösung, oder geht es wirklich nur mit einem kompletten repaint des Panels?

Danke schonmal im vorraus.

Gruss Ari
Wer lesen kann ist klar im vorteil!
MSDN
Dein Feund in allen fragen

871 Beiträge seit 2005
vor 16 Jahren

Hallo,

das hört sich so an, als ob in deinem Paint Handler das Invalidierte Rect nicht korrekt aus dem BackBuffer rüberkopiert wird. Zeig uns mal etwas Code, dann können wir schauen ob wir was finden.

Grüsse,
Egon

4.506 Beiträge seit 2004
vor 16 Jahren

Hallo TNDAri,

arbeitest Du dann auch mit den Windows-Messages? Oder lässt Du .NET gewisse Events abarbeiten?

Ich denke Dir fehlen gewisse Informationen, eben bei Größenänderung (WM_SIZING, WM_SIZE) oder bei Invalidate (gerade entfallen was für eine Message da verwendet wird, eventuell WM_PAINT).

Ich gehe also davon aus, dass das Neuzeichnen des Rechtecks schon nicht mehr aktuell ist, sobald Du es zeichnen musst. Eventuell ist die Größenangabe des Rechtecks zu dem Zeitpunkt der Zeichnung nicht korrekt.

Ich bin mir nicht sicher in wie weit .NET diese Messages mitbekommt, wenn man direkt mit der GDI API arbeitet.

Ich kann Dir als Tipp geben, dass Du die WndProc implementierst, und dort mal ausgeben lässt, was da ankommt (aber bitte keine MessageBox, sondern ein System.Diagnostics.Debug.Trace ).

Für eine Liste "aller" Windows-Messages:
WINE Wiki - List of Windows Messages

Grüße
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo TNDAri,

siehe [Hinweis] Wie poste ich richtig? Punkt 6.1

herbivore

TNDAri Themenstarter:in
139 Beiträge seit 2006
vor 16 Jahren

Sorry hab mich gestern verschreiben, ich benut als Basisklasse Control nicht Panel 😁

Also vom Control sind die OnPaint und OnPaintBackground funktion überschreiben, so das die nix machen, also auch nicht die base funktion aufrufen.
Es wird alles über die WindowsMessages gemacht. Hatte zwar erst vergessen WM_SIZE und WM_SIZING zu verarbeiten aber auch wenn ich das amche, bleibt das selbe Problem.

Also hier ein bissel Code:


private GDIMemDC mBuffer; // Memory DC

protected override void OnPaint( PaintEventArgs e ) { }
protected override void OnPaintBackground( PaintEventArgs pevent ) { }
protected override void OnSizeChanged( EventArgs e ) { }

public static int HiWord( int number )
        {
            return ( number >> 16 ) & 0xFFFF;
        }

        public static int LoWord( int number )
        {
            return number & 0xFFFF;
        }

        protected override void WndProc( ref Message m )
        {
            switch ( (WindowsMessages)m.Msg )
            {
                case WindowsMessages.WM_FONTCHANGE:
                    MeasureTextMetric( );
                    break;
                case WindowsMessages.WM_CREATE:
                    MeasureTextMetric( );
                    break;
                case WindowsMessages.WM_SETFOCUS:
                    break;
                case WindowsMessages.WM_SIZE:
                    this.Width = LoWord( m.LParam.ToInt32() );
                    this.Height = HiWord( m.LParam.ToInt32( ) );
                    mBuffer.SetSize( Width, Height );
                    break;
                case WindowsMessages.WM_SIZING:
                    //m.Result = new IntPtr( 1 );
                    break;
                case WindowsMessages.WM_ERASEBKGND:
                    m.Result = new IntPtr( 1 );
                    return;
                case WindowsMessages.WM_PAINT:
                    GDIGraphics g = GDIGraphics.FromHandle( this.Handle );
                    Rectangle ur = g.UpdateRect;

                    DrawTextArea( mBuffer, ur );
                    DrawGutterArea( mBuffer, ur );

                    mBuffer.Draw( g.Hdc, ur.X, ur.Y, ur.Width, ur.Height, ur.X, ur.Y );

                    g.Destroy( );
                    break;
            }

            base.WndProc( ref m );
        }
    }

Für die GDI verwendung häng ich den Code mal mit dran. Ist an manchen stelölen etwas verbesserungs würdig und es sind noch längst nicht alle Funktionen drinne, aber für mich funzt die.
Meine vermutung ist noch, da ich bei den GDIGraphics funktionen System.Drawing.Rectangle's und System.Drawing.Color's benutze, das alles etwas evtl ausbremst.
Naja schauts euch an 😉

Gruss Ari
Wer lesen kann ist klar im vorteil!
MSDN
Dein Feund in allen fragen

TNDAri Themenstarter:in
139 Beiträge seit 2006
vor 16 Jahren

Ok, hab ein bisschen die GDI sachen verändert und raus genommen, das der Buffer jedesmal wenn WM_PAINT kommt neu gezeichnet wird (wenns auch nur bestimmte abschnitte waren) und siehe da, das Probelm ist gelöst 😉

Gruss Ari
Wer lesen kann ist klar im vorteil!
MSDN
Dein Feund in allen fragen