netlib.narod.ru< Назад | Оглавление | Далее >

Метрические размеры

Размеры клиентской области формы доступны через ее свойство ClientSize и всегда исчисляются в пикселах. Задав другое преобразование страницы, лучше выражать размеры клиентской области не в пикселах, а в единицах, используемых для методов рисования.

Существует минимум два способа получения размеров клиентской области в метрических единицах. Возможно, самый удобный — использование свойства VisibleClipBounds объекта Graphics. Оно всегда возвращает размеры клиентской области в единицах, соответствующих текущим значениям свойств PageUnit и PageScale. Вот программа, которая при помощи VisibleClipBounds показывает размер клиентской области, выраженный во всевозможных единицах.

WhatSize.cs

  //-----------------------------------------
  // WhatSize.cs (C) 2001 by Charles Petzold
  //-----------------------------------------
  using System;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Windows.Forms;

  class WhatSize: PrintableForm
  {
      public new static void Main()
      {
          Application.Run(new WhatSize());
      }
      public WhatSize()
      {
          Text = "What Size?";
      }
      protected override void DoPage(Graphics grfx, Color clr, int cx, int cy)
      {
          Brush brush = new SolidBrush(clr);
          int   y     = 0;

          DoIt(grfx, brush, ref y, GraphicsUnit.Pixel);
          DoIt(grfx, brush, ref y, GraphicsUnit.Display);
          DoIt(grfx, brush, ref y, GraphicsUnit.Document);
          DoIt(grfx, brush, ref y, GraphicsUnit.Inch);
          DoIt(grfx, brush, ref y, GraphicsUnit.Millimeter);
          DoIt(grfx, brush, ref y, GraphicsUnit.Point);
      }
      void DoIt(Graphics grfx, Brush brush, ref int y, GraphicsUnit gu)
      {
          GraphicsState gs = grfx.Save();

          grfx.PageUnit  = gu;
          grfx.PageScale = 1;

          SizeF sizef = grfx.VisibleClipBounds.Size;

          grfx.Restore(gs);

          grfx.DrawString(gu + ": " + sizef, Font, brush, 0, y);
          y += (int) Math.Ceiling(Font.GetHeight(grfx));
     }
}

Метод DoIt в этой программе использует возможности методов Save и Restore, поэтому различные значения PageUnit в действительности не мешают выводу информации при вызове методов DrawString и GetHeight. Вот типичный вид программы WhatSize:


Рис. 7.4.

К сожалению, в случае принтера все иначе. Конструкция свойства VisibleClipBounds такова, что для принтера оно возвращает значения в единицах 1/100 дюйма независимо от заданного преобразования страницы. Но если значение свойства PageUnit для принтера задает измерения в пикселах, VisibleClipBounds также возвращает размер области печати в пикселах.

Историческое замечание: я написал свою первую статью о программировании для Windows в 1986 г. для декабрьского выпуска Microsoft Systems Journal. WSZ («what size»), программа-пример для этой статьи, выводила размер клиентской области программы в пикселах, дюймах и миллиметрах. Приведенная здесь программа WhatSize — существенно упрощенная и сокращенная версия своей бабушки.

Другой подход к определению размеров области экрана включает использование метода TransformPoints, реализованного в классе Graphics.


Методы TransformPoints класса Graphics



void TransformPoints(CoordinateSpace csDst, CoordinateSpace csSrc,
Point[] apt)
void TransformPoints(CoordinateSpace csDst, CoordinateSpace csSrc,
PointF[] aptf)


Перечисление CoordinateSpace определяется в пространстве имен System.Drawing.Drawing2D.


Перечисление CoordinateSpace



Член Значение

World 0
Page 1
Device 2


Пока нам известны два пространства координат: Device (где размеры исчисляются в пикселах относительно левого верхнего угла клиентской области) и Page (в нем размеры исчисляются в дюймах, миллиметрах, пунктах и т.п.). При наличии массива структур PointF, выраженных в единицах устройства, можно пересчитать их в единицы страницы, вызвав метод:

  grfx.TransformPoints(CoordinateSpace.Page, CoordinateSpace.Device, apt);

О пространстве координат World мы поговорим чуть ниже.

Вот другая версия программы WhatSize, использующая для расчета размера клиентской области метод TransformPoints.

WhatSizeTransform.cs

  //--------------------------------------------------
  // WhatSizeTransform.cs (C) 2001 by Charles Petzold
  //--------------------------------------------------
  using System;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Windows.Forms;

  class WhatSizeTransform: PrintableForm
  {
      public new static void Main()
      {
          Application.Run(new WhatSizeTransform());
      }
      public WhatSizeTransform()
      {
          Text = "What Size? With TransformPoints";
      }
      protected override void DoPage(Graphics grfx, Color clr, int cx, int cy)
      {
          Brush   brush = new SolidBrush(clr);
          int     y     = 0;
          Point[] apt   = { new Point(cx, cy) };

          grfx.TransformPoints(CoordinateSpace.Device, 
                               CoordinateSpace.Page, apt);

          DoIt(grfx, brush, ref y, apt[0], GraphicsUnit.Pixel);
          DoIt(grfx, brush, ref y, apt[0], GraphicsUnit.Display);
          DoIt(grfx, brush, ref y, apt[0], GraphicsUnit.Document);
          DoIt(grfx, brush, ref y, apt[0], GraphicsUnit.Inch);
          DoIt(grfx, brush, ref y, apt[0], GraphicsUnit.Millimeter);
          DoIt(grfx, brush, ref y, apt[0], GraphicsUnit.Point);
      }

      void DoIt(Graphics grfx, Brush brush, ref int y, 
                Point pt, GraphicsUnit gu)
      {
          GraphicsState gs = grfx.Save();

          grfx.PageUnit  = gu;
          grfx.PageScale = 1;

          PointF[] aptf = { pt };

          grfx.TransformPoints(CoordinateSpace.Page, 
                               CoordinateSpace.Device, aptf);

          SizeF sizef = new SizeF(aptf[0]);
          grfx.Restore(gs);

          grfx.DrawString(gu + ": " + sizef, Font, brush, 0, y);
          y += (int) Math.Ceiling(Font.GetHeight(grfx));
     }
}

В этой программе я добавил к методу DoIt еще один аргумент — структуру Point, содержащую значения ширины и высоты области экрана в пикселах. Поскольку значения аргументов сх и су метода DoPage уже выражены в пикселах, это не проблема для дисплея, но проблема для принтера. В силу этих причин метод DoPage прибавляет значения сх и су к структуре Point, создает массив структур Point из одного элемента и передает этот массив методу TransformPoints для преобразования значений в единицы устройства. Заметьте, что целевым пространством координат при вызове TransformPoints является CoordinateSpace.Device. Затем DoIt осуществляет преобразование из единиц устройства к пространству координат CoordinateSpace.Page с помощью метода TransformPoints.


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz