Graphics.DrawLine () всегда выбрасывает исключение OutofMemory в некоторых условиях - PullRequest
1 голос
/ 06 октября 2010

Вот мои коды. Очень простой метод, который обрабатывает событие System.Windows.Forms.Form.Paint.

void Form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    PointF start = new PointF(121.0F, 106.329636F);
    PointF end = new PointF(0.9999999F, 106.329613F);

    using (Pen p05 = new Pen(Color.Red, 1F))
    {
        p05.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
        p05.DashPattern = new float[] { 4, 2, 1, 3 };
        e.Graphics.DrawLine(p05, start, end);
    }
}

Этот метод всегда вызывает исключение OutofMemoryException.

Я протестировал код под WindowsXP32bit .Net Framework 2.0,3.0 и 3.5, и результат тот же. Но он отлично работает под Windows732bit и Net Framework 2.0,3.0 и 3.5.

Вот что я делаю, чтобы код не выдавал исключение OutofMemoryException. (1, 2 или 3)

1. Установите Graphics.SmoothingMode в System.Drawing.Drawing2D.SmoothingMode.Default

2.Измените конечную точку на PointF (0.99999F, 106.329613F)

3. Установите DashStyle в System.Drawing.Drawing2D.DashStyle.Solid

Но мне нужны SmoothingMode и DashStyle. А в реальной программе координаты рисуемой точки всегда преобразуются матрицей, которая представляет движение, вращение и масштабирование, примененные к лежащему в основе изображению. Так возможны такие координаты, как (0.9999999F, 106.329613F).

Не могли бы вы сказать мне, как справиться с этой назойливой проблемой.

С наилучшими пожеланиями,

STACK TRACE

  • 7 октября 2010 г. добавлено

    System.OutOfMemoryException Сообщение = "Недостаточно памяти" Источник = "System.Drawing" Трассировки стека: расположение System.Drawing.Graphics.CheckErrorStatus (состояние Int32) Местоположение System.Drawing.Graphics.DrawLine (Ручка пера, Одиночная x1, Одиночная y1, Одиночная x2, Одиночная y2) Местоположение System.Drawing.Graphics.DrawLine (Ручка пера, PointF pt1, PointF pt2) расположение WindowsFormsApplication1.Form1.Form1_Paint (отправитель объекта, PaintEventArgs e) расположение C: \ Documents and Settings \ sunyi \ Мои документы \ Visual Studio 2008 \ Projects \ WindowsFormsApplication1 \ WindowsFormsApplication1 \ Form1.cs: строка 24 Местоположение System.Windows.Forms.Control.OnPaint (PaintEventArgs e) Местоположение System.Windows.Forms.Form.OnPaint (PaintEventArgs e) расположение System.Windows.Forms.Control.PaintWithErrorHandling (PaintEventArgs e, слой Int16, логическое значение disposeEventArgs) Местоположение System.Windows.Forms.Control.WmPaint (Сообщение & m) Местоположение System.Windows.Forms.Control.WndProc (Сообщение & m) Местоположение System.Windows.Forms.ScrollableControl.WndProc (Сообщение & m) Местоположение System.Windows.Forms.ContainerControl.WndProc (Сообщение & m) Местоположение System.Windows.Forms.Form.WndProc (Сообщение & m) расположение System.Windows.Forms.Control.ControlNativeWindow.OnMessage (Message & m) Местоположение System.Windows.Forms.Control.ControlNativeWindow.WndProc (Сообщение & m) расположение System.Windows.Forms.NativeWindow.DebuggableCallback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) Местоположение System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW (MSG & msg) расположение System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop (Int32 dwComponentID, причина Int32, Int32 pvLoopData) расположение System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner (причина Int32, контекст ApplicationContext) расположение System.Windows.Forms.Application.ThreadContext.RunMessageLoop (причина Int32, контекст ApplicationContext) Расположение System.Windows.Forms.Application.Run (Форма mainForm) расположение WindowsFormsApplication1.Program.Main () расположение C: \ Documents and Settings \ sunyi \ Мои документы \ Visual Studio 2008 \ Projects \ WindowsFormsApplication1 \ WindowsFormsApplication1 \ Program.cs: строка 17 расположение System.AppDomain._nExecuteAssembly (сборка сборки, строковые [] аргументы) location System.AppDomain.ExecuteAssembly (String assemblyFile, Evidence assemblySecurity, String [] args) расположение Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly () расположение System.Threading.ThreadHelper.ThreadStart_Context (состояние объекта)location System.Threading.ExecutionContext.Run (ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта) location System.Threading.ThreadHelper.ThreadStart () InnerException:

FULL SOURCE

  • 7 октября 2010 г. добавлено
  • 7 октября 2010 г. обновлено в соответствии с рекомендациями Вулканино

Form1.designer.cs

namespace WindowsFormsApplication1
    {
        partial class Form1
        {
            private System.ComponentModel.IContainer components = null;

            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }

            private void InitializeComponent()
            {
                this.SuspendLayout();
                //
                // Form1
                //
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(292, 266);
                this.Name = "Form1";
                this.Text = "Form1";
                this.ResumeLayout(false);
            }
        }
    }

Form1.cs

using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            p05 = new Pen(Color.Red, 1F);
            p05.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
            p05.DashPattern = dashStyle;
            this.Paint += new PaintEventHandler(Form1_Paint);
        }

        void Form1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            e.Graphics.DrawLine(p05, start, end);
        }

        // start and end point are within the
        // client rectangle of the form which has been specified in the designer (292, 266);
        private PointF start = new PointF(121.0F, 106.329636F);
        private PointF end = new PointF(0.9999999F, 106.329613F);
        private float[] dashStyle = new float[] { 4, 2, 1, 3 };
        private Pen p05;
    }
}

1 Ответ

0 голосов
/ 06 октября 2010

Это действительно может быть ошибка нехватки памяти; поскольку некоторые из ваших данных постоянны, попробуйте поместить эти данные вне метода Paint, чтобы вам не приходилось вызывать New:

void Form1_Paint(object sender, PaintEventArgs e)
        {
            //e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

            using ( redPen )
            {
                redPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
                redPen.DashPattern = dashPattern;
                e.Graphics.DrawLine(redPen, startingPoint, endingPoint);
            }
        }

private PointF startingPoint = new PointF(121.0F, 106.329636F);
private PointF endingPoint = new PointF(0.9999999F, 106.329613F);
private Pen redPen = new Pen(Color.Red, 1F);
private float[] dashPattern = { 4, 2, 1, 3 };

Еще одна вещь, которую следует учитывать, это границы графики. Прежде чем делать что-либо еще, сделайте:

  e.DrawBackground();
  Rectangle r = e.Bounds;

А затем нарисуйте границы прямоугольника.

edit: добавить обработчик рисования в событие Load, а не в конструктор.

...