wie man aufhört, C # -Winforms zu flackern

76

Ich habe ein Programm, das im Wesentlichen wie eine Farbanwendung ist. Mein Programm hat jedoch einige flackernde Probleme. Ich habe die folgende Zeile in meinem Code (die das Flackern beseitigen sollte - aber nicht):

this.SetStyle(ControlStyles.AllPaintingInWmPaint 
| ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);

Mein Code (abzüglich der Super- und Unterklassen für die Formen lautet wie folgt:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Paint
{
    public partial class Paint : Form
    {
        private Point startPoint;
        private Point endPoint;
        private Rectangle rect = new Rectangle();
        private Int32 brushThickness = 0;
        private Boolean drawSPaint = false;
        private List<Shapes> listOfShapes = new List<Shapes>();
        private Color currentColor;
        private Color currentBoarderColor;
        private Boolean IsShapeRectangle = false;
        private Boolean IsShapeCircle = false;
        private Boolean IsShapeLine = false;

        public SPaint()
        {

            InitializeComponent();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);

            currentColor = Color.Red;
            currentBoarderColor = Color.DodgerBlue;
            IsShapeRectangle = true; 
        }

        private void panelArea_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = panelArea.CreateGraphics();

            if (drawSPaint == true)
            {

                Pen p = new Pen(Color.Blue);
                p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;

                if (IsShapeRectangle == true)
                {
                    g.DrawRectangle(p, rect);
                }
                else if (IsShapeCircle == true)
                {
                    g.DrawEllipse(p, rect);
                }
                else if (IsShapeLine == true)
                {
                    g.DrawLine(p, startPoint, endPoint);
                }
            }
            foreach (Shapes shape in listOfShapes)
            {

                shape.Draw(g);

            }
        }

        private void panelArea_MouseDown(object sender, MouseEventArgs e)
        {

            startPoint.X = e.X;
            startPoint.Y = e.Y;

            drawSPaint = true;
        }

        private void panelArea_MouseMove(object sender, MouseEventArgs e)
        {


            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {

                if (e.X > startPoint.X)
                {
                    rect.X = startPoint.X;
                    rect.Width = e.X - startPoint.X;
                }
                else
                {
                    rect.X = e.X;
                    rect.Width = startPoint.X - e.X;
                }
                if (e.Y > startPoint.Y)
                {
                    rect.Y = startPoint.Y;
                    rect.Height = e.Y - startPoint.Y;
                }
                else
                {
                    rect.Y = e.Y;
                    rect.Height = startPoint.Y - e.Y;
                }


                panelArea.Invalidate();

            }

        }

        private void panelArea_MouseUp(object sender, MouseEventArgs e)
        {

            endPoint.X = e.X;
            endPoint.Y = e.Y;

            drawSPaint = false;

            if (rect.Width > 0 && rect.Height > 0)
            {
                if (IsShapeRectangle == true)
                {
                    listOfShapes.Add(new TheRectangles(rect, currentColor, currentBoarderColor, brushThickness));
                }
                else if (IsShapeCircle == true)
                {
                    listOfShapes.Add(new TheCircles(rect, currentColor, currentBoarderColor, brushThickness));
                }
                else if (IsShapeLine == true)
                {
                    listOfShapes.Add(new TheLines(startPoint, endPoint, currentColor, currentBoarderColor, brushThickness));
                }

                panelArea.Invalidate();
            }
        }


        private void rectangleToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IsShapeRectangle = true;
            IsShapeCircle = false;
            IsShapeLine = false; 
        }

        private void ellipseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IsShapeRectangle = false;
            IsShapeCircle = true;
            IsShapeLine = false; 
        }

        private void lineToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IsShapeCircle = false;
            IsShapeRectangle = false;
            IsShapeLine = true; 
        }

        private void ThicknessLevel0_Click(object sender, EventArgs e)
        {
            brushThickness = 0; 
        }

        private void ThicknessLevel2_Click(object sender, EventArgs e)
        {
            brushThickness = 2; 
        }

        private void ThicknessLevel4_Click(object sender, EventArgs e)
        {
            brushThickness = 4; 
        }

        private void ThicknessLevel6_Click(object sender, EventArgs e)
        {
            brushThickness = 6; 
        }

        private void ThicknessLevel8_Click(object sender, EventArgs e)
        {
            brushThickness = 8; 
        }

        private void ThicknessLevel10_Click(object sender, EventArgs e)
        {
            brushThickness = 10; 
        }

        private void ThicknessLevel12_Click(object sender, EventArgs e)
        {
            brushThickness = 12; 
        }

        private void ThicknessLevel14_Click(object sender, EventArgs e)
        {
            brushThickness = 14; 
        }

        private void FillColour_Click(object sender, EventArgs e)
        {

            ColorDialog fillColourDialog = new ColorDialog();
            fillColourDialog.ShowDialog();
            currentColor = fillColourDialog.Color;
            panelArea.Invalidate(); 
        }

        private void button1_Click(object sender, EventArgs e)
        {

            ColorDialog fillColourDialog = new ColorDialog();
            fillColourDialog.ShowDialog();
            currentBoarderColor = fillColourDialog.Color;
            panelArea.Invalidate(); 
        }


    }
}

Wie stoppe ich das Flackern?

* UPDATE: * Dieser Code funktioniert wirklich gut, wenn ich direkt auf dem Formular zeichne. Wenn ich jedoch versuche, auf das Panel zu zeichnen, wird das Flackern zu einem Problem

Großer Käfer
quelle
7
Hast du auch eingestellt this.DoubleBuffered = true;?
Marc Gravell
1
@ Marc Gravell Ich habe gerade versucht, dies hinzuzufügen. DoubleBuffered = true; und es flackert immer noch wie verrückt: S
BigBug
Ist panelArea voller Steuerelemente? Invalidate funktioniert rekursiv und kann daher dazu führen, dass jedes untergeordnete Steuerelement in panelArea neu gestrichen wird
Polity
@ Polity nein, panelArea ist nur ein Panel, auf das ich zeichne. Es hat jedoch keine Kontrollen ..
BigBug
1
+1, ehrlich gesagt hat mir die SetStyle-Funktion geholfen, das Flimmern zu beseitigen. c # ist soooo viel besser als c ++ !!!
Neophile

Antworten:

69

Für eine "sauberere Lösung" und um das Basisfenster weiterhin zu verwenden, können Sie einfach Reflection verwenden, um die doppelte Pufferung zu implementieren, indem Sie diesen Code dem Formular hinzufügen, das die Felder enthält, in die Sie zeichnen möchten

    typeof(Panel).InvokeMember("DoubleBuffered", 
    BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic, 
    null, DrawingPanel, new object[] { true });

Wobei "DrawingPanel" der Name des Bedienfelds ist, für das Sie die doppelte Pufferung durchführen möchten.

Ich weiß, dass seit der Frage ziemlich viel Zeit vergangen ist, aber dies könnte in Zukunft jemandem helfen.

Viper
quelle
3
Dies ist eine großartige Lösung! Sehr einfach zu implementieren und funktioniert genau wie gewünscht
Musefan
5
@musefan Ich bin so froh, Ihnen geholfen zu haben: DI bin froh, dass eine Lösung, die 2 Jahre später als die ursprüngliche Frage veröffentlicht wurde, immer noch Menschen helfen kann! Deshalb ist der Stapelüberlauf so gut! :)
Viper
1
Es flackert immer noch für mich. Wo füge ich diesen Code hinzu? PS. In dieser Antwort sollte oben "Sie müssen 'System.Reflection verwenden' stehen."
John Ktejik
2
Sie müssen dies für das Bedienfeld aufrufen, das das Flackern stoppen soll, bevor Sie es verwenden. Sie können es im Load-Ereignis Ihres Hauptformulars (oder des Formulars mit dem Bedienfeld) aufrufen. Wo nennst du es?
Viper
3
@RotaryHeart Bitte beachten Sie, dass Sie dies nicht in der Malmethode verwenden sollten, da es jedes Mal ausgeführt wird, wenn das Steuerelement neu gestrichen wird und die Reflexion teuer ist. Sie müssen dies nur einmal pro Steuerelement einstellen. Ich bin mir nicht sicher, ob Sie dies getan haben. Nach dem Lesen Ihres Kommentars schien es, als wäre es Ihre Lösung gewesen.
Viper
64

