2010-11-22 3 views
0

мой код ниже должен отображать N строк на дюйм. вместо этого я получаю немного больше, чем N строк на дюйм. расстояние между линиями несколько меньше. кроме того, изменение разрешения экрана приводит к изменению расстояния между строками. кто-нибудь знает, как с этим справиться?Как нарисовать N строк на дюйм?


using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 

namespace MyApp 
{ 
    class MyControl : Control 
    { 
     private readonly ContainerVisual container = new ContainerVisual(); 
     private readonly DrawingVisual drawing = new DrawingVisual(); 

     private void RenderDrawing() 
     { 
      var s = PresentationSource.FromVisual(this); 
      var dpiX = 96 * s.CompositionTarget.TransformToDevice.M11; 
      var dpiY = 96 * s.CompositionTarget.TransformToDevice.M22; 

      double N = 1; 

      using (var c = drawing.RenderOpen()) 
      { 
       var p = new Pen(new SolidColorBrush(Colors.Black), 1); 

       for (int i = 0; i < 10; i++) 
       { 
        var x = i * dpiX/N; 
        c.DrawLine(p, new Point(x, 0), new Point(x, 100)); 
       } 
      } 
     } 

     protected override Size ArrangeOverride(Size s) 
     { 
      RenderDrawing(); 
      return s; 
     } 

     protected override Visual GetVisualChild(int index) 
     { 
      return container; 
     } 

     protected override Size MeasureOverride(Size s) 
     { 
      return new Size(); 
     } 

     protected override int VisualChildrenCount 
     { 
      get { return 1; } 
     } 

     public MyControl() 
     { 
      container.Children.Add(drawing); 
      AddVisualChild(container); 
     } 
    } 
} 
+0

Я предполагаю, что это всего лишь образец кода, но кажется, что вы всегда будете рисовать 10 строк. Не N строк на дюйм. Я мог что-то пропустить, но я уверен, что цикл for от 0 до 9 будет рисовать 10 строк. Кроме того, вы должны поместить Pen в оператор using (используя var p = new Pen ...), иначе вы закончите утечку дескрипторов GDI. – pstrjds 2010-11-22 19:44:18

+0

Да, это пример кода. да он рисует десять строк. он должен нарисовать эти десять строк так, чтобы они находились на расстоянии 1/N дюймов друг от друга. – akonsu 2010-11-22 19:46:19

+0

Хорошо, я мог бы отредактировать вопрос, чтобы объяснить это, я прочитал его, так как вы хотите, чтобы N строк на дюйм не 10 строк с расстоянием между ними 1/N. На самом деле, снова прочитав ваш вопрос, я немного смущен, вы говорите, что разрыв меняется с изменением разрешения, но это именно то, что вы хотите, если хотите только 10 строк с расстоянием между основанием на текущем разрешении, тогда расстояние изменяется при изменении разрешения. – pstrjds 2010-11-22 19:48:43

ответ

1

эта статья, кажется, с той же проблемой: WPF DPI issues не существует никакого решения этой проблемы, кроме запроса пользователя установить правильные настройки DPI, которые соответствуют физическому DPI экрана. обходной путь, который я нашел, что облегчает жизнь, - это использовать масштабирование уровня приложения WPF, как описано здесь: http://www.odewit.net/ArticleContent.aspx?id=WpfDpiScaling&lang=en&format=html

0

Не уверен, если это будет сделать то, что вы ищете, но это должно помочь, если проблема связана с округлением. Как я уже сказал в комментариях, ваш код выглядит в основном правильным, я думаю, что это проблема округления с вычислением dpi. Поскольку вы хотите визуализировать на основе 96 точек на дюйм, вычислите координаты на основе 96 точек на дюйм, а затем преобразуйте точки на свое устройство. Я написал это для большей наглядности, вы можете использовать один массив точек и просто помнить, что i является начальной точкой, а i+1 является конечной точкой, и тогда вам нужно будет сделать только один вызов, чтобы преобразовать точки.

private void RenderDrawing() 
    { 
     var s = PresentationSource.FromVisual(this); 
     var dpiX = 96; 

     int numberOfLines = 10; 
     double N = 1; 
     double spacing = dpiX/N; 

     var startPoints = new Point[numberOfLines](); 
     var endPoints = new Point[numberOfLines](); 
     for (int i = 0; i < numberOfLines; i++) 
     { 
      var x = i * spacing; 
      startPoints[i] = new Point(x, 0); 
      endPoints[i] = new Point(x, 100);     
     } 
     s.CompositionTarget.TransformToDevice.Transform(startPoints); 
     s.CompositionTarget.TransformToDevice.Transform(endPoints); 

     using (var c = drawing.RenderOpen()) 
     { 
      using (var p = new Pen(new SolidColorBrush(Colors.Black), 1)) 
      { 
       for(int i=0; i < numberOfLines; i++) 
       { 
        c.DrawLine(p, startPoints[i], endPoints[i]); 
       } 
      } 
     } 
    }