添加实时更新chart后CrossCorrPlotForm图表滚轮缩放失效求助
解决实时更新图表导致其他窗体图表滚轮缩放失效的问题
你的推测方向是对的——MainForm上histChart的高频更新确实会频繁抢占焦点,导致CrossCorrPlotForm的图表无法接收滚轮事件。下面给你几个针对性的解决方案,从简单到进阶逐步尝试:
方案1:更新图表时保留原焦点
每次更新histChart前,先记录当前拥有焦点的控件,更新完成后再恢复焦点,避免histChart抢走焦点:
修改你的bgw1_RunWorkerCompleted方法:
private void bgw1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (this.InvokeRequired) { BeginInvoke((Action)(() => bgw1_RunWorkerCompleted(sender, e))); } else { // 保存当前焦点控件 Control focusedControl = FocusedControl; // 这里建议把计算逻辑移到DoWork里(后面会补充说明) new Thread(() => { Thread.CurrentThread.IsBackground = true; DataFromBitmap DataFromBitmapHist = new DataFromBitmap(SaveBitmap.Clone(cloneRect, SaveBitmap.PixelFormat)); PixelColorCount = DataFromBitmapHist.ColorCountOutput(); }).Start(); // 更新图表的逻辑 chartHist.Titles["Title2"].Visible = false; chartHist.Series["Pixel count"].Points.Clear(); for (int i = 0; i < PixelColorCount.Length; i++) { chartHist.Series["Pixel count"].Points.AddXY(i, PixelColorCount[i]); } if (PixelColorCount.Last() > 1) { chartHist.Titles["Title1"].Visible = false; chartHist.Titles["Title2"].Visible = true; } else { chartHist.Titles["Title1"].Visible = true; chartHist.Titles["Title2"].Visible = false; } // 恢复之前的焦点 if (focusedControl != null && focusedControl.CanFocus) { focusedControl.Focus(); } } }
同时在设计器里把histChart的TabStop属性设为false(或者代码里chartHist.TabStop = false;),彻底阻止它自动获取焦点。
方案2:优化线程逻辑,避免额外线程竞争
你当前在RunWorkerCompleted里新开线程计算像素数据,这其实是多余的——BackgroundWorker的DoWork本身就是后台线程,直接在这里计算更安全,还能避免线程同步问题:
修改bgw1_DoWork:
private void bgw1_DoWork(object s, DoWorkEventArgs e) { Frame frame = (Frame)e.Argument; myBitmap = null; try { frame.Fill(ref myBitmap); mycamera.QueueFrame(frame); SaveBitmap = myBitmap.Clone(cloneRect, myBitmap.PixelFormat); BitmapToPrint = myBitmap.Clone(cloneRect, myBitmap.PixelFormat); // 直接在DoWork里计算数据,通过e.Result传递到UI线程 DataFromBitmap DataFromBitmapHist = new DataFromBitmap(SaveBitmap.Clone(cloneRect, SaveBitmap.PixelFormat)); e.Result = DataFromBitmapHist.ColorCountOutput(); } catch {} }
然后修改RunWorkerCompleted:
private void bgw1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (this.InvokeRequired) { BeginInvoke((Action)(() => bgw1_RunWorkerCompleted(sender, e))); } else { Control focusedControl = FocusedControl; if (e.Result != null) { PixelColorCount = (int[])e.Result; // 更新图表逻辑 chartHist.Titles["Title2"].Visible = false; chartHist.Series["Pixel count"].Points.Clear(); for (int i = 0; i < PixelColorCount.Length; i++) { chartHist.Series["Pixel count"].Points.AddXY(i, PixelColorCount[i]); } if (PixelColorCount.Last() > 1) { chartHist.Titles["Title1"].Visible = false; chartHist.Titles["Title2"].Visible = true; } else { chartHist.Titles["Title1"].Visible = true; chartHist.Titles["Title2"].Visible = false; } } // 恢复焦点 if (focusedControl != null && focusedControl.CanFocus) { focusedControl.Focus(); } } }
方案3:让CrossCorrPlotForm的图表无焦点也能响应滚轮
如果上面的方法还没解决问题,说明滚轮消息被MainForm拦截了。可以重写CrossCorrPlotForm的WndProc方法,直接捕获滚轮消息并转发给鼠标悬停的图表:
protected override void WndProc(ref Message m) { const int WM_MOUSEWHEEL = 0x020A; if (m.Msg == WM_MOUSEWHEEL) { // 获取鼠标在窗体中的位置 Point mousePos = PointToClient(Cursor.Position); // 检查是否在CrossCorrExpChart上,转发消息 if (CrossCorrExpChart.ClientRectangle.Contains(mousePos)) { CrossCorrExpChart.WndProc(ref m); return; } // 检查是否在CrossCorrRefChart上,转发消息 if (CrossCorrRefChart.ClientRectangle.Contains(mousePos)) { CrossCorrRefChart.WndProc(ref m); return; } } base.WndProc(ref m); }
这样即使CrossCorrPlotForm不是当前激活窗体,只要鼠标悬停在它的图表上,滚轮消息就会被正确处理。
内容的提问来源于stack exchange,提问作者Trion
相关产品推荐
相关产品推荐

