C# 如何更改选项卡控件上的图像而不闪烁
C# 如何更改选项卡控件上的图像而不闪烁,c#,tabcontrol,C#,Tabcontrol,我在C#tab控件的标题上放置了一个图像。我想在光标悬停在图像上时更改图像。 现在我调用Control.Refresh方法,如下所示: TabControl tabControl1 = new TabControl(); [...] private void tabControl1_MouseMove(object sender, MouseEventArgs e) { [...] tabControl1.Refresh(); } private void tabControl
我在C#tab控件的标题上放置了一个图像。我想在光标悬停在图像上时更改图像。
现在我调用Control.Refresh方法,如下所示:
TabControl tabControl1 = new TabControl();
[...]
private void tabControl1_MouseMove(object sender, MouseEventArgs e)
{
[...]
tabControl1.Refresh();
}
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
e.Graphics.DrawImage(imagefile, arg1, arg2, arg3, arg4);
[...]
}
通过使用标志,当光标即将放在图像上并离开图像时,将调用Refresh方法,也就是说,一行中不会多次调用Refresh方法。通过这种方式,图像成功更改,但经常闪烁。
如何更改它而不闪烁?有什么想法吗?你需要双缓冲区 “双缓冲区是一种技术,我们将所有图形需要绘制到存储在内存(缓冲区)中的图像上,完成所有绘制需要后,我们将从内存中绘制一个完整的图像到屏幕上。这将图形集中到屏幕上(一种严重影响应用程序性能的操作)只进行一次操作,而不是多次小操作。”
请参见此操作需要双缓冲区 “双缓冲区是一种技术,我们将所有图形需要绘制到存储在内存(缓冲区)中的图像上,完成所有绘制需要后,我们将从内存中绘制一个完整的图像到屏幕上。这将图形集中到屏幕上(一种严重影响应用程序性能的操作)只进行一次操作,而不是多次小操作。”
请参见
选项卡控件
是一种特殊的控件,不能在其上启用双缓冲。这是因为它要求活动选项卡的所有子元素将自己绘制到其内容上。不幸的是,这也会影响选项卡,即使您不想自定义页面图形,而只想自定义选项卡
但是,您可以使用一些技巧来最小化闪烁:
1。切勿使用Refresh()
Refresh()
方法强制立即重新绘制整个控件,无论您此刻正在做什么。相反,使用Invalidate
将控件标记为无效,以便在专用刷新会话中将其与其他无效控件一起重新绘制
2。使完整的表单双缓冲
虽然TabControl
不支持双缓冲,但是您可以将整个表单
进行双缓冲,这样可以减少闪烁
只需在表单中重写CreateParams
,即可:
private const int WS_EX_COMPOSITED = 0x02000000;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= WS_EX_COMPOSITED;
return cp;
}
}
3。仅使无效区域无效
如果使整个选项卡控件无效
,它将与其子项一起完全重新绘制。但是您希望使选项卡中的一些16x16像素矩形无效,这样就可以避免刷新整个控件
private int hoveredIndex = -1;
private Size imageSize = new Size(16, 16);
private void TabControl1_MouseMove(object sender, MouseEventArgs e)
{
for (int i = 0; i < tabControl1.TabPages.Count; i++)
{
Rectangle rect = tabControl1.GetTabRect(i);
Rectangle closeButton = GetImageLocation(rect);
if (closeButton.Contains(e.Location))
{
if (hoveredIndex != i)
{
hoveredIndex = i;
tabControl1.Invalidate(rect);
}
}
else if (hoveredIndex == i)
{
tabControl1.Invalidate(tabControl1.GetTabRect(hoveredIndex));
hoveredIndex = -1;
}
}
}
private void TabControl1_MouseLeave(object sender, EventArgs e)
{
if (hoveredIndex != -1)
{
tabControl1.Invalidate(tabControl1.GetTabRect(hoveredIndex));
hoveredIndex = -1;
}
}
private Rectangle GetImageLocation(Rectangle rect)
{
return new Rectangle(rect.Right - imageSize.Width, rect.Top, imageSize.Width, imageSize.Height);
}
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
Image image = e.Index == hoveredIndex ? imageHovered : imageNormal;
e.Graphics.DrawImage(image, GetImageLocation(e.Bounds));
}
private int hoveredIndex=-1;
私有大小imageSize=新大小(16,16);
私有无效选项卡控件1\u MouseMove(对象发送方,MouseEventArgs e)
{
对于(int i=0;i
TabControl
是一种特殊的控件,您不能在其上启用双缓冲。这是因为它要求活动选项卡的所有子元素将自己绘制到其内容上。不幸的是,这也会影响选项卡,即使您不想自定义页面图形,而只想自定义选项卡
但是,您可以使用一些技巧来最小化闪烁:
1。切勿使用Refresh()
Refresh()
方法强制立即重新绘制整个控件,无论您此刻正在做什么。相反,使用Invalidate
将控件标记为无效,以便在专用刷新会话中将其与其他无效控件一起重新绘制
2。使完整的表单双缓冲
虽然TabControl
不支持双缓冲,但是您可以将整个表单
进行双缓冲,这样可以减少闪烁
只需在表单中重写CreateParams
,即可:
private const int WS_EX_COMPOSITED = 0x02000000;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= WS_EX_COMPOSITED;
return cp;
}
}
3。仅使无效区域无效
如果使整个选项卡控件无效
,它将与其子项一起完全重新绘制。但是您希望使选项卡中的一些16x16像素矩形无效,这样就可以避免刷新整个控件
private int hoveredIndex = -1;
private Size imageSize = new Size(16, 16);
private void TabControl1_MouseMove(object sender, MouseEventArgs e)
{
for (int i = 0; i < tabControl1.TabPages.Count; i++)
{
Rectangle rect = tabControl1.GetTabRect(i);
Rectangle closeButton = GetImageLocation(rect);
if (closeButton.Contains(e.Location))
{
if (hoveredIndex != i)
{
hoveredIndex = i;
tabControl1.Invalidate(rect);
}
}
else if (hoveredIndex == i)
{
tabControl1.Invalidate(tabControl1.GetTabRect(hoveredIndex));
hoveredIndex = -1;
}
}
}
private void TabControl1_MouseLeave(object sender, EventArgs e)
{
if (hoveredIndex != -1)
{
tabControl1.Invalidate(tabControl1.GetTabRect(hoveredIndex));
hoveredIndex = -1;
}
}
private Rectangle GetImageLocation(Rectangle rect)
{
return new Rectangle(rect.Right - imageSize.Width, rect.Top, imageSize.Width, imageSize.Height);
}
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
Image image = e.Index == hoveredIndex ? imageHovered : imageNormal;
e.Graphics.DrawImage(image, GetImageLocation(e.Bounds));
}
private int hoveredIndex=-1;
私有大小imageSize=新大小(16,16);
私有无效选项卡控件1\u MouseMove(对象发送方,MouseEventArgs e)
{
对于(int i=0;i