Winforms TabControl导致UserControl出现虚假的绘制事件

3
对于我们的项目,我们编写了一个用于绘图的WinForms UserControl。
当我们的控件位于TabControl中时,我们会看到一些奇怪的行为 - 即使用户没有任何操作,我们的控件仍然不断触发Paint事件。
我们只在TabControl中看到这种情况。 当我们将我们的控件放置在其他容器中,例如窗体或分割器中时,只有在你期望的情况下才会触发Paint事件,例如当控件首次显示等。
有人可以建议为什么会出现这种情况吗?
以下是我们控件Paint处理程序中断点的堆栈跟踪,如果有帮助的话。 我们的控件是BaseGraphXY,它位于TabControl上,TabControl又位于一些嵌套的SplitContainers上。 抱歉格式不好 - 不知道为什么SO编辑器无法停止换行。
OverlordFrontEnd.exe!OverlordFrontEnd.MainForm.graphControl_Paint(object sender =  BI_BaseGraphXY.BaseGraphXY}, System.Windows.Forms.PaintEventArgs e = {ClipRectangle = {X=0,Y=0,Width=1031,Height=408}}) Line 422 C#
System.Windows.Forms.dll!System.Windows.Forms.Control.OnPaint(System.Windows.Forms.PaintEventArgs e) + 0x73 bytes   
BI_AppCore.dll!BI_BaseGraphXY.BaseGraphXY.OnPaint(System.Windows.Forms.PaintEventArgs e = {ClipRectangle = {X=0,Y=0,Width=1031,Height=408}}) Line 377 + 0xb bytes   C#
System.Windows.Forms.dll!System.Windows.Forms.Control.PaintTransparentBackground(System.Windows.Forms.PaintEventArgs e, System.Drawing.Rectangle rectangle, System.Drawing.Region transparentRegion = null) + 0x16c bytes   
System.Windows.Forms.dll!System.Windows.Forms.Control.PaintBackground(System.Windows.Forms.PaintEventArgs e = {ClipRectangle = {X=0,Y=0,Width=1029,Height=406}}, System.Drawing.Rectangle rectangle, System.Drawing.Color backColor, System.Drawing.Point scrollOffset) + 0xbc bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.PaintBackground(System.Windows.Forms.PaintEventArgs e, System.Drawing.Rectangle rectangle) + 0x63 bytes   
System.Windows.Forms.dll!System.Windows.Forms.Control.OnPaintBackground(System.Windows.Forms.PaintEventArgs pevent) + 0x59 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.PaintWithErrorHandling(System.Windows.Forms.PaintEventArgs e = {ClipRectangle = {X=0,Y=0,Width=1029,Height=406}}, short layer, bool disposeEventArgs = false) + 0x74 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.WmPaint(ref System.Windows.Forms.Message m) + 0x1ba bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x33e bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x10 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x31 bytes  
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int msg = 15, System.IntPtr wparam, System.IntPtr lparam) + 0x5a bytes  
[Native to Managed Transition]  
[Managed to Native Transition]  
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason = -1, int pvLoopData = 0) + 0x24e bytes 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = -1, System.Windows.Forms.ApplicationContext context = {Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.WinFormsAppContext}) + 0x177 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x61 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.ApplicationContext context) + 0x18 bytes 
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun() + 0x81 bytes    
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel() + 0xef bytes   
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(string[] commandLine) + 0x2c0 bytes 
OverlordFrontEnd.exe!OverlordFrontEnd.Program.Main() Line 36 + 0x10 bytes   C#
[Native to Managed Transition]  
[Managed to Native Transition]  
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x3a bytes    
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x2b bytes  
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes   
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes    
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes   

堆栈跟踪是完全正常的,这是在控件上调用Invalidate并打开DoubleBuffered时所期望的。我从未听说过TabControl会引发这种情况。 - Hans Passant
你是否使用SetStyle? - user117499
不,我们不是。也许我们应该这样做 - 感谢您的提示。 - Tom Bushell
2个回答

1

选项卡控件确实有一些怪癖,请尝试调整SetStyle:

Me.SetStyle(ControlStyles.UserPaint Or ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.DoubleBuffer Or ControlStyles.Selectable Or ControlStyles.ResizeRedraw,True)


0

我的同事已经找到了一个解决问题的方法:

图形控件的问题在于 BackColor 属性默认为 System.Drawing.Color.Transparent。这导致一种“反馈循环”消息的出现。我猜它应该是这样工作的?不管怎样,我将构造函数更改为使用 System.Drawing.SystemColors.ControlLightLight 作为默认的 BackColor 属性。这似乎可以抑制额外的图形绘画。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接