我有一个SplitContainer(确切地说是一个NonFlickerSplitContainer)并且我将它们的两个面板视为一个要绘制的画布。我使用Graphics.DrawImage方法分别在面板上绘制位图。我首先刷新Panel1,然后刷新Panel2,导致垂直/水平撕裂 - 绘制Panel1结束,然后绘制Panel2开始 - 这就是原因。什么是我的问题的解决方案?我使用splitContainer作为具有前/后功能的“位图视频流”的输出。也许我可以以某种方式冻结UI,直到Panel2_Paint结束?
private void splitContainer_Panel1_Paint(object sender, PaintEventArgs e)
{
if (frameA != null)
{
if (ORIGINAL_SIZE_SET)
e.Graphics.DrawImage(frameA, 0, 0);
else
e.Graphics.DrawImage(frameA, 0, 0, ClientSize.Width, ClientSize.Height);
}
}
private void splitContainer_Panel2_Paint(object sender, PaintEventArgs e)
{
if (frameB != null)
{
//...
if (ORIGINAL_SIZE_SET)
e.Graphics.DrawImage(frameB, x, y);
else
e.Graphics.DrawImage(frameB, x, y, ClientSize.Width, ClientSize.Height);
}
}
private Bitmap frameA = null;
private Bitmap frameB = null;
private void RefreshOutput(bool refreshClipA = true, bool refreshClipB = true)
{
if (refreshClipA)
{
frameA = GetVideoFrame(...);
//...
}
if (refreshClipB)
{
frameB = GetVideoFrame(...);
//...
}
if (refreshClipA)
splitContainer.Panel1.Refresh();
if (refreshClipB)
splitContainer.Panel2.Refresh();
}
答案 0 :(得分:0)
也许我可以以某种方式冻结UI,直到Panel2_Paint结束?
看看:https://msdn.microsoft.com/en-us/library/system.windows.forms.control.suspendlayout(v=vs.110).aspx
在您的控件上调用SuspendLayout(),执行所有图形操作,然后调用ResumeLayout()一次更新所有内容。该文档中有一个例子。
如果您的绘图操作花费的时间太长,那么临时图形工件将开始出现在“冻结”区域中,直到ResumeLayout()之后。
答案 1 :(得分:0)
从链接:
使控件的特定区域无效并导致将油漆消息发送到控件。 (可选)使分配给控件的子控件无效。
因此,不要单独使每个面板无效,只需调用此方法一次,它应该执行您想要的操作。或者只修改一下代码:
if (refreshClipA && refreshClipB)
{
splitContainer.Invalidate(true);
}
else
{
if (refreshClipA)
{
splitContainer.Panel1.Refresh();
}
else if (refreshClipB)
{
splitContainer.Panel2.Refresh();
}
}
基本上我正在做的是如果他们两个都需要重新绘制,让splitContainer
处理它,否则单独检查每一个并在必要时绘制。
来自@ DonBoitnott的评论,而不是使用文档中的Invalidate(true)
使用SplitContainer.Invalidate(bool invalidate Children)
:
强制控件使其客户区无效并立即重绘自身和任何子控件。
所以只需将splitContainer.Invalidate(true)
更改为splitContainer.Refresh()
。
答案 2 :(得分:0)
我经历过,无法确保两个单独的panel.Paint()事件在同一时刻完成,至少不会在WinForms项目中完成。对我有用的唯一解决方案是DonBoitnott的建议。我现在使用单个面板并模拟splitcontainer行为。
如果我回答这个问题,我建议你放弃拆分容器并渲染到单个表面,这样你总是在一个Paint事件中,你只需将其分开并相应地绘制。 - DonBoitnott 2016年2月17日17:51