gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 08:20:14 25 4
gpt4 key购买 nike

我正在使用 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);

查看.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 不会强制立即重绘。 Refresh 技术上应该,但并不总是可靠的。 (更新:这是因为 Refresh虚拟的,并且有一些在野外使用不正确的实现覆盖此方法的控件。)

有一种方法确实通过发出WM_PAINT 消息强制立即绘制,这就是Control.Update。 .所以如果你想强制立即重绘,你可以使用:

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

这将始终重绘控件,无论发生什么情况,即使 UI 仍在处理消息也是如此。从字面上看,我相信它使用 SendMessage API 而不是 PostMessage 强制同步完成绘制,而不是将其扔到长消息队列的末尾。

关于C#:Windows 窗体:什么会导致 Invalidate() 不重绘?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2695608/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com