Endlich das Flackern gelöst. Da ich anstelle des Formulars auf einer Tafel gezeichnet habe, löst die folgende Codezeile das Flackern nicht:

this.SetStyle(
    ControlStyles.AllPaintingInWmPaint | 
    ControlStyles.UserPaint | 
    ControlStyles.DoubleBuffer, 
    true);

SetStyle muss vom Typ 'YourProject.YourProject' sein (oder davon abgeleitet sein), daher müssen Sie eine Klasse als solche erstellen (damit Sie MyPanel verwenden können, das von SPaint.SPaint abgeleitet wird und somit Doublebuffering direkt für verwenden kann das Panel - und nicht das Formular):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SPaint; 

namespace YourProject
{
    public class MyPanel : System.Windows.Forms.Panel
    {
        public MyPanel()
        {
            this.SetStyle(
                System.Windows.Forms.ControlStyles.UserPaint | 
                System.Windows.Forms.ControlStyles.AllPaintingInWmPaint | 
                System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer, 
                true);
        }
    }
}

Nachdem Sie dies getan haben (obwohl Sie den Designer-Code eigentlich nie bearbeiten sollten, es sei denn, Sie wissen wirklich, was Sie tun), müssen Sie die Form.Designer.cs bearbeiten. In dieser Datei finden Sie Code, der folgendermaßen aussieht:

this.panelArea = new YourProject.MyPanel();

Die obige Zeile muss geändert werden in:

this.panelArea = new MyPanel(); 

Nachdem ich diese Schritte ausgeführt habe, flackert mein Malprogramm nicht mehr.

Für alle anderen, die das gleiche Problem haben, ist das Problem endlich gelöst.

Genießen!

Großer Käfer
quelle
Aber es erscheint nicht mehr im Designer. Wie auch immer, um es zu beheben?
Flügelspieler Sendon
@WingerSendon - Um Designerprobleme zu vermeiden, verwenden Sie eine "Code" -Lösung wie die von Viper , mit der die Doppelpufferung zur Laufzeit festgelegt wird.
ToolmakerSteve
42

Kopieren Sie diese und fügen Sie sie in Ihr Projekt ein

protected override CreateParams CreateParams
{
    get
    {
        CreateParams handleParam = base.CreateParams;
        handleParam.ExStyle |= 0x02000000;   // WS_EX_COMPOSITED       
        return handleParam;
    }
}

Dies ermöglicht die Doppelpufferung für alle Steuerelemente ab der Formularebene. Andernfalls muss die Doppelpufferung für jedes Steuerelement einzeln aktiviert werden. Anschließend möchten Sie möglicherweise die Doppelpufferung optimieren, da eine doppelte Doppelpufferung unerwünschte Nebenwirkungen haben kann.

user3641393
quelle
8
Um Ihre Antworten nützlicher zu machen, sollten Sie eine kurze Erklärung hinzufügen, warum ein bestimmter Code zur Beantwortung der Frage hilfreich sein kann.
Kris
2
Es sieht so aus, als wäre dies die Quelle , die auch hier auf SO veröffentlicht wird . Die grundlegende Erklärung dafür ist, dass dies die doppelte Pufferung für alle Steuerelemente ab der Formularebene ermöglicht. Andernfalls muss die doppelte Pufferung individuell aktiviert werden jeder ... Sie können danach die doppelte Pufferung fein einstellen, da eine doppelte Pufferung unerwünschte Nebenwirkungen hervorrufen kann
u8it
Warum funktioniert das eher als die akzeptierte Antwort?
Aswzen
@ Ivan 10+? Wow: D
Momoro
16

