| 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 | < Назад | Оглавление | Далее > |