Благодаря нескольким ответам, в том числе от Ханса Пассанта, я смог создать переключенную версию, которая будет в этом режиме только тогда, когда это необходимо, в данном случае: когда размер элемента управления вкладками изменялся из-за родительской формы.
Это было нелегко, так как я решил, что лучше всего, чтобы он слушал начало изменения размера формы и конец изменения размера ... Вот что я сделал, и это соответствует моим потребностям, больше не мерцает 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
}