C#:Windows窗体:可能会导致Invalidate()不重绘?

我正在使用 Windows窗体.很长一段时间,pictureBox.Invalidate();努力使屏幕重绘.但是,现在不行,我不知道为什么.
this.worldBox = new System.Windows.Forms.PictureBox();
this.worldBox.BackColor = System.Drawing.SystemColors.Control;
this.worldBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.worldBox.Location = new System.Drawing.Point(170,82);
this.worldBox.Name = "worldBox";
this.worldBox.Size = new System.Drawing.Size(261,250);
this.worldBox.TabIndex = 0;
this.worldBox.TabStop = false;
this.worldBox.MouseMove += new 
    System.Windows.Forms.MouseEventHandler(this.worldBox_MouseMove);
this.worldBox.MouseDown += new 
    System.Windows.Forms.MouseEventHandler(this.worldBox_MouseDown);
this.worldBox.MouseUp += new 
    System.Windows.Forms.MouseEventHandler(this.worldBox_MouseUp);

在我的代码中被称为适当地画出世界:

view.DrawWorldBox(worldBox,canvas,gameEngine.GameObjectManager.Controllers,selectedGameObjects,LevelEditorUtils.PREVIEWS);

View.DrawWorldBox

public void DrawWorldBox(PictureBox worldBox,Panel canvas,ICollection<IGameObjectController> controllers,ICollection<IGameObjectController> selectedGameObjects,IDictionary<string,Image> previews)
{
    int left = Math.Abs(worldBox.Location.X);
    int top = Math.Abs(worldBox.Location.Y);
    Rectangle screenRect = new Rectangle(left,top,canvas.Width,canvas.Height);

    IDictionary<float,ICollection<IGameObjectController>> layers = 
        LevelEditorUtils.LayersOfControllers(controllers);
    IOrderedEnumerable<keyvaluePair<float,ICollection<IGameObjectController>>> sortedLayers 
            = from item in layers
              orderby item.Key descending
              select item;

    using (Graphics g = Graphics.FromImage(worldBox.Image))
    {
        foreach (keyvaluePair<float,ICollection<IGameObjectController>> 
        kv in sortedLayers)
        {
            foreach (IGameObjectController controller in kv.Value)
            {
                // ...

                float scale = controller.View.Scale;
                float width = controller.View.Width;
                float height = controller.View.Height;
                Rectangle controllerRect = new 
                    Rectangle((int)controller.Model.Position.X,(int)controller.Model.Position.Y,(int)(width * scale),(int)(height * scale));

                // cull objects that aren't intersecting with the canvas
                if (controllerRect.IntersectsWith(screenRect))
                {
                    Image img = previews[controller.Model.HumanReadableName];
                    g.DrawImage(img,controllerRect);
                }

                if (selectedGameObjects.Contains(controller))
                {
                    selectionRectangles.Add(controllerRect);
                }
            }
        }
        foreach (Rectangle rect in selectionRectangles)
        {
            g.DrawRectangle(drawingPen,rect);
        }
        selectionRectangles.Clear();
    }
    worldBox.Invalidate();
}

在这里我可以做错什么

解决方法

要理解这一点,您必须对操作系统级别的工作方式有所了解.

Windows控件是为响应WM_PAINT消息而绘制的.当他们收到这个消息时,他们绘制自己的哪一部分已经被无效.特定控制可以被无效,并且控制的特定区域可以被无效,这一切都是为了尽量减少重新绘制的量.

最终,Windows会看到一些控件需要重画,并向他们发出WM_PAINT消息.但是,只有在处理完所有其他消息后才能执行此操作,这意味着Invalidate不会强制立即重绘.在技​​术上刷新应该,但并不总是可靠的. (更新:这是因为刷新是虚拟的,并且有一些控件在野外覆盖此方法与不正确的实现.)

有一种方法通过发出WM_PAINT消息强制立即绘制,即Control.Update.所以如果要强制立即重画,您可以使用:

control.Invalidate();
control.Update();

即使UI仍在处理消息,这将始终重绘控件,无论发生了什么.从字面上来说,我相信它使用SendMessage API而不是PostMessage,它强制绘画同步完成,而不是在长消息队列的末尾将它们折腾.

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...