Avatar billede superdude Nybegynder
08. oktober 2006 - 21:56 Der er 8 kommentarer og
1 løsning

Refresh() på Graphics object

Jeg har følgende kode (simplet ekesempel) som tegner nogle streger på en PictureBox control - kodeblokken bliver kaldt gentagne gange efter hinanden med intervaller på 1 sekund og effekten skulle gerne være at man ser èen streg der flytter sig:

using (Graphics g = pictureBox1.CreateGraphics())
{
  //g.Clear(Color.White);
  g.DrawLine(new Pen(Color.Black), 0, 0, DateTime.Now.Millisecond,100);
  pictureBox1.Refresh();
}

Men resultatet er at man ser flere streger samtidigt. Hvis jeg udkommenterer første linie i blokken fungere det efter hensigten, bortset fra at baggrunden i min PictureBox nu bliver hvid og dermed "sletter" det baggrunds-billede jeg har i PictureBoxen.

Jeg troede egentlig at en Refresh() på PictureBoxen ville slette "gamle" streger, men det virker ikke sådan. Hvad gør jeg galt her...?
Avatar billede superdude Nybegynder
08. oktober 2006 - 21:58 #1
Rettelse:
"Hvis jeg udkommenterer første linie..."
skal være
"Hvis jeg IKKE udkommenterer første linie..."
Avatar billede superdude Nybegynder
08. oktober 2006 - 23:33 #2
Det jeg egentlig savner er en måde at slette alt det man har tegnet med Graphics objektet (uden samtidig at male hele baggrunden). Troede lige at GraphicsState var løsningen, således at følgende kode ikke ville tegne den blå streg, men sådan virker det desværre ikke...

g.DrawLine(new Pen(Color.Red), 0, 0, DateTime.Now.Millisecond, 100);
GraphicsState state = g.Save();
g.DrawLine(new Pen(Color.Blue), 0, 100, DateTime.Now.Millisecond, 200);
g.Restore(state);
Avatar billede bulgroz Nybegynder
08. oktober 2006 - 23:53 #3
Når man kalder refresh, invalideres kontrollen og gentegnes.

Det du bør gøre er at override OnPaint hvorved du direkte har dit grafiske objekt. Følgende lille eksempel viser hvorledes du kan gøre. Her har jeg ladet en timer refreshe kontrollen i et interval. Kontrollen tegner blot en streg over det billede som er i PictureBoxen


namespace PictureBox
{
    using System;
    using System.Windows.Forms;
    using System.Drawing;

    class MyPictureBox : PictureBox
    {
        private Timer refreshTimer = new Timer();
        private int counter;

        public MyPictureBox()
        {
            this.DoubleBuffered = true;

            this.refreshTimer.Tick += new EventHandler(RefreshTimerTick);
            this.refreshTimer.Interval = 50;
            this.refreshTimer.Enabled = true;
        }

        protected override void OnPaint(PaintEventArgs paintEventArgs)
        {
            base.OnPaint(paintEventArgs);

            using (Pen pen = new Pen(Color.Magenta))
            {
                if (this.counter > paintEventArgs.ClipRectangle.Width)
                {
                    this.counter = 1;
                }

                Point p1 = new Point(this.counter, paintEventArgs.ClipRectangle.Y);
                Point p2 = new Point(this.counter, paintEventArgs.ClipRectangle.Y + paintEventArgs.ClipRectangle.Height);

                paintEventArgs.Graphics.DrawLine(pen, p1, p2);
            }
        }

        void RefreshTimerTick(object sender, EventArgs e)
        {
            this.counter ++;
            this.Refresh();
        }


    }
}
Avatar billede superdude Nybegynder
09. oktober 2006 - 18:53 #4
Den gentegner fint når jeg sætter doublebuffered til true, men så har min control ikke længere transparent baggrund. Når jeg sætter doublebuffered til false, er der transparent baggrund, men så gentegner kontrollen ikke sig selv. Hvorfor kan jeg ikke få begge dele... :-(

Jeg bruger følgende kode, tyvstjålet fra nettet, for at give min control transparent baggrund (men den knækker åbenbart når doublebuffered er sat til true):

protected override CreateParams CreateParams
{
    get
    {
          CreateParams cp = base.CreateParams;
          cp.ExStyle |= 0x20;
          return cp;
    }
}

       
protected override void OnPaintBackground(PaintEventArgs e)
{
    // do nothing           
}
Avatar billede superdude Nybegynder
09. oktober 2006 - 18:54 #5
... men mit nye problem med transparency er jo et helt andet issue, så smid et svar og du skal få points.
Avatar billede bulgroz Nybegynder
09. oktober 2006 - 23:52 #6
At sætte følgende styles i din constructor bør løse dit problem:

this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);

Øvrige styles kan med fordel sættes når du selv tegner din kontrol:
this.SetStyle(ControlStyles.DoubleBuffer, true); // Er det samme som at sætte this.DoubleBuffered = true;
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
Avatar billede superdude Nybegynder
10. oktober 2006 - 19:06 #7
Ja, jeg har prøvet disse men uden umiddelbar success. Men tak alligevel.
Avatar billede bulgroz Nybegynder
11. oktober 2006 - 06:17 #8
Så må der være noget andet galt i din kode. de styles er dem man normalt sætter når man selv tegner sin kontrol og vil have support for transparens.
Avatar billede superdude Nybegynder
11. oktober 2006 - 15:51 #9
Ja det kan jeg ikke afvise.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester