为什么Windows窗体控件的属性不能在OnPaint事件期间更改?

本文关键字:事件 OnPaint 窗体 Windows 控件 不能 属性 为什么 | 更新日期: 2023-09-27 18:09:13

我使用OnPaint (c#)事件在我的窗体中绘制一些东西。我想在OnPaint过程中获得变量的值。但是我不能得到它,只有在OnPaint过程之前或之后…

实际上,这个变量就像一个计数器,我想要得到它来增加ProgressBar的值。

我试着添加一个线程,一个定时器和"ValueChanged"事件,我仍然无法获得值。代码相当长(用于从一些数据生成热图)。

我在事件期间增加了一些for循环的值,并通过"Invalidate()"函数调用OnPaint事件。

我希望不要粘贴我的代码(它很长)!谢谢。

(简化)
public partial class HeatPainter : UserControl
{
    public long _progress = 0; //My counter
    public HeatPainter()
    {
        InitializeComponent();
    }
    public void DrawHeatMap(List<List<int>> Items, decimal Value, int MaxStacks, int Factor, string FileName)
    {
        if (_allowPaint) //If the control is ready to process
        {
            timer1.Start();
            _progress = 0;
            _allowPaint = false;
            Invalidate();
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        for (int Pass = _factor; Pass >= 0; Pass--)
        {
            //Some draw stuff
            //...
            _progress++;
        }
     }
     private void timer1_Tick(object sender, EventArgs e)
    {
        Console.WriteLine(_progress);
    }
}

为什么Windows窗体控件的属性不能在OnPaint事件期间更改?

看起来你的重新粉刷花了很多时间。在重新绘制期间,您无法更改表单上的任何内容(直到最后才会更改)。

所以你应该从另一个角度来看这个任务。如果您将在并行线程(或另一个并行化结构http://www.dotnetperls.com/backgroundworker)中创建图像(如如何使用。net在内存中动态创建jpg图像?)绘制完成后,将其设置为背景或某些PictureBox的.Image。表单将一直响应。

你将不得不同步(更新你的进度条),但这并不是一个困难的任务(线程不更新进度条控件- c#, c# Windows窗体应用程序-从另一个线程和类更新GUI ?)。

对于未来:线程和后台工作者正在慢慢远离。网络世界。它们仍然在。net &lt中使用。但是。net 4.0及更高版本为异步操作提供了更好的抽象。我建议你阅读task和Async Await。它们更适合于许多"启动-工作-完成-结果"的场景。

你应该只使用一个异步构造(例如BackgroundWorker)来绘制图像。您的用户控件应该提供一个事件(实际上最好在用户界面之外重构此功能),例如

public event EventHandler ProgressChanged;

,并在修改Progress的属性时在创建图像的代码中引发此事件。只是不要忘记同步和调度(见上文)。