1

質問: OnPaint() メソッド以外のメソッドから winform に適切に描画するにはどうすればよいですか?

追加情報: 私が今持っているコードは、OnPaint() メソッドで TicTacToe ゲームの背景線をいくつか描画します。次に、Mouse_Click イベントを使用して、明らかに適切ではないこのコードを実行しています。

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

理由がわかりませんが、円を描画しますが、フォームを最小化または画面外に移動すると、円は消去されますが、OnPaint() メソッドからの線は消去されません。

4

3 に答える 3

2

問題は、作成者がそのようなメモリを提供しない限り、Windows ウィンドウ (WinForms を含む) には独自のグラフィック メモリがなく、その特定のウィンドウが上書きまたは非表示になり、最終的に再描画が必要になるのは時間の問題です。あなたは画面に絵を描いています (と言うかもしれません)。他の人も同じことができます。信頼できる唯一の規則は、必要に応じて OnPaint が呼び出されるということです。基本的には、自分の哲学を使用して、必要なときにいつでも描くことができます (不可思議で予測不可能なスケジュールではありません)。そのためには、私のソリューションをチェックしてください。

次のような「バックバッファ ビットマップ」を使用する必要があります。

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);
}

それを試してみてください。それはそれを行う必要があります:)

于 2013-02-24T22:35:32.643 に答える
2

あなたは多くの「ビュー」を行っていますが、「モデル」は行っていません。

形状を作成する場合、マウス ボタンが上下に移動したときに、形状を表す DATA を作成します。

データ構造は永続的な情報を表します (これは、セッション間でこの情報を保存およびロードできるようにするデータです)。

ペイント関数で行う必要があるのは、DATA 構造を調べてペイントすることだけです。したがって、これはサイズ変更/非表示/表示の間で持続します。

于 2013-02-24T22:45:14.643 に答える
1

あなたがしているのは、(OnPaint メソッドから) 「非同期に」フォームに描画することです。ご覧のとおり、OnPaint メソッドは、Windows フォームがフォーム全体を描画するために依存しているものです。From に何かが起こると無効になり、OnPaint が再度呼び出されます。そのメソッドで何かが描画されない場合、それが起こった後はそこにはありません。

ボタンで何かを永続的に表示したい場合は、そのオブジェクトをどこかのコレクションに追加するか、それに関連する変数を設定する必要があります。次に、Invalidate() と Update() を呼び出す Refresh() を呼び出します。次に、OnPaint 中に、そのオブジェクト (ellipis) を描画します。

最小化など、フォームに何かが起こった後もそれを残しておきたい場合は、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);
        }
    }
}
于 2013-02-24T22:30:54.217 に答える