2016-06-30 19 views
0

ゲージ(メートル)の固定グラフィックに可動針(ポインタ)を配置しようとしています。バッファされたグラフィックス上でマトリックス回転を使用して針を動かす。私は固定グラフィックと針を表示することができます。しかし、画面にレンダリングすると、最後に配置されたイメージが前のグラフィックを削除します。私は針のアニメーションを取得するためにタイマーを使用しており、動きを生成するためにトラックバーの入力を使用しています。針は私が探している正確な動きをします。バッファリングされた行列回転グラフィックを固定画像に配置

私は固定された背景と針を同時に表示することはできません。

アイデア?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Drawing.Drawing2D; 
using System.Globalization; 
using System.Linq; 
using System.Reflection; 
using System.Resources; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

namespace Dial01 
{ 
    public partial class dial01Form : Form 
    { 
     // Establishes timer for graphics animation 

     private Timer timer01 = new Timer(); 

     /* Establishes a graphic buffer to write to 
     * prior display on screen */ 

     private Graphics myGraphics; 
     private BufferedGraphics myBufferedGraphics1; 

     // Establishes manager for embedded resources (Images) 
     private System.Resources.ResourceManager myRM = new 
      System.Resources.ResourceManager("Resources.resx", 
      System.Reflection.Assembly.GetExecutingAssembly()); 

     int y = 0;  // Rotation value 
     Graphics g,g1;  // Graphics objects 

     public dial01Form() 
     { 
      // Establishes size of Dial01Form 
      this.Width = 500; 
      this.Height = 500; 

      // Gets reference to the current BufferedGraphicsContext 
      BufferedGraphicsContext myContext1 = BufferedGraphicsManager.Current; 

      // Specifically sets maximum buffer size 
      myContext1.MaximumBuffer = new Size(this.Width + 1, this.Height + 1); 

      // Sets the buffer size 
      myBufferedGraphics1 = myContext1.Allocate(this.CreateGraphics(), 
       new Rectangle(0, 0, this.Width, this.Height)); 


      // Actvates timer and sets interval 
      timer01.Enabled = true; 
      timer01.Tick += onTimer; 
      timer01.Interval = 20; 
      timer01.Start(); 

      // Initializes form components 
      InitializeComponent(); 
     } 

     private void onTimer(object sender, System.EventArgs e) 
     { 
      myGraphics = this.CreateGraphics(); 

      // Initializes graphics buffer variable 
      g1 = myBufferedGraphics1.Graphics; 

      // Clears graphic buffer with a color 
      g1.Clear(SystemColors.Control); 


      // Initializes an image variable for Dial Outline 
      Image dial01Outline = Dial01.Properties.Resources.DialOutline250x250; 

      // Draw Dial Outline to graphics buffer 
      myGraphics.DrawImage(dial01Outline, (ClientSize.Width/2) - 100, 
       (ClientSize.Height/2) - 100); 

      // Goto drawPointer method passing trackBar1 value 
      drawPointer(trackBar1.Value); 


      // Render buffered graphics to screen 
      // myBufferedGraphics.Render(Graphics.FromHwnd(this.Handle)); 
      myBufferedGraphics1.Render();   

     } 

     public int drawPointer(int trkBarValue) 
     { 
      int x = trkBarValue; 
      y = 0; 
      if (225 + x <= 360) { y = 222 + x; } 
      else if (225 + x > 360) { y = x - 135; } 

      // These two labels are for testing purposes 
      label1.Text = ("Trk Bar Val = " + x).ToString(); 
      label2.Text = ("Ptr value = " + y).ToString();   

      y = y + 180; 

      // Matrix rotation to pointer   
      Matrix myMatrix = new Matrix(); 
      myMatrix.Rotate(y, MatrixOrder.Append); 
      myMatrix.Translate(this.ClientSize.Width/2, 
       this.ClientSize.Height/2, MatrixOrder.Append); 
      g1.Transform = myMatrix; 


      // Pointer polygon 
      PointF point1 = new PointF(0.0F, 0.0F); 
      PointF point2 = new PointF(0.0F, 50.0F); 
      PointF point3 = new PointF(3.0F, 55.0F); 
      PointF point4 = new PointF(7.0F, 50.0F); 
      PointF point5 = new PointF(7.0F, 0.0F); 

      PointF[] polyPoints = 
      { 
       point1, 
       point2, 
       point3, 
       point4, 
       point5 
      }; 

      g1.FillPolygon(Brushes.Black, polyPoints); 


      return y; 
     } 


     private void dial01Form_Load(object sender, EventArgs e) 
     { 

     } 

     private void trackBar1_Scroll(object sender, EventArgs e) 
     { 


     } 
    } 
} 
+2

'CreateGraphics'を絶対に呼び出しません。 'OnPaint'を扱い、代わりに' e.Graphics'を使う必要があります。 – Blorgbeard

答えて

1

一般的なグラフィックス手法は、winformsアプリケーションには適していません。

フォームがwinformsで動作する方法、フォームが覆われているか、覆われていないか、サイズが変更されたときなど、Windowsはそれを再描画するように指示します。 CreateGraphicsで行ったことは、この時点で上書きされます。このため、CreateGraphicsに電話しないでください。

代わりに、Paintイベントを介して再描画プロセスをインターセプトし、そこにすべてのカスタムペイントを実行する必要があります。タイマーでまだ塗り直すことができます。タイマーの内部でInvalidate()を呼び出すだけで、できるだけ早くフォームが再描画されます。

これはそれを行うには「正しい方法」の一般的な形状である:

public partial class dial01Form : Form 
{ 
    private Timer timer01 = new Timer(); 

    int y = 0;  // Rotation value 

    public dial01Form() 
    { 
     // Establishes size of Dial01Form 
     this.Width = 500; 
     this.Height = 500; 

     // Actvates timer and sets interval 
     timer01.Enabled = true; 
     timer01.Tick += onTimer; 
     timer01.Interval = 20; 
     timer01.Start(); 

     // handle the paint event 
     this.Paint += OnPaint; 

     // Initializes form components 
     InitializeComponent(); 
    } 

    private void OnPaint(object sender, PaintEventArgs e) 
    { 
     // all painting here, targeting e.Graphics 
     e.Graphics.Clear(SystemColors.Control); 
     Image dial01Outline = Dial01.Properties.Resources.DialOutline250x250; 
     e.Graphics.DrawImage(dial01Outline, (ClientSize.Width/2) - 100, 
      (ClientSize.Height/2) - 100); 
     drawPointer(e.Graphics, trackBar1.Value); 
    } 

    private void onTimer(object sender, System.EventArgs e) 
    { 
     this.Invalidate(); 
    } 

    public int drawPointer(Graphics g1, int trkBarValue) 
    { 
     // elided: same code as before, but using the g1 parameter instead of a field 
    } 

} 

あなたがちらつきの問題を持つべきではない、と思う - ダブルバッファリングはデフォルトで有効になっています。フォームのDoubleBufferedプロパティがTrueに設定されていることを確認してください。