Ich hatte das gleiche Problem. Ich konnte mich nie zu 100% vom Flimmern befreien (siehe Punkt 2), aber ich habe es benutzt

protected override void OnPaint(PaintEventArgs e) {}

ebenso gut wie

this.DoubleBuffered = true;

Das Hauptproblem beim Flackern ist, dass Sie sich vergewissern

  1. Malen Sie die Dinge in der richtigen Reihenfolge!
  2. Stellen Sie sicher, dass Ihre Zeichenfunktion <ungefähr 1/60 Sekunde ist

winforms ruft die OnPaintMethode jedes Mal auf , wenn das Formular neu gezeichnet werden muss. Es gibt viele Möglichkeiten, wie es entwertet werden kann. Wenn Sie einen Mauszeiger über das Formular bewegen, kann dies manchmal zu einem Neuzeichnungsereignis führen.

Und ein wichtiger Hinweis OnPaintist, dass Sie nicht jedes Mal von vorne anfangen, sondern dort beginnen, wo Sie waren. Wenn Sie die Hintergrundfarbe überfluten, werden Sie wahrscheinlich flackern.

Endlich dein gfx Objekt. Im Inneren müssen OnPaintSie das Grafikobjekt neu erstellen, jedoch NUR, wenn sich die Bildschirmgröße geändert hat. Die Neuerstellung des Objekts ist sehr teuer und muss vor der Neuerstellung entsorgt werden (die Speicherbereinigung behandelt es nicht zu 100% korrekt, heißt es in der Dokumentation). Ich habe eine Klassenvariable erstellt

protected Graphics gfx = null;

und dann lokal OnPaintso verwendet, aber das lag daran, dass ich das gfx-Objekt an anderen Stellen in meiner Klasse verwenden musste. Andernfalls tun Sie dies nicht. Wenn Sie nur in OnPaint malen, verwenden Sie bitte e.Graphics!!

// clean up old graphics object
gfx.Dispose();

// recreate graphics object (dont use e.Graphics, because we need to use it 
// in other functions)
gfx = this.CreateGraphics();

Hoffe das hilft.

Ohmusama
quelle
Dies hat mein Problem nicht gelöst :( .. Dieser Code funktioniert tatsächlich hervorragend, wenn ich direkt auf dem Formular zeichne. Wenn ich jedoch versuche, auf dem Bedienfeld zu zeichnen, wird Flackern zu einem Problem ...
BigBug
@BlueMonster als versuchen, Panel.DoubleBuffered = true;
Burimi
Ich empfehle, ein untergeordnetes Objekt der Panel-Klasse zu erstellen, vom Panel zu erben und dann das untergeordnete protected override void OnPaint(PaintEventArgs e) {}Objekt zu überschreiben. Das neue Objekt wird in Ihrer Liste der Elemente angezeigt, die in Ihr Formular eingefügt werden sollen. Sie können den Code auch manuell bearbeiten, um den Referenztyp zu ändern, wenn Sie das Bedienfeld bereits erstellt haben und nicht die einfache Möglichkeit haben, es einfach neu zu erstellen.
Ohmusama
Verwenden von e.GraphicsHilfen zusammen mit this.DoubleBuffered = true. Durch die Verwendung von erstellt Graphicserhöht der doppelte Puffer nicht nur den Flackereffekt, sondern macht das Control(oder Form) während der meisten Zeit auch weiß.
Meow Cat 2012
4

Doppelte Pufferung wird hier leider keine große Hilfe sein. Ich bin vor einiger Zeit darauf gestoßen und habe auf ziemlich ungeschickte Weise ein separates Panel hinzugefügt, aber es hat für meine Anwendung funktioniert.

Machen Sie das ursprüngliche Panel, das Sie haben (panelArea), zu einem transparenten Bereich und legen Sie es auf ein zweites Panel, das Sie beispielsweise panelDraw nennen. Stellen Sie sicher, dass panelArea vorne ist. Ich habe das ausgepeitscht und es hat das Flackern beseitigt, aber die Form, die gezeichnet wurde, ist verschmiert, so dass es auch keine vollständige Lösung ist.

Eine transparente Tafel kann erstellt werden, indem einige Malaktionen der ursprünglichen Tafel überschrieben werden:

public class ClearPanel : Panel
{
    public ClearPanel(){}

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams createParams = base.CreateParams;
            createParams.ExStyle |= 0x00000020;
            return createParams;
        }
    }

    protected override void OnPaintBackground(PaintEventArgs e){}
}

