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:
К сожалению, в случае принтера все иначе. Конструкция свойства 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 | < Назад | Оглавление | Далее > |