我注意到,如果在具有圖像背景的面板中有TabControl,當鼠標懸停在選項卡上時,它會閃爍並重新繪製。有沒有解決辦法來防止這種情況發生?如果圖像是背景,TabControl閃爍
回答
我明白了。發生這種情況是因爲TabControl通過要求父控件在自己的窗口中繪製自己而部分地繪製自己。必要的,因爲選項卡不覆蓋控制的全部寬度,他們「伸出」。如果BackgroundImage繪製速度慢,則會在所繪製的背景與在其上繪製的選項卡之間看到閃爍。
這將很難解決,TabControl不支持任何類型的雙緩衝。您只能通過使BackgroundImage高效繪製來最大限度地降低效果。您需要通過使圖像與面板的ClientSize的大小完全一致來實現,以便圖像不必調整大小。並用PixelFormat32bppPArgb像素格式創建該位圖,通常比其他圖像快10倍。
有一種魔法治療可用,windows有一個樣式標誌,可以爲整個窗口(包括其子控件)啓用雙緩衝。自XP以來支持,但一些副作用已被報告。這段代碼粘貼到您的形式,它修復了TabControl的閃爍:
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
但要注意的是,視覺風格渲染的TabControl有這種風格的一個標誌,而主要的不兼容。如果你的標籤溢出,你得到的選擇箭頭,然後它去香蕉,並開始渲染標籤一遍又一遍,產生非常高的閃爍率。
您可以嘗試創建一個使用雙緩衝的面板。從面板派生並設置DoubleBuffered爲true:
public partial class DoubleBufferedPanel : Panel
{
public DoubleBufferedPanel()
{
InitializeComponent();
this.DoubleBuffered = true;
UpdateStyles();
}
}
我已經試過溶液的CreateParams,並介紹了自己的問題。我需要動態地添加和刪除選項卡,並且在刪除選項卡後,即使在Invalidate()方法之後,帶WS_EX_COMPOSITED的TabControl也不會自我重繪。只有當我將鼠標移動到選項卡區域時,TabControl纔會開始以非常奇怪的方式重繪自己。
所以最後我來到了這個解決方案:
public class TabControlX : TabControl
{
protected override void WndProc(ref Message m)
{
if(m.Msg == WinAPI.WM_MOUSEMOVE && !HotTrack)
return;
base.WndProc(ref m);
}
}
凡
public const int WM_MOUSEMOVE = 0x0200;
對於一些未知的原因HotTrack財產TabControl控件不工作,所以我其實已經固定它:)
當然,它在調整大小時不起作用,但它對我很好。
感謝來自Hans Passant的多個答案,我能夠創建一個只有在需要時纔會處於該模式的切換版本,在這種情況下:當選項卡控件由於父窗體而調整大小時。
這並不容易,因爲我決定最好讓它聽取表單的大小調整開始並調整大小的結尾......這就是我所做的,它適合我的需求,tabcontrol不再閃爍從窗體調整大小正在調整大小。
public class NoFlickerTabControl : TabControl
{
#region PInvoke Change Window Rendering Style Params
public static IntPtr SetWindowLong(HandleRef hWnd, int nIndex, IntPtr dwNewLong)
{
if (IntPtr.Size == 8)
{
return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
}
else
{
return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
}
}
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
private static extern int SetWindowLong32(HandleRef hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
private static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, IntPtr dwNewLong);
public enum WindowLongFlags : int
{
GWL_WNDPROC = -4,
GWL_HINSTANCE = -6,
GWL_HWNDPARENT = -8,
GWL_STYLE = -16,
GWL_EXSTYLE = -20,
GWL_USERDATA = -21,
GWL_ID = -12
}
#endregion
#region Tab Control Style!
public NoFlickerTabControl()
{
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
}
#region Events to use from Parent
private bool bNeedToLinkFormResizeEvents = true;
private void ParentForm_ResizeBegin(object sender, EventArgs e)
{
EnableWS_EX_COMPOSITED();
}
private void ParentForm_ResizeEnd(object sender, EventArgs e)
{
DisableWS_EX_COMPOSITED();
}
#endregion
#region Enable/Disabled WS_EX_COMPOSITED
private const int WS_EX_COMPOSITED = 0x02000000;
private void EnableWS_EX_COMPOSITED()
{
CreateParams cp = CreateParams;
cp.ExStyle |= WS_EX_COMPOSITED; // Turn on WS_EX_COMPOSITED
//Make our call.
HandleRef handleRef = new HandleRef(null, Handle);
IntPtr style = new IntPtr(cp.ExStyle);
SetWindowLong(handleRef, (int)WindowLongFlags.GWL_EXSTYLE, style);
}
private void DisableWS_EX_COMPOSITED()
{
CreateParams cp = CreateParams;
cp.ExStyle &= ~WS_EX_COMPOSITED; // Turn OFF WS_EX_COMPOSITED (in case it's been set)
//Make our call.
HandleRef handleRef = new HandleRef(null, Handle);
IntPtr style = new IntPtr(cp.ExStyle);
SetWindowLong(handleRef, (int)WindowLongFlags.GWL_EXSTYLE, style);
}
#endregion
protected override void WndProc(ref Message m)
{
int WM_MOUSEMOVE = 0x0200;
if (m.Msg == WM_MOUSEMOVE && !HotTrack)
{
return;
}
base.WndProc(ref m);
}
protected override void OnPaint(PaintEventArgs e)
{
if(Width <= 0 || Height <= 0)
{
return;
}
//Paint related, found it was best to do the check here when control finally gets Parent set by the program.
if (bNeedToLinkFormResizeEvents)
{
Form parentForm = FindForm();
if (parentForm != null)
{
bNeedToLinkFormResizeEvents = false;
parentForm.ResizeBegin += ParentForm_ResizeBegin;
parentForm.ResizeEnd += ParentForm_ResizeEnd;
}
}
//~~~~~~ DO THE PAINTING OF THE CONTROL NOW.
}
#endregion
}
- 1. 閃爍背景
- 2. IE7/IE8非背景圖像閃爍
- 3. jquery閃爍的背景圖像
- 4. 背景圖像閃爍鼠標懸停
- 5. Applet背景閃爍?
- 6. IE背景閃爍
- 7. 背景圖像:封面,閃爍的圖像
- 8. 圖片背景在頁面加載時閃爍白色閃爍
- 9. Visual Studio 2010背景閃爍
- 10. 白色背景閃爍
- 11. 使UITextField背景閃爍
- 12. 被加載的背景圖片閃爍
- 13. 背景圖片閃爍jQuery .animate()
- 14. 在div中閃爍背景圖片
- 15. 如何防止Internet Explorer/Edge中的背景圖像閃爍?
- 16. 如何保持內容加載的背景圖像「閃爍」?
- 17. WPF列表視圖行背景閃爍效果
- 18. 鼠標懸停時背景圖像閃爍 - IE
- 19. jquery動畫導致背景圖像閃爍
- 20. 加載頁面時背景圖像閃爍的視頻
- 21. 的Webkit:閃爍上CSS過渡與背景圖像
- 22. 讓CSS背景圖像不斷改變jQuery模仿閃爍
- 23. 使用數據綁定設置背景圖像閃爍
- 24. 背景圖像閃爍在鉻/ jquery後+ div刷新
- 25. 當背景圖像縮放時,它開始在Chrome中閃爍
- 26. jQuery,更改背景圖像時刪除閃爍
- 27. 在winforms中的tabcontrol背景圖像
- 28. 禁用懸停在鏈接上,背景圖像懸停效果導致閃爍
- 29. 在IE頁面閃爍閃爍,mozilla顯示白色背景
- 30. 圖像不閃爍
這樣做的竅門,謝謝! – jwarzech 2010-06-24 18:19:17
忘記標記答案爲答案,這解決了我的問題,謝謝:0) – jwarzech 2010-06-25 19:09:15
真棒,拯救了我的一天! – BerggreenDK 2012-01-06 12:57:07