2013-02-24 3 views
1

Вопрос: Как правильно рисовать winform методом, отличным от метода OnPaint()?C# Draw Line OnPaint() vs CreateGraphics()

Дополнительная информация: Код, который я сейчас рисую, имеет некоторые фоновые линии для игры TicTacToe в методе OnPaint(). Затем я использую событие Mouse_Click и бегаю этот код, по-видимому, не является собственно:

private void TicTacToe_MouseClick(object sender, MouseEventArgs e) 
    Graphics g = this.CreateGraphics(); 
    g.DrawEllipse(this.penRed, this.Rectangle); 

По причинам, которые я не понимаю, это не нарисовать круг, но при сворачивании или перемещении формы от экрана стирает круги но не строки из метода OnPaint().

ответ

1

Что вы делаете, это рисование формы «асинхронно» (из метода OnPaint). Вы видите, метод OnPaint - это то, на что опирается Windows Forms, чтобы нарисовать всю вашу форму. Когда что-то происходит с вашим От, оно недействительно, а OnPaint вызывается снова. Если что-то не нарисовано в этом методе, тогда оно не будет после этого.

Если вы хотите, чтобы кнопка запускала что-то, что бы отображалось надолго, тогда вам нужно добавить этот объект в коллекцию или установить переменную, связанную с ней. Затем вызовите Refresh(), который вызывает Invalidate() и Update() Затем во время OnPaint нарисуйте этот объект (эллипс).

Если вы хотите, чтобы он все еще находился там, когда что-то случалось с вашей формой, например, сведение к минимуму, вы должны нарисовать его во время OnPaint.

Вот мое предложение:

public partial class Form1 : Form 
{ 
    Rectangle r = Rectangle.Empty; 
    Pen redPen = new Pen(Color.Red); 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     r = new Rectangle(50, 50, 100, 100); 
     Refresh(); 
    } 

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

     if (r != Rectangle.Empty) 
     { 
      e.Graphics.DrawRectangle(redPen, r); 
     } 
    } 
} 
2

Проблема заключается в том, что Windows Windows (который включает в себя WinForms) не имеет графическую памяти самостоятельно, если их создатель не предоставляет такую ​​память, и это лишь вопрос времени, прежде чем, что особенно window wilk переписываются или скрываются и в конечном итоге должны быть перекрашены. Вы рисуете на экране (вы можете сказать), и другие могут сделать то же самое. Единственное соглашение, на которое вы можете положиться, это то, что OnPaint будет вызван, когда потребуется. В принципе, хорошо использовать свою философию и рисовать всякий раз, когда вам нужно (не на каком-то грязном и непредсказуемом графике). Для этого проверьте мое решение.

Вы должны использовать "BackBuffer точечный рисунок", как:

private Bitmap bb; 

protected override void OnResize(EventArgs e) { 
    this.bb = new Bitmap(this.ClientSize.Width, this.ClientSize.Height); 
    this.InitBackBuffer(); 
} 
private void InitBackBuffer() { 
    using (var g = Graphics.FromImage(this.bb)) { 
    // do any of the "non dissapearing line" drawing here 
    } 
} 

private void TicTacToe_MouseClick(object sender, MouseEventArgs e) 
    using (Graphics g = Graphics.FromImage(this.bb)) 
    g.DrawEllipse(this.penRed, this.Rectangle); 
    this.Invalidate(); 
} 

protected override void OnPaint(PaintEventArgs e) { 
    base.OnPaint(e); 
    e.Graphics.DrawImageUnscaled(this.bb); 
} 

Попробуйте это. Это должно сделать это :)

2

Вы занимаетесь «просмотром», но не «моделью».

Если вы хотите создать фигуру, когда кнопка мыши идет вниз/вверх, создайте несколько ДАННЫХ, представляющих форму.

Ваши структуры данных представляют собой постоянную информацию (это данные, которые позволяют сохранять и загружать эту информацию между сеансами).

Все, что вам нужно сделать, это посмотреть на структуры DATA и нарисовать их. Поэтому это будет сохраняться между калибровкой/скрытием/показом.