我正在使用
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,它强制绘画同步完成,而不是在长消息队列的末尾将它们折腾.