gpt4 book ai didi

c# - 自定义控件边框在调用 Update() 时不显示,但在调用 Refresh() 时显示

转载 作者:太空宇宙 更新时间:2023-11-03 10:40:24 25 4
gpt4 key购买 nike

我已经在自定义控件周围绘制了一个边框,但是现在当我尝试在绘制初始边框之后(甚至之前)在自定义控件内部绘制一个小矩形时,它不会绘制/显示在控件上当鼠标在控件上移动时。

我在 OnPaint 方法中放置了一个 Console.WriteLine(...) 以查看它是否被击中,但没有任何内容输出到控制台/输出 Pane 。它输出任何内容的唯一时间是 Control 首次加载时。但是如果点击了 else 子句,为什么当鼠标 移到 Control 上时小矩形没有被绘制?

您可以安全地忽略 Borders 区域内的任何内容,因此不会显示代码。

namespace JTS.Controls
{
public partial class ListBox : Control
{
public enum ListBoxBorders
{
Top,
Bottom,
Left,
Right,
All,
None
}

ListBoxBorders SelectedListBoxBorder = ListBoxBorders.All;

[Browsable(true)]
[Description("Defines which borders are drawn onto the ListBox."), Category("Appearance")]
public ListBoxBorders ListBoxBorder
{
get { return SelectedListBoxBorder; }
set { SelectedListBoxBorder = value; }
}

public enum BorderStyles
{
Top,
Bottom,
Left,
Right,
All,
None
}

Graphics graphics;

protected bool mouseMoving;

public ListBox()
{
InitializeComponent();
}

private void ListBox_MouseMove(object sender, MouseEventArgs e)
{
Console.WriteLine("Handled.");
mouseMoving = true;

this.Update(); // it works if Refresh is called
}

protected override void OnPaint(PaintEventArgs pe)
{
graphics = pe.Graphics;

#region Borders
// logic to draw right-edge border.
#endregion

if (mouseMoving)
{
// ************************************
// THIS PART NEVER GETS EXECUTED.
// ************************************
Console.WriteLine(mouseMoving.ToString());
graphics.DrawRectangle(new Pen(
Color.Green, 1), new Rectangle(
5, 5, 50, 50));
}
else
{
Console.WriteLine(mouseMoving.ToString());
}
}
}
}

编辑:在我将 this.Update 更改为 this.Refresh 之后,一切正常。谁能解释一下为什么?

最佳答案

您需要了解InvalidateUpdateRefresh 之间的区别和关系。这是一个very good blog关于它,偷懒的可以看看我的总结:)

简而言之:Invaidate使客户区无效,但从不更新Update将无效的客户区更新为新外观Refresh 本质上以调用结束 Invalidate 之后是 Update

现在让我们详细讨论一下。

在我们调查您的问题之前,让我们先了解一下 winforms 控件是如何绘制的。

所有控件绘制实际上对 WM_PAINT messages 的响应.作为简短的总结,此消息在以下条件下发送:

  • UpdateWindowRedrawWindow 被调用,或者
  • DispatchMessage 从消息队列中调度一个 WM_PAINT

当控件收到 WM_PAINT 消息时,如果需要,它会先绘制背景,然后再绘制前景,然后触发 OnPaint 事件以执行用户定义的自定义绘制.

有了背景,再说说InvalidateUpdateRefresh

Invalidate ... essentially ends up calling one of the RedrawWindow, InvaliateRect or InvalidateRgn functions. If RedrawWindow is called then this may result in a WM_PAINT message being posted to the application message queue (to invalidate the child controls).

但请注意,该函数只是通过将其添加到控件窗口的当前更新区域来“使”客户区“无效”或“变脏”。这个无效区域以及所有其他区域更新区域中的区域,在收到下一个 WM_PAINT 消息时被标记为绘画。因此,您可能不会看到您的控件立即(或同步)刷新(并显示失效)。

Update calls UpdateWindow function which updates the client area of the control by sending WM_PAINT message to the window (of the control) if the window's update region is not empty. This function sends a WM_PAINT directly to WndProc() bypassing the application message queue.

因此,如果窗口更新区域之前是“无效的”,那么调用“更新”将立即“更新”(并导致重新绘制)无效。

最后,Refresh 将上面的函数链接在一起:它调用 Invalidate 使该区域无效,然后调用 Update 强制刷新。

关于c# - 自定义控件边框在调用 Update() 时不显示,但在调用 Refresh() 时显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25532622/

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