Die Idee ist, das Zeichnen der temporären Form während des MouseMove-Ereignisses der 'panelArea' zu handhaben und NUR das 'panelDraw' des MouseUp-Ereignisses neu zu malen.

// Use the panelDraw paint event to draw shapes that are done
void panelDraw_Paint(object sender, PaintEventArgs e)
{
    Graphics g = panelDraw.CreateGraphics();

    foreach (Rectangle shape in listOfShapes)
    {
        shape.Draw(g);
    }
}

// Use the panelArea_paint event to update the new shape-dragging...
private void panelArea_Paint(object sender, PaintEventArgs e)
{
    Graphics g = panelArea.CreateGraphics();

    if (drawSETPaint == true)
    {
        Pen p = new Pen(Color.Blue);
        p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;

        if (IsShapeRectangle == true)
        {
            g.DrawRectangle(p, rect);
        }
        else if (IsShapeCircle == true)
        {
            g.DrawEllipse(p, rect);
        }
        else if (IsShapeLine == true)
        {
            g.DrawLine(p, startPoint, endPoint);
        }
    }
}

private void panelArea_MouseUp(object sender, MouseEventArgs e)
{

    endPoint.X = e.X;
    endPoint.Y = e.Y;

    drawSETPaint = false;

    if (rect.Width > 0 && rect.Height > 0)
    {
        if (IsShapeRectangle == true)
        {
            listOfShapes.Add(new TheRectangles(rect, currentColor, currentBoarderColor, brushThickness));
        }
        else if (IsShapeCircle == true)
        {
            listOfShapes.Add(new TheCircles(rect, currentColor, currentBoarderColor, brushThickness));
        }
        else if (IsShapeLine == true)
        {
            listOfShapes.Add(new TheLines(startPoint, endPoint, currentColor, currentBoarderColor, brushThickness));
        }

        panelArea.Invalidate();
    }

    panelDraw.Invalidate();
}
Tom
quelle
3

Ich würde empfehlen, OnPaintBackground zu überschreiben und den Hintergrund selbst zu löschen. Wenn Sie wissen, dass Sie das gesamte Steuerelement malen, können Sie in OnPaintBackground nichts tun (rufen Sie nicht die Basismethode auf), und es wird verhindert, dass die Hintergrundfarbe zuerst gezeichnet wird

Matt
quelle
1
Nachdem Sie Ihre Frage erneut gelesen haben, wird dies wahrscheinlich nicht helfen ... außer dass Sie möglicherweise ein Unterklassenfeld vorschlagen und es Ihnen ermöglichen, OnPaint und OnPaintBackground zu überschreiben und dort zu zeichnen ...
Matt
3

Ich weiß, dass dies eine wirklich alte Frage ist, aber vielleicht findet es jemand nützlich.
Ich möchte die Antwort der Viper kaum verbessern.

Sie können die Panel-Klasse einfach erweitern und die Einstellungseigenschaft durch Reflektion ausblenden.

public static class MyExtensions {

    public static void SetDoubleBuffered(this Panel panel) {
        typeof(Panel).InvokeMember(
           "DoubleBuffered",
           BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
           null,
           panel,
           new object[] { true });
    }
}

Wenn der Name Ihrer Panel-Variablen myPanel ist, können Sie einfach
myPanel.SetDoubleBuffered () aufrufen .
und das ist es. Code sieht viel sauberer aus.

