using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Windows.Forms; using Uni_Trend.MSO7000X.Touch; #pragma warning disable IDE1006 // lowercase public properties #pragma warning disable CS0067 // unused events namespace ScottPlot { public partial class FormsPlot : UserControl,ITouchAble { /// /// This is the plot displayed by the user control. /// After modifying it you may need to call Render() to request the plot be redrawn on the screen. /// public Plot Plot => Backend.Plot; /// /// This object can be used to modify advanced behaior and customization of this user control. /// public Control.Configuration Configuration => Backend.Configuration; /// /// This event is invoked any time the axis limits are modified. /// public event EventHandler AxesChanged; /// /// 创建扩展通道事件 /// public event EventHandler ZoomCreated; /// /// This event is invoked any time the plot is right-clicked. /// By default it contains DefaultRightClickEvent(), but you can remove this and add your own method. /// public event EventHandler RightClicked; /// /// This event is invoked after the mouse moves while dragging a draggable plottable. /// The object passed is the plottable being dragged. /// public event EventHandler PlottableDragged; [Obsolete("use 'PlottableDragged' instead", error: true)] public event EventHandler MouseDragPlottable; /// /// This event is invoked right after a draggable plottable was dropped. /// The object passed is the plottable that was just dropped. /// public event EventHandler PlottableDropped; [Obsolete("use 'PlottableDropped' instead", error: true)] public event EventHandler MouseDropPlottable; //定义ITouchAble的接口相关的事件 public event Action TouchDown; public event Action TouchMove; public event Action TouchUp; public event Action TouchTranslation; public event Action TouchRotation; public event Action TouchScale; private readonly Control.ControlBackEnd Backend = new(1, 1); private readonly Dictionary Cursors; private readonly bool IsDesignerMode = Process.GetCurrentProcess().ProcessName == "devenv"; [Obsolete("Reference 'Plot' instead of 'plt'")] public Plot plt => Plot; public FormsPlot() { if (IsDesignerMode) { try { Plot.Title($"ScottPlot {Plot.Version}"); Plot.Render(); } catch (Exception e) { InitializeComponent(); pictureBox1.Visible = false; rtbErrorMessage.Visible = true; rtbErrorMessage.Dock = DockStyle.Fill; rtbErrorMessage.Text = "ERROR: ScottPlot failed to render in design mode.\n\n" + "This may be due to incompatible System.Drawing.Common versions or a 32-bit/64-bit mismatch.\n\n" + "Although rendering failed at design time, it may still function normally at runtime.\n\n" + $"Exception details:\n{e}"; return; } } Backend.Resize(Width, Height, useDelayedRendering: false); Backend.BitmapChanged += new EventHandler(OnBitmapChanged); Backend.BitmapUpdated += new EventHandler(OnBitmapUpdated); Backend.CursorChanged += new EventHandler(OnCursorChanged); Backend.RightClicked += new EventHandler(OnRightClicked); Backend.AxesChanged += new EventHandler(OnAxesChanged); Backend.ZoomCreated += new EventHandler(OnZoomCreated); Backend.PlottableDragged += new EventHandler(OnPlottableDragged); Backend.PlottableDropped += new EventHandler(OnPlottableDropped); Cursors = new Dictionary() { [ScottPlot.Cursor.Arrow] = System.Windows.Forms.Cursors.Arrow, [ScottPlot.Cursor.WE] = System.Windows.Forms.Cursors.SizeWE, [ScottPlot.Cursor.NS] = System.Windows.Forms.Cursors.SizeNS, [ScottPlot.Cursor.All] = System.Windows.Forms.Cursors.SizeAll, [ScottPlot.Cursor.Crosshair] = System.Windows.Forms.Cursors.Cross, [ScottPlot.Cursor.Hand] = System.Windows.Forms.Cursors.Hand, [ScottPlot.Cursor.Question] = System.Windows.Forms.Cursors.Help, }; InitializeComponent(); rtbErrorMessage.Visible = false; pictureBox1.BackColor = System.Drawing.Color.Transparent; BackColor = System.Drawing.Color.Transparent; Plot.Style(figureBackground: BackColor); pictureBox1.MouseWheel += PictureBox1_MouseWheel; RightClicked += DefaultRightClickEvent; Backend.StartProcessingEvents(); SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor, true); } /// /// Return the mouse position on the plot (in coordinate space) for the latest X and Y coordinates /// public (double x, double y) GetMouseCoordinates() => Backend.GetMouseCoordinates(); /// /// Return the mouse position (in pixel space) for the last observed mouse position /// public (float x, float y) GetMousePixel() => Backend.GetMousePixel(); /// /// Reset this control by replacing the current plot with a new empty plot /// public void Reset() => Backend.Reset(Width, Height); /// /// Reset this control by replacing the current plot with an existing plot /// public void Reset(Plot newPlot) => Backend.Reset(Width, Height, newPlot); /// /// Re-render the plot and update the image displayed by this control. /// /// disable anti-aliasing to produce faster (but lower quality) plots /// public void Render(bool lowQuality = false, bool skipIfCurrentlyRendering = false) { Application.DoEvents(); Backend.Render(lowQuality, skipIfCurrentlyRendering); this.Invalidate(); } /// /// 余晖类型 /// public WaveFormPersist WfmPersist { get { return Backend.WfmPersist; } set { Backend.WfmPersist = value; } } /// /// Request the control re-render the next time it is available. /// This method does not block the calling thread. /// public void RenderRequest(RenderType renderType = RenderType.LowQualityThenHighQualityDelayed) => Backend.RenderRequest(renderType); public void SetZoomingState(Boolean state) { Backend.IsZooming = state; } /// /// 清除无限余晖时的波形缓存 /// public void ClearWfmCache() { Backend.ClearWfmCache(); } private void PlottableCountTimer_Tick(object sender, EventArgs e) => Backend.RenderIfPlottableListChanged(); private void FormsPlot_Load(object sender, EventArgs e) { OnSizeChanged(null, null); } private void OnBitmapUpdated(object sender, EventArgs e) { Application.DoEvents(); /*pictureBox1.Invalidate();*/ } private void OnBitmapChanged(object sender, EventArgs e) {/* pictureBox1.Image = Backend.GetLatestBitmap();*/ } private void OnCursorChanged(object sender, EventArgs e) => Cursor = Cursors[Backend.Cursor]; private void OnSizeChanged(object sender, EventArgs e) => Backend.Resize(Width, Height, useDelayedRendering: true);//创建BMP private void OnAxesChanged(object sender, EventArgs e) => AxesChanged?.Invoke(this, e); private void OnZoomCreated(object sender, EventArgs e) => ZoomCreated?.Invoke(this, e); private void OnRightClicked(object sender, EventArgs e) => RightClicked?.Invoke(this, e); private void OnPlottableDragged(object sender, EventArgs e) => PlottableDragged?.Invoke(sender, e); private void OnPlottableDropped(object sender, EventArgs e) => PlottableDropped?.Invoke(sender, e); private void PictureBox1_MouseDown(object sender, MouseEventArgs e) { Backend.MouseDown(GetInputState(e)); base.OnMouseDown(e); } private void PictureBox1_MouseUp(object sender, MouseEventArgs e) { Backend.MouseUp(GetInputState(e)); base.OnMouseUp(e); } private void PictureBox1_DoubleClick(object sender, EventArgs e) { Backend.DoubleClick(); base.OnDoubleClick(e); } private void PictureBox1_MouseWheel(object sender, MouseEventArgs e) { Backend.MouseWheel(GetInputState(e)); base.OnMouseWheel(e); } private void PictureBox1_MouseMove(object sender, MouseEventArgs e) { Backend.MouseMove(GetInputState(e)); base.OnMouseMove(e); } private void PictureBox1_MouseEnter(object sender, EventArgs e) => base.OnMouseEnter(e); private void PictureBox1_MouseLeave(object sender, EventArgs e) => base.OnMouseLeave(e); //pictureBox1上的触摸的相关事件的处理 private void pictureBox1_TouchDown(int x, int y) { Backend.MouseDown(GetInputState(new MouseEventArgs(MouseButtons.Left, 1, x, y, 0))); TouchDown?.Invoke(x, y); } private void pictureBox1_TouchUp(int x, int y) { Backend.MouseUp(GetInputState(new MouseEventArgs(MouseButtons.Left, 1, x, y, 0))); TouchUp?.Invoke(x, y); } private void pictureBox1_TouchScale(float scale, Uni_Trend.MSO7000X.Touch.ScaleDirection direction) { TouchScale?.Invoke(scale, direction); } private void pictureBox1_TouchMove(int x, int y, int transX,int transY) { Backend.MouseMove(GetInputState(new MouseEventArgs(MouseButtons.Left, 1, x, y, 0))); TouchMove?.Invoke(x, y,transX, transY); } private void pictureBox1_TouchRotation(float rotate) { TouchRotation?.Invoke(rotate); } private Control.InputState GetInputState(MouseEventArgs e) => new() { X = e.X, Y = e.Y, LeftWasJustPressed = e.Button == MouseButtons.Left, RightWasJustPressed = e.Button == MouseButtons.Right, MiddleWasJustPressed = e.Button == MouseButtons.Middle, ShiftDown = ModifierKeys.HasFlag(Keys.Shift), CtrlDown = ModifierKeys.HasFlag(Keys.Control), AltDown = ModifierKeys.HasFlag(Keys.Alt), WheelScrolledUp = e.Delta > 0, WheelScrolledDown = e.Delta < 0, }; protected override void OnPaint(PaintEventArgs e) { e.Graphics.DrawImage(Backend.GetLatestBitmap(), 0, 0); base.OnPaint(e); } /// /// Launch the default right-click menu. /// public void DefaultRightClickEvent(object sender, EventArgs e) => DefaultRightClickMenu.Show(System.Windows.Forms.Cursor.Position); private void RightClickMenu_Copy_Click(object sender, EventArgs e) => Clipboard.SetImage(Plot.Render()); private void RightClickMenu_Help_Click(object sender, EventArgs e) => new FormHelp().Show(); private void RightClickMenu_AutoAxis_Click(object sender, EventArgs e) { Plot.AxisAuto(); Render(); } private void RightClickMenu_OpenInNewWindow_Click(object sender, EventArgs e) => new FormsPlotViewer(Plot).Show(); private void RightClickMenu_SaveImage_Click(object sender, EventArgs e) { var sfd = new SaveFileDialog { FileName = "ScottPlot.png", Filter = "PNG Files (*.png)|*.png;*.png" + "|JPG Files (*.jpg, *.jpeg)|*.jpg;*.jpeg" + "|BMP Files (*.bmp)|*.bmp;*.bmp" + "|All files (*.*)|*.*" }; if (sfd.ShowDialog() == DialogResult.OK) Plot.SaveFig(sfd.FileName); } } }