Почему PictureBox.Invalidate () вызывает сбой программы? System.AccessViolationException - PullRequest
2 голосов
/ 18 апреля 2019

поэтому я написал приложение Windows Form на C #, чтобы открыть видео, отобразить видео в pictureBox_display и позволить пользователям определять (рисовать) ограничительные рамки на картинке.Единственное, что я могу очень предсказуемо заставить программу вызвать System.AccessViolationException и аварийно завершить работу, просто: 1) открыв видео (любое видео), 2) щелкнув мышью + перетащив мышку на поле рисунка на несколько секунд.

Вот некоторый код:

VideoCapture VC;
bool IsMouseDown = false;
bool MouseMoved = false;
string VideoFileName;


private void OpenFileButton_Click(object sender, EventArgs e) {
        OpenFileDialog OFD = new OpenFileDialog();
        if (OFD.ShowDialog() == DialogResult.OK) {
                FrameNumber = 0;
                VideoFileName = OFD.FileName;
                VC = new VideoCapture(VideoFileName);

                if (VC.Width<=0 || VC.Height<=0) {
                    System.Windows.Forms.MessageBox.Show("ERROR: Please load a valid video file");
                    return;
                }


        // Initialize picturebox dimensions according to image
        double W_H_ratio = Convert.ToDouble(VC.Width) / VC.Height;
                if (W_H_ratio >= (double)(5 / 4)) {
                    pictureBox_display.Width = Math.Min(VC.Width, 800);
                    pictureBox_display.Height = Math.Min(VC.Height, (int)((1 / W_H_ratio )* 800));
                }
                else {
                    pictureBox_display.Height = Math.Min(VC.Height, 640);
                    pictureBox_display.Width = Math.Min(VC.Width, (int)(W_H_ratio * 640));
                }

                Mat tempimg = GetMat(FrameNumber);
                Console.WriteLine("Size of tempimg: " + tempimg.Size);
                pictureBox_display.Image = tempimg.Bitmap;
        }
}

private Mat GetMat(int someFrameNumber) {

        try {
                Mat m = new Mat();
                VC.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.PosFrames, someFrameNumber);
                VC.Read(m);

                Mat resized = new Mat();
                CvInvoke.ResizeForFrame(m, resized, pictureBox_display.Size);
                m.Dispose();
                return resized;
        }

        catch {
                Mat m = new Mat();
                System.Windows.Forms.MessageBox.Show("ERROR: Cannot read video frame");
                return m;
        }
}

private void pictureBox_display_MouseDown(object sender, MouseEventArgs e) {
        if (VideoFileName != null && checkBox1.Checked == false && VideoPlaying == false) {
                IsMouseDown = true;
                MouseMoved = false;
                ThereIsNewSelection = true;
                StartLocation = e.Location;
                Console.WriteLine(StartLocation);
        }
}


// Constantly alter the end location of the mouse to provide the coordinates for the rectangle
private void pictureBox_display_MouseMove(object sender, MouseEventArgs e) {
        if (IsMouseDown == true) {
                MouseMoved = true;

                EndLocation = e.Location;
                pictureBox_display.Invalidate();
        }
}

private void pictureBox_display_Paint(object sender, PaintEventArgs e) {
        if (!VideoPlaying && ThereIsNewSelection) {
                e.Graphics.DrawRectangle(Pens.Red, GetRectangle());
        }
}

Я знаю, что это определенно связано с Invalidate (), так как я закомментировал код построчно, и он падает только при наличии Invalidate ().Может кто-нибудь сказать мне, что может быть причиной проблемы?

Вот трассировка стека, если она полезна:

в System.Drawing.SafeNativeMethods.Gdip.GdipDrawImageRectI (графика HandleRef, изображение HandleRef, Int32 x, Int32 y, ширина Int32,Высота Int32) в System.Drawing.Graphics.DrawImage (изображение изображения, Int32 x, Int32 y, ширина Int32, высота Int32) в System.Drawing.Graphics.DrawImage (изображение, прямоугольник) в System.Windows.Forms.PictureBox.OnPaint (PaintEventArgs pe) в System.Windows.Forms.Control.PaintWithErrorHandling (PaintEventArgs e, слой Int16) в System.Windows.Forms.Control.WmPaint (Message & m)
в System.Windows.Forms.Control.WndProc(Сообщение & m) в System.Windows.Forms.NativeWindow.DebuggableCallback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

1 Ответ

0 голосов
/ 16 мая 2019

Вам необходимо клонировать (глубокое копирование) растровое изображение, например:

B.Clone(new Rectangle(0, 0, B.Width, B.Height), B.PixelFormat)
...