2016-06-30 1 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에서 작동하는 방식, 양식이 덮여 있거나 밝혀지지 않은/크기가 조정 된/etc 때마다 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로 설정되어 있는지 확인하십시오.

관련 문제