Thorgil
quelle
3

In diesem Zustand müssen Sie den Doppelpuffer aktivieren. Öffnen Sie das aktuelle Formular, gehen Sie zu den Formulareigenschaften und wenden Sie den doppelten Puffer true an. oder Sie können diesen Code auch schreiben.

this.DoubleBuffered = true;     

In Form laden.


quelle
1

Hier ist das Programm zum Bewegen von Kreisen in .net, das nicht flackert.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
namespace CircleMove
{
    /// <summary>
    /// Description of MainForm.
    /// </summary>
    public partial class MainForm : Form
    {
        int x=0,y=0;
        Thread t;

        public MainForm()
        {

            //
            // The InitializeComponent() call is required for Windows Forms designer support.
            //
            InitializeComponent();

            //
            // TODO: Add constructor code after the InitializeComponent() call.
            //
        }
        void MainFormPaint(object sender, PaintEventArgs e)
        {
            Graphics g=e.Graphics;
            Pen p=new Pen(Color.Orange);
            Brush b=new SolidBrush(Color.Red);
        //  g.FillRectangle(b,0,0,100,100);
            g.FillEllipse(b,x,y,100,100);
        }
        void MainFormLoad(object sender, EventArgs e)
        {
            t=new Thread(  new ThreadStart(

                ()=>{
                    while(true)
                    {
                        Thread.Sleep(10);
                        x++;y++;
                        this.Invoke(new Action(
                            ()=>{

                                this.Refresh();
                                this.Invalidate();
                                this.DoubleBuffered=true;
                                }
                                            )
                                        );
                    }
                    }
                                            )

                        );

            t.Start();
        }
    }
}
Sanjay
quelle
1

Es ist eine alte Frage, aber um ganz zu sein: Es gibt noch eine andere Lösung, die bei mir funktioniert hat, bei der die Doppelpufferung nicht funktioniert hat.

Wie sich herausstellt, bietet Microsoft die BufferedGraphics- Klasse als Lösung an. Das Schöne an dieser Klasse ist, dass Sie damit ein Grafikobjekt in ein anderes kopieren können. Abgesehen davon, dass Sie ein temporäres Grafikobjekt einrichten und es schließlich an das endgültige Ziel kopieren, können Sie so ziemlich denselben Code verwenden, den Sie wann erstellt hätten Das Flackern sollte kein Problem gewesen sein:

private void Indicator_Paint(object sender, PaintEventArgs e)
{
    Control pbIndicator = (Control)sender;
    Rectangle targetRect = pbIndicator.ClientRectangle;

    Image img = Bitmap.FromFile("bitmap.bmp");

    BufferedGraphicsContext ctx = new BufferedGraphicsContext();
    BufferedGraphics bg = ctx.Allocate(e.Graphics, targetRect);

    // Do the graphic stuff 
    bg.Graphics.Clear(this.BackColor);
    bg.Graphics.DrawImage(img, 0, 0);
    // etcetera

    bg.Render(e.Graphics);
    bg.Dispose();
    ctx.Dispose();
}

Nachteil dieser Lösung, dass es Ihren Code überladen könnte. Außerdem bin ich mir nicht sicher, ob es eine gute Idee ist, den Kontext jedes Mal einzurichten, oder ob es ausreichen würde, einen im Voraus zu erstellen und diesen Kontext weiterhin zu verwenden.

Weitere Informationen finden Sie unter https://docs.microsoft.com/en-us/dotnet/api/system.drawing.bufferedgraphicscontext?view=dotnet-plat-ext-3.1

Frank den Blaauwen
quelle
0

Wenn der Speicher knapp ist (Sie möchten also nicht die Speicherkosten für die Doppelpufferung), können Sie das Flimmern möglicherweise reduzieren, aber nicht beseitigen, indem Sie die Hintergrundfarbe auf die dominierende Farbe in Ihrer aktuellen Szene einstellen.

Warum dies hilft: Flimmern ist ein kurzes Aufblitzen der Hintergrundfarbe, die das Betriebssystem zeichnet, bevor untergeordnete Steuerelemente oder Ihr benutzerdefinierter Zeichencode gezeichnet werden. Wenn dieser Blitz eine Farbe ist, die näher an der endgültigen anzuzeigenden Farbe liegt, fällt er weniger auf.

Wenn Sie sich nicht sicher sind, mit welcher Farbe Sie beginnen sollen, beginnen Sie mit 50% Grau, da dies ein Durchschnitt von Schwarzweiß ist und daher den meisten Farben in Ihrer Szene näher kommt.

myFormOrControl.BackColor = Color.Gray;
ToolmakerSteve
quelle
0

Versuchen Sie, die Zeichnungslogik in die aktuellen Formulare einzufügen

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
}

Methode. In diesem Fall sollten Sie den Parameter e verwenden, um das Grafikobjekt abzurufen. Verwenden Sie die Eigenschaft e.Graphics. Dann sollten Sie die Invalidate () -Methode für dieses Formular aufrufen, wenn das Formular neu gezeichnet werden muss. PS: DoubleBuffered muss auf true gesetzt sein.

DeeDee
quelle
0

tun Sie einfach, this.Refresh()wenn das Formular angezeigt wird.

Marmelade
quelle
Entschuldigung? Dies beantwortet die Frage nicht.
Momoro
0

Das Zeichnen auf ein Etikett anstelle eines Panels löste das Problem für mich.

Sie müssen weder DoubleBuffering noch etwas anderes verwenden.

Sie können den Text von der Beschriftung entfernen, AutoSize auf false setzen, ihn dann andocken oder die Größe festlegen und ihn wie für das Bedienfeld verwenden.

Die besten Wünsche,

ThrowNewRandomException
quelle
Hinweis: Eine ArgumentException wird ausgelöst, nachdem Dispose () für das Graphics-Objekt aus PaintEventArgs aufgerufen wurde. Dies geschieht, wenn das Label das erste Steuerelement (höchster Ordnung) im übergeordneten Element ist.
ThrowNewRandomException
-2

Können Sie versuchen, mit einem Timer und einem Booleschen Wert zu überprüfen, ob die Maus gedrückt ist, und an dieser Stelle malen, indem Sie erneut eine Variable verwenden, um zu überprüfen, ob der Benutzer seine Maus bewegt hat, ob diese Stelle auch bewegt wurde usw.

Oder überprüfen Sie einfach mit einem Timer, ob die Maus gedrückt ist (über einen Booleschen Wert, der bei gedrückter Maus auf true gesetzt ist), und malen Sie ihn, wenn Sie wahrscheinlich nur ein Pixel malen möchten , nicht als hätten Sie Schatten usw. Anstatt die eigentliche Maus zu verwenden. Sie überprüfen also alle 1 Sekunde anstelle von 0,0001 und es flackert nicht. Oder versuchen Sie es umgekehrt mit Ihren eigenen Zeiten.

Sturmschildkröte
quelle
1
Flimmern tritt auf, wenn die Hintergrundfarbe (normalerweise Weiß) eines Formulars oder Steuerelements gezeichnet wird und dann Ihr benutzerdefinierter Code ausgeführt wird, um den betroffenen Bereich neu zu zeichnen. Das "Flimmern" ist ein kurzes Aufblitzen der Hintergrundfarbe. Das Lösen von Flimmern erfordert eine doppelte Pufferung, sodass das System über einen Ort verfügt, an dem der gewünschte Inhalt wiederhergestellt werden kann, anstatt die Hintergrundfarbe zu zeichnen. Das Setzen Ihres Zeichnungscodes auf einen Timer ist schlimmer als nichts zu tun (CPU-Zyklen ohne Nutzen zu verbrauchen). Verlassen Sie sich auf das Betriebssystem, um zu erfahren, wann Sie zeichnen müssen. Versuchen Sie nicht, es zu überlisten.
ToolmakerSteve