Файлы к лабораторной работе Вы можете скачать здесь.
Даже при простом выводе текста на экран часто нужно обеспечить
взаимодействие с пользователем. В данной работе мы рассмотрим
вопросы вывода текста в колонках и добавление ..
Прежде всего мы создадим главную форму, позволяющую управлять вызовом дочерних форм для каждого упражнения.
Перейдите
в каталог для размещения работы и создайте новое решение
с именем Petzold4

Оболочка создаст новый
Щелкните
правой кнопкой мыши на узле решения в панели Solution
Explorer и добавьте к решению новый пустой проект с именем Test
В панели
References (ссылки)
проекта и выполните команду Add Reference контекстного
меню
Добавьте
ссылки на нужные нам библиотеки 
Щелкните
по узлу Test панели Solution Explorer и
добавьте в проект новый класс с именем Start.cs
Мастер оболочки создаст заготовку, которую мы и будем использовать
для
using System;
namespace Test
{
///
/// Summary description for Start.
///
public class Start
{
public Start()
{
//
// TODO: Add constructor logic here
//
}
}
}
Добавьте
в начало файла Start.cs нужные пространства
имен, соответствующие добавленным ссылкам на библиотеки Form.
Удалите сгенерированные оболочкой комментарии и должен получиться
такой кодusing System;
using System.Windows.Forms;
using System.Drawing;
namespace Test
{
public class Start : Form
{
public Start()
{
// В этом конструкторе будем размещать
// настройки формы
}
}
}
Отметьте, что как только мы добавили к нашему классу базовый
класс Form, в панели пиктограмма класса заменилась
на значек формы.
Добавьте
к проекту новый пустой файл с именем AppClass.cs, в котором
мы разместим точку входа приложения
Удалите
из кода файла AppClass.cs лишние комментарии
и конструктор. Окончательно
содержащий точку входа класс должен
иметь такой кодnamespace Test
{
public class AppClass
{
// Точка входа приложения
static void Main()
{
System.Windows.Forms.Application.Run(new Start());
}
}
}
Здесь мы из точки входа, расположенной в классе AppClass,
создаем экземпляр главной формы вызовом Start.
Выполните
команду меню оболочки Project /Test Properties и
в поле Output Type вкладки Common
Properties/General установите значение Windows
Application,
чтобы отключить окно командной строки приложения
В этом же окне свойств проекта установите параметр в значение Test.AppClass

Задайте
значение строки заголовка главной формы, разместив в конструкторе
класса Start следующий кодusing System;
using System.Windows.Forms;
using System.Drawing;
namespace Test
{
public class Start : Form
{
public Start()
{
// В этом конструкторе будем размещать
// настройки формы
this.Text = "Главная форма Лекция №15";
}
}
}
Постройте
проект и убедитесь, что пустая форма создается
Теперь мы поместим на главную форму элемент управления ListBox и
заполним в нем строки заголовков упражнений, которые нам предстоит
выполнить в этой лабораторной работе. Затем мы создадим обработчики
событий выбора любого из упражнений, внутри которых будем запускать
дочерние формы, соответствующие каждому отдельному упражнению.
Упражнения будут демонстрировать возможности классов библиотеки
.
Откройте
форму Start.cs в режиме View Designer и
поместите на ней из панели ListBox.
Выделите элемент управления ListBox и через панель Properties задайте значения его свойств в
соответствии с таблицей| Свойство | Значение |
|---|---|
Name |
listBox |
|
|
Items |
1) Избранные сведения о системе (SysInfoFirstTry) |
| 2) Разбиение текста на колонки (SysInfoColumn) | |
| 3) Использование своего класса (SysInfoList) | |
| 4) Добавление полос прокрутки (SysInfoPanel) | |
| 5) Прокрутка без элементов управления (SysInfoScroll) | |
| 6) События изменения настроек системы (SysInfoUpdate) | |
| 7) Оптимизация работы функции прорисовки (SysInfoEfficient) |
Растяните
форму Start.cs так, чтобы все строки списка
были полностью в ней видны
Запустите
приложение.Мы не увидели тех изменений, которые внесли в форму и ожидали увидеть. Как и прежде, она оказалось пустой. Исправим это.
Щелкните
на форме правой кнопкой мыши и выполните команду View CodeМы видим, что оболочка сгенерировала соответствующий код,
когда мы создавали пользовательский интерфейс. Весь сгенерированный
код разместился в функции InitializeComponent(),
но вызова этой функции в коде нет.
Поместите
в Start код вызова функции InitializeComponent()public Start()
{
// В этом конструкторе будем размещать
// настройки формы
this.Text = "Главная форма Лекция №15";
InitializeComponent();
}
Постройте
приложение - должен получиться такой результат
Теперь нам нужно создать обработчик, который бы при выборе любой строки списка запускал соответствующую форму.
Перейдите
в режим View Designer формы Start и
выделите компонент listBox. Установите в
панели Properties режим Events и
для события SelectedIndexChanged двойным щелчком на его поле
значений создайте обработчик, который заполните такprivate void listBox_SelectedIndexChanged(object sender, System.EventArgs e)
{
switch(listBox.SelectedIndex + 1)
{
case 1:
SysInfoFirstTry frm1 = new SysInfoFirstTry();
frm1.Show();
break;
case 2:
SysInfoColumn frm2 = new SysInfoColumn();
frm2.Show();
break;
case 3:
SysInfoList frm3 = new SysInfoList();
frm3.Show();
break;
case 4:
SysInfoPanel frm4 = new SysInfoPanel();
frm4.Show();
break;
case 5:
SysInfoScroll frm5 = new SysInfoScroll();
frm5.Show();
break;
case 6:
SysInfoUpdate frm6 = new SysInfoUpdate();
frm6.Show();
break;
case 7:
SysInfoEfficient frm7 = new SysInfoEfficient();
frm7.Show();
break;
}
}
Давайте, по ходу дела, для удобства редактирования кода воспользуемся
свойством текстового
редактора оболочки, для управления которого применяются команды,
показанные на снимке

Перейдите
в режим кода файла Start.cs и охватите функцию InitializeComponent() секционными скобками#region Это секция кода создания списка
private void InitializeComponent()
{
...............................................
}
#endregion
То
же самое проделаем с кодом, где будут размещаться объявления
переменных-членов класса#region Это секция переменных-членов класса
private System.Windows.Forms.ListBox listBox;
#endregion
Сверните
созданные секции кода и насладитесь полученным "коммунальным"
удобством. Убедитесь, что при наведении указателя мыши на
свернутую секцию оболочка показывает содержащийся в ней код
Теперь давайте создадим заготовки из 7 форм, соответствующие
упражнениям, рассматриваемым далее. Вначале создадим одну
шаблонную форму, заполнив в ней необходимые подключаемые пространства
имен. Затем будем эту форму копировать в требуемые, задавая
соответствующие имена файлов и классов. Затем, после физического
(
Добавьте
в проект новый класс с именем Template командой Project /Add Class
Отредактируйте
код файла Template.cs такusing System;
using System.Windows.Forms;
using System.Drawing;
namespace Test
{
public class Template : Form
{
public Template()
{
}
}
}
Сохраните
изменения файла Template.cs на диске, выполнив команду File/Save
All
В панели Solution Explorer выделите файл Template.cs,
затем через меню Edit оболочки выполните
команду Copy, а
затем 7 раз подряд команду
Paste. Таким образом мы получим 7 копий файла

Выделите
файл Template.cs и выполните команду Edit/Delete, чтобы удалить
файл физически.
В панели Solution Explorer переименуйте полученные копии файлов в
соответствии со следующим спискомSysInfoFirstTry.csSysInfoColumn.csSysInfoList.csSysInfoPanel.csSysInfoScroll.csSysInfoUpdate.csSysInfoEfficient.cs
Откройте
каждый из только что using System;
using System.Windows.Forms;
using System.Drawing;
namespace Test
{
public class SysInfoFirstTry : Form
{
public SysInfoFirstTry()
{
}
}
}
Постройте
приложение и проверьте, что при щелчке на каждой строке списка
создается соответствующая ей новая форма (пока еще пустая).После таких грандиозных подготовительных операций перейдем
к выполнению самих упражнений. В каждом упражнении мы будем
ставить задачу и рассматривать ее решение с использованием
Основную информацию о системе, на которой выполняется программа, можно получить с помощью класса System.Windows.Forms.SystemInformation, вернее с помощью его 60 общедоступных статических свойств

Класс SystemInformation содержит
данные о количестве кнопок мыши, размере значков
Расстояние между базовыми линиями двух строк по вертикали можно определить несколькими способами
float System.Drawing.Font.GetHeight(float dpi ) - Возвращает
высоту шрифта в пикселах для вывода на устройство с указанной
вертикальной разрешающей способностью. Это может быть экран,
принтер или другое устройство вывода.float
System.Drawing.Font.GetHeight() - Возвращает
межстрочный интервал, в пикселах, установленного шрифта.
Межстрочный интервал - вертикальное расстояние между
базовыми линиями двух последовательных строк текста.
Таким образом, межстрочный интервал включает в себя пустое
пространство между строками вместе с высотой самого символа.float
System.Drawing.Font.GetHeight(System.Drawing.Graphics
graphics ) -
Возвращает межстрочный интервал шрифта, указанный в текущем
модуле графического объекта.int
System.Drawing.Font.Height - Содержит межстрочный
интервал текущего шрифта.int System.Windows.Forms.Control.FontHeight -
Свойство устанавливает или возвращает В следующем примере мы воспользуемся свойством Font.Height формы
для определения требуемого междустрочного расстояния для установленного
в форме шрифта. Давайте выведем первые десять свойств
класса System.Windows.Forms.SystemInformation.
Откройте
файл SysInfoFirstTry в режиме кода и отредактируйте его такusing System;
using System.Windows.Forms;
using System.Drawing;
namespace Test
{
public class SysInfoFirstTry : Form
{
public SysInfoFirstTry()
{
// В этом конструкторе будем размещать
// настройки формы
this.Text = "Избранные сведения о системе";
this.BackColor = SystemColors.Window;
this.ForeColor = SystemColors.WindowText;
}
int i;
// Заголовок этой функции набрать вручную!!!!!!!!!!!!!!!!!!!!!!!!!!!!
protected override void OnPaint(PaintEventArgs e)
{
Graphics gr = e.Graphics;
SolidBrush brush = new SolidBrush(this.ForeColor);
System.Int32 y = 0; // Псевдонимом является int
gr.DrawString((++i).ToString() + ") "
+ "ArrangeDirection: "
+ SystemInformation.ArrangeDirection.ToString(),
Font, brush, 0, y);
y += Font.Height;
gr.DrawString((++i).ToString() + ") "
+ "ArrangeStartingPosition: "
+ SystemInformation.ArrangeStartingPosition.ToString(),
Font, brush, 0, y);
y += Font.Height;
gr.DrawString((++i).ToString() + ") "
+ "BootMode: "
+ SystemInformation.BootMode.ToString(),
Font, brush, 0, y);
y += Font.Height;
gr.DrawString((++i).ToString() + ") "
+ "Border3DSize: "
+ SystemInformation.Border3DSize.ToString(),
Font, brush, 0, y);
y += Font.Height;
gr.DrawString((++i).ToString() + ") "
+ "BorderSize: "
+ SystemInformation.BorderSize.ToString(),
Font, brush, 0, y);
y += Font.Height;
gr.DrawString((++i).ToString() + ") "
+ "CaptionButtonSize: "
+ SystemInformation.CaptionButtonSize.ToString(),
Font, brush, 0, y);
y += Font.Height;
gr.DrawString((++i).ToString() + ") "
+ "CaptionHeight: "
+ SystemInformation.CaptionHeight.ToString(),
Font, brush, 0, y);
y += Font.Height;
gr.DrawString((++i).ToString() + ") "
+ "ComputerName: "
+ SystemInformation.ComputerName,
Font, brush, 0, y);
y += Font.Height;
gr.DrawString((++i).ToString() + ") "
+ "CursorSize: "
+ SystemInformation.CursorSize.ToString(),
Font, brush, 0, y);
y += Font.Height;
gr.DrawString((++i).ToString() + ") "
+ "DbcsEnabled: "
+ SystemInformation.DbcsEnabled.ToString(),
Font, brush, 0, y);
base.OnPaint (e);
}
}
}
Экранный результат будет таким

Попробуйте посворачивать и поразворачивать дочернюю форму
SysInfoFirstTry. Можно заметить, что каждый раз
Добавьте
в начало функции OnPaint() следующий кодprotected override void OnPaint(PaintEventArgs e)
{
i = 0;
............................................
}
Из 60 свойств системы в библиотечном классе SystemInformation мы вывели только первые 10, чтобы повторяющийся код был не
таким большим. Но можно воспользоваться циклом для вывода всех
Модифицируем предыдущую программу так, чтобы значения свойств выводились в столбик с отступом. Вот соответствующий вариант программы
using System;
using System.Windows.Forms;
using System.Drawing;
namespace Test
{
public class SysInfoColumn : Form
{
public SysInfoColumn()
{
// Начальные настройки формы
// Здесь ключевое слово this необязательно
this.Text = "Разбиение текста на колонки";
this.BackColor = SystemColors.Window;
this.ForeColor = SystemColors.WindowText;
}
// Заголовок этой функции набрать вручную!!!!!!!!!!!!!!!!!!!!!!!!!!!!
protected override void OnPaint(PaintEventArgs e)
{
Graphics gr = e.Graphics;
SolidBrush brush = new SolidBrush(this.ForeColor);
int linespacing = Font.Height;
Single y = 0; // Позиция строк по вертикали
SizeF sizeF = gr.MeasureString( // Измеряем текстовый блок
"ArrangeStartingPosition ", // Образец самого длинного текста
Font);
Single xCol = sizeF.Width;// Позиция второй колонки
gr.DrawString("ArrangeDirection: ",
Font, brush, 0, y);
gr.DrawString(SystemInformation.ArrangeDirection.ToString(),
Font, brush, xCol, y);
y += linespacing;
gr.DrawString("ArrangeStartingPosition: ",
Font, brush, 0, y);
gr.DrawString(SystemInformation.ArrangeStartingPosition.ToString(),
Font, brush, xCol, y);
y += linespacing;
gr.DrawString("BootMode: ",
Font, brush, 0, y);
gr.DrawString(SystemInformation.BootMode.ToString(),
Font, brush, xCol, y);
y += linespacing;
gr.DrawString("Border3DSize: ",
Font, brush, 0, y);
gr.DrawString(SystemInformation.Border3DSize.ToString(),
Font, brush, xCol, y);
y += linespacing;
gr.DrawString("BorderSize: ",
Font, brush, 0, y);
gr.DrawString(SystemInformation.BorderSize.ToString(),
Font, brush, xCol, y);
y += linespacing;
gr.DrawString("CaptionButtonSize: ",
Font, brush, 0, y);
gr.DrawString(SystemInformation.CaptionButtonSize.ToString(),
Font, brush, xCol, y);
y += linespacing;
gr.DrawString("CaptionHeight: ",
Font, brush, 0, y);
gr.DrawString(SystemInformation.CaptionHeight.ToString(),
Font, brush, xCol, y);
y += linespacing;
gr.DrawString("ComputerName: ",
Font, brush, 0, y);
gr.DrawString(SystemInformation.ComputerName,
Font, brush, xCol, y);
y += linespacing;
gr.DrawString("CursorSize: ",
Font, brush, 0, y);
gr.DrawString(SystemInformation.CursorSize.ToString(),
Font, brush, xCol, y);
y += linespacing;
gr.DrawString("DbcsEnabled: ",
Font, brush, 0, y);
gr.DrawString(SystemInformation.DbcsEnabled.ToString(),
Font, brush, xCol, y);
base.OnPaint (e);
}
}
}
Экранный результат выполнения этого кода будет таким

Класс SystemInformation очень полезный класс, к которому возможно
разработчику придется часто обращаться, чтобы заставить программу
автоматически приспосабливаться к конкретной платформе. На
примере этого класса рассмотрим важное средство языка C# -
создавать
Если вспомнить принцип private.
Но мы уже говорили, и это справедливо, что библиотека классов
BCL ( BCL== )является классическим примером объектно-ориентированного
подхода к разработке классов. В то же время мы говорили о
переменных-членах многих классов BCL, которые можно читать
и даже писать, потому что они доступны клиенту (нашему коду)
на уровне public. Есть ли здесь противоречие?
Нет, потому что это не переменные-члены класса, а свойства-члены
класса.
Свойства являются специальным механизмом, позволяющим упаковывать
переменные члены в функции доступа так, что со стороны клиента
не нужна соблюдать синтаксис вызова функций, достаточно указать
просто одно
Свойство C# состоит из двух блоков: get и set. Внутри этих
блоков активно используется универсальный тип value,
который определяется типом свойства. Свойство представляет
собой именованный блок кода, имя которой является именем свойства,
сам блок размещен внутри класса и состоит из разделов get и set.
Вот простой пример синтаксиса
public class MyClass
{
...........................................
private int xxx; // закрытая переменная - член
// Свойство Xxx для xxx
public int Xxx
{
get{return xxx;}
set
{
// Здесь можно реализовать логику проверки
// сохраняемого данного и любой другой контроль
xxx = value; // value - ключевое слово, менять нельзя!
}
} // Конец блока кода объявления свойства
...........................................
}
Несколько замечаний.
value можно
только в теле блока set внутри определения свойства.get_ или set_.set опустить, то получится
свойство "только для чтения".readonly ,
то свойство будет доступно "только для чтения" несмотря
на присутствие блока set.После такого отступления давайте упакуем свойства библиотечного
класса SystemInformation в свойства нашего отдельного класса.
Естественно, что они должны иметь статус "только для чтения".
Выполните
команду меню оболочки Project /Add Class и присвойте SysInfoStrings
Ниже приведен соответствующий код этого класса (этот листинг я выделил зеленым фоном как вспомогательный класс)
using System;
using System.Windows.Forms;
using System.Drawing;
namespace Test
{
// Упаковка 60 свойств класса SystemInformation BCL
public class SysInfoStrings
{
// Свойство массива наименований
public static String[] Labels
{
get
{
return new String[]
{
"ArrangeDirection",
"ArrangeStartingPosition",
"BootMode",
"Border3DSize",
"BorderSize",
"CaptionButtonSize",
"CaptionHeight",
"ComputerName",
"CursorSize",
"DbcsEnabled",
"DebugOS",
"DoubleClickSize",
"DoubleClickTime",
"DragFullWindows",
"DragSize",
"FixedFrameBorderSize",
"FrameBorderSize",
"HighContrast",
"HorizontalScrollBarArrowWidth",
"HorizontalScrollBarHeight",
"HorizontalScrollBarThumbWidth",
"IconSize",
"IconSpacingSize",
"KanjiWindowHeight",
"MaxWindowTrackSize",
"MenuButtonSize",
"MenuCheckSize",
"MenuFont",
"MenuHeight",
"MidEastEnabled",
"MinimizedWindowSize",
"MinimizedWindowSpacingSize",
"MinimumWindowSize",
"MinWindowTrackSize",
"MonitorCount",
"MonitorsSameDisplayFormat",
"MouseButtons",
"MouseButtonsSwapped",
"MousePresent",
"MouseWheelPresent",
"MouseWheelScrollLines",
"NativeMouseWheelSupport",
"Network",
"PenWindows",
"PrimaryMonitorMaximizedWindowSize",
"PrimaryMonitorSize",
"RightAlignedMenus",
"Secure",
"ShowSounds",
"SmallIconSize",
"ToolWindowCaptionButtonSize",
"ToolWindowCaptionHeight",
"UserDomainName",
"UserInteractive",
"UserName",
"VerticalScrollBarArrowHeight",
"VerticalScrollBarThumbHeight",
"VerticalScrollBarWidth",
"VirtualScreen",
"WorkingArea"
}; // End of Array property Labels
} // End of get
} // end of property Labels
// Свойство массива значений
public static String[] Values
{
get
{
return new String[]
{
SystemInformation.ArrangeDirection.ToString(),
SystemInformation.ArrangeStartingPosition.ToString(),
SystemInformation.BootMode.ToString(),
SystemInformation.Border3DSize.ToString(),
SystemInformation.BorderSize.ToString(),
SystemInformation.CaptionButtonSize.ToString(),
SystemInformation.CaptionHeight.ToString(),
SystemInformation.ComputerName.ToString(),
SystemInformation.CursorSize.ToString(),
SystemInformation.DbcsEnabled.ToString(),
SystemInformation.DebugOS.ToString(),
SystemInformation.DoubleClickSize.ToString(),
SystemInformation.DoubleClickTime.ToString(),
SystemInformation.DragFullWindows.ToString(),
SystemInformation.DragSize.ToString(),
SystemInformation.FixedFrameBorderSize.ToString(),
SystemInformation.FrameBorderSize.ToString(),
SystemInformation.HighContrast.ToString(),
SystemInformation.HorizontalScrollBarArrowWidth.ToString(),
SystemInformation.HorizontalScrollBarHeight.ToString(),
SystemInformation.HorizontalScrollBarThumbWidth.ToString(),
SystemInformation.IconSize.ToString(),
SystemInformation.IconSpacingSize.ToString(),
SystemInformation.KanjiWindowHeight.ToString(),
SystemInformation.MaxWindowTrackSize.ToString(),
SystemInformation.MenuButtonSize.ToString(),
SystemInformation.MenuCheckSize.ToString(),
SystemInformation.MenuFont.ToString(),
SystemInformation.MenuHeight.ToString(),
SystemInformation.MidEastEnabled.ToString(),
SystemInformation.MinimizedWindowSize.ToString(),
SystemInformation.MinimizedWindowSpacingSize.ToString(),
SystemInformation.MinimumWindowSize.ToString(),
SystemInformation.MinWindowTrackSize.ToString(),
SystemInformation.MonitorCount.ToString(),
SystemInformation.MonitorsSameDisplayFormat.ToString(),
SystemInformation.MouseButtons.ToString(),
SystemInformation.MouseButtonsSwapped.ToString(),
SystemInformation.MousePresent.ToString(),
SystemInformation.MouseWheelPresent.ToString(),
SystemInformation.MouseWheelScrollLines.ToString(),
SystemInformation.NativeMouseWheelSupport.ToString(),
SystemInformation.Network.ToString(),
SystemInformation.PenWindows.ToString(),
SystemInformation.PrimaryMonitorMaximizedWindowSize.ToString(),
SystemInformation.PrimaryMonitorSize.ToString(),
SystemInformation.RightAlignedMenus.ToString(),
SystemInformation.Secure.ToString(),
SystemInformation.ShowSounds.ToString(),
SystemInformation.SmallIconSize.ToString(),
SystemInformation.ToolWindowCaptionButtonSize.ToString(),
SystemInformation.ToolWindowCaptionHeight.ToString(),
SystemInformation.UserDomainName.ToString(),
SystemInformation.UserInteractive.ToString(),
SystemInformation.UserName.ToString(),
SystemInformation.VerticalScrollBarArrowHeight.ToString(),
SystemInformation.VerticalScrollBarThumbHeight.ToString(),
SystemInformation.VerticalScrollBarWidth.ToString(),
SystemInformation.VirtualScreen.ToString(),
SystemInformation.WorkingArea.ToString()
}; // End of Array property Values
} // End of get
} // end of property Values
// Свойство. Содержит длину массива строк
public static int Count
{
get
{
return Labels.Length;
}
}
// Вспомогательный метод поиска длины
// самой длинной строки
private static Single MaxWidth(String[] strArray,
Graphics graphics, Font font)
{
Single fMax = 0;
foreach(String str in strArray)
fMax = Math.Max(fMax, graphics.MeasureString(str, font).Width);
return fMax;
}
// Метод, доступный для клиентов через имя класса
public static Single MaxLabelWidth(Graphics graphics, Font font)
{
return MaxWidth(Labels, graphics, font);
}
// Метод, доступный для клиентов через имя класса
public static Single MaxValueWidth(Graphics graphics, Font font)
{
return MaxWidth(Values, graphics, font);
}
} // End of class SysInfoStrings
} // End of namespace Test
Упаковка получилась немалая, зато ее можно использовать неоднократно.
Обратите внимание, что стал показывать по
поводу нашего класса, после того, как мы этот класс создали
- ну точь в точь как для стандартных классов...

Теперь код вызывающего класса будет совсем маленьким, но по-прежнему поучительным
using System;
using System.Windows.Forms;
using System.Drawing;
namespace Test
{
public class SysInfoList : Form
{
// Переменные-члены класса (поля класса)
Single xCol;
int linespacing;
public SysInfoList()
{
// Начальные настройки формы
this.Text = "Использование своего класса";
this.BackColor = SystemColors.Window;
this.ForeColor = SystemColors.WindowText;
this.Width += 100;
// Временно создать графический объект,
// чтобы измерить длину пробела
Graphics gr = this.CreateGraphics();
// Замерим длину пробела
SizeF sizeF = gr.MeasureString(" ", Font);
// Определим позицию второй колонки
xCol = sizeF.Width
+ SysInfoStrings.MaxLabelWidth(gr, Font);
// Освободить занимаемые временным объектов ресурсы
gr.Dispose();
linespacing = Font.Height;
}
// Заголовок этой функции набрать вручную!!!!!!!!!!!!!!!!!!!!!!!!!!!!
protected override void OnPaint(PaintEventArgs e)
{
Graphics gr = e.Graphics;
SolidBrush brush = new SolidBrush(this.ForeColor);
// Длина массива свойств
int count = SysInfoStrings.Count;
// Локальные ссылки на массивы через статические свойства
String[] strArrayLabels = SysInfoStrings.Labels;
String[] strArrayValues = SysInfoStrings.Values;
// Выводим все свойства на экран,
// хоть часть и не поместится
for(int i = 0; i < count; i++)
{
gr.DrawString(strArrayLabels[i],
Font, brush, 0, i * linespacing);
gr.DrawString(strArrayValues[i],
Font, brush, xCol, i * linespacing);
}
base.OnPaint (e);
}
}
}
Класс Control содержит наследуемый классом Form метод CreateGraphics(),
который мы использовали для создания временного объекта, чтобы
воспользоваться его методом MeasureString() для измерения длины
пробела и текстового блока максимальной длины. Тем самым мы вычислили
величину отступа, которую сохранили в xCol. Мы
должны также вовремя позаботиться об можно
использовать для вывода графики в клиентской области окна программы,
что мы и делаем в обработчике события OnPaint().
Запустите приложение и должен получиться такой результат

К сожалению все 60 свойств на форме не поместились, но дальше,
когда мы "приделаем" к форме
VScrollBar и HScrollBar и разместить
их в любой части клиентской областиAutoScroll значение True.
Это свойство действует на элементы управления, размещенные
на форме, но не помещающиеся в ее видимой области.Для создания ,
который не
имеет визуального представления, а служит для группирования
визуальных элементов в качестве родителя. Мы добавим в наше
приложение код создания элемента по размерам клиентской
области формы и включим в форме свойство автопрокрутки. Нужно
создать обработчик события для перерисовки элемента панель.
Мы будем использовать в коде созданный нами ранее класс SysInfoStrings.
Добавьте
в класс SysInfoPanel переменные-члены и
код using System;
using System.Windows.Forms;
using System.Drawing;
namespace Test
{
public class SysInfoPanel : Form
{
// Переменные-члены класса
Single xCol;
int linespacing;
public SysInfoPanel()
{
// Начальные настройки формы
this.Text = "Добавление полос прокрутки";
this.BackColor = SystemColors.Window;
this.ForeColor = SystemColors.WindowText;
this.AutoScroll = true;// Включить автопрокрутку в форме
// Надбавка к области для скролирования формы
this.AutoScrollMargin = new Size(10, 10);
// Временно создать, чтобы измерить
Graphics gr = this.CreateGraphics();
// Замерим длину пробела
SizeF sizeF = gr.MeasureString(" ", Font);
// Определим позицию второй колонки
xCol = sizeF.Width
+ SysInfoStrings.MaxLabelWidth(gr, Font);
linespacing = Font.Height;
// Создать объект типа Panel
Panel panel = new Panel();
// Указать панели в качестве родителя текущую форму
// Каждый элемент управления должен иметь родителя!!!
panel.Parent = this;
// Создать делегата обработчика события Paint панели
// Эту строку кода написать вручную!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
panel.Paint +=new PaintEventHandler(panel_Paint);
// Задать левый верхний угол панели нулевым
// (совместить с левым верхним углом клиентской области формы)
panel.Location = Point.Empty;
// Настроить правый нижний угол панели на размер документа
panel.Size = new Size(
(int)Math.Ceiling(xCol + SysInfoStrings.MaxValueWidth(gr, Font)),
(int)Math.Ceiling(linespacing * SysInfoStrings.Count));
/*
// Или то же самое по другому
SizeF size_F = new SizeF(
xCol + SysInfoStrings.MaxValueWidth(gr, Font),
linespacing * SysInfoStrings.Count);
panel.Size = Size.Ceiling(size_F);
*/
// Освободить занимаемые временным графическим объектов ресурсы
gr.Dispose();
}
}
}
Пропишите
выделенный красным код регистрации обработчика вручную, чтобы
правильно создать заготовку обработчика события Paint панели
Заполните
заготовку обработчика события Paint панели
следующим кодомprivate void panel_Paint(object sender, PaintEventArgs e)
{
Graphics gr = e.Graphics;
// Перекрасим фон панели, чтобы видеть ее размеры
// в клиентской области формы
gr.Clear(Color.Yellow);
SolidBrush brush = new SolidBrush(this.ForeColor);
// Длина массива свойств
int count = SysInfoStrings.Count;
// Локальные ссылки на массивы через статические свойства
String[] strArrayLabels = SysInfoStrings.Labels;
String[] strArrayValues = SysInfoStrings.Values;
// Выводим все строки на элемент Panel. Если часть из них не
// поместится, то у элемента Panel появятся полосы прокрутки
for(int i = 0; i < count; i++)
{
gr.DrawString(strArrayLabels[i],
Font, brush, 0, i * linespacing);
gr.DrawString(strArrayValues[i],
Font, brush, xCol, i * linespacing);
}
}
Мы создали объект панель и настроили ее размеры с помощью
временного графического объекта, который использовался для
измерения измерения позиции второй колонки.
Мы назначили панели родителя - форму, чтобы панель принимала
сообщения от Windows, которые передаются системой самой форме.
Размеры панели соответствуют размерам отображаемого на ней
документа и, если панель не помещается в своем родителе, то
форма генерирует AutoScroll.
Мы создали панели,
чтобы панель могла восстанавливать себя всякий раз после своего
разрушения на экране.
Метод использовался для для дополнения вещественных
значений до целого числа. Как альтернативу этому можно было
создать структуру типа SizeF и использовать статический
метод Size. для округления до целого
// Или то же самое по другому
SizeF size_F = new SizeF(
xCol + SysInfoStrings.MaxValueWidth(gr, Font),
linespacing * SysInfoStrings.Count);
panel.Size = Size.Ceiling(size_F);
Постройте приложение и поизменяйте размеры формы. Как только
размер клиентской области формы превысит размеры панели (которая
определяется размерами документа), соответствующая

И наоборот, как только панель не помещается в клиентской
области формы по одному из измерений, то сразу появляется
соответствующая

Отметьте, что ползунки
Другой способ увидеть панель - установить свойство AutoScrollMargin
формы в ее конструкторе. В этом случае область скролирования
формы будет добавлена к размеру документа, т.е. полосу прокрутки
будут исчезать только тогда, когда размер клиентской области
превысит размер документа плюс значение свойства AutoScrollMargin
в пикселах. Ну и, если переместить ползунки до конца вправо
и до конца вниз в нашем примере, то можно увидеть эту
белую границу заданной ширины (можно увидеть краешек клиентской области
самой формы).

Использование классов System.Windows.Forms.HScrollBar и System.Windows.Forms.VScrollBar - более универсальный подход к прокрутке. Оба этих класса наследуют
от класса ScrollBar, который имеет ряд свойств для настройки.
Свойства и , в частности, позволяют задать числовые
значения, соответствующие крайним положениям ползунка, внутри
которых и может работать

В случае применения автопрокрутки в этих свойствах нужды нет.
Диапазон значений задается , на котором мы рисуем текст) плюс
размеров окаймления, устанавливаемых свойством AutoScrollMargin формы.
когда пользователь работает
с полосой прокрутки. При автопрокрутке такое событие не возникает
- по крайней мере получить к нему доступ из приложения нельзя.
Хотя последняя наша программа не обрабатывает событие ,
она обрабатывает событие для панели. Когда программа
выводит информацию на панель, прорисовывается только видимая
область панели. Но при каждой прокрутке на экране появляются
новые области панели и срабатывает событие панели, чтобы
их прорисовать. То же происходит при появления панели на
переднем плане после ее закрытия другими окнами.
Среди многих классов, наследуемых классом Form, есть класс ScrollableControl
и именно в нем реализована автопрокрутка.

Некоторые из ScrollableControl с
уровнем доступа "чтение/запись" приведены в таблице.
| Свойство | Тип | Описание |
|---|---|---|
AutoScroll |
|
Включает автопрокрутку |
HScroll |
|
Включает/выключает видимость горизонтальной |
VScroll |
|
Включает/выключает видимость вертикальной |
AutoScrollMargin |
Size |
Устанавливает отступ справа и снизу от элемента управления |
AutoScrollMinSize |
Size |
Задает минимальную область прокрутки |
AutoScrollPosition |
|
Указывает положение |
Давайте посмотрим, сможем ли мы заставить автопрокрутку работать
без создания дочерних элементов управления, таких, как .
Ключ к созданию автопрокрутки без использования дочерних элементов
управления - в установке наследуемому формой свойству AutoScrollMinSize ненулевого значения (0,0 устанавливается по умолчанию). Обычно
область прокрутки основывается на положении и размере элементов
управления в клиентской области формы. Однако AutoScrollMinSize задает минимальную область прокрутки независимо от наличия
на форме элементов управления. И, конечно, нужно задать наследуемому
формой свойству AutoScroll значение true.
Обычно значение свойства AutoScrollMinSize задается равным
размерам, необходимым для отображения всей выводимой информации.
В нашей программе, отображающей сведения о системе, свойство AutoScrollMinSize должно быть установлено так, чтобы вместить
высоту и ширину всех 60 строк текста. Такие размеры мы задавали
для элемента управления SysInfoStrings.
Откройте
созданную нами ранее заготовку файла SysInfoScroll.cs
Заполните
файл SysInfoScroll.cs следующими кодомpublic class SysInfoScroll : Form
{
// Переменные-члены класса
Single xCol;
int linespacing;
public SysInfoScroll()
{
// Начальные настройки формы
this.Text = "Прокрутка без элементов управления";
// this.BackColor = SystemColors.Window;
BackColor = Color.MediumSpringGreen;
this.ForeColor = SystemColors.WindowText;
// Временно создать, чтобы измерить
Graphics gr = this.CreateGraphics();
// Замерим длину пробела
SizeF sizeF = gr.MeasureString(" ", Font);
// Определим позицию второй колонки
xCol = sizeF.Width
+ SysInfoStrings.MaxLabelWidth(gr, Font);
linespacing = Font.Height;
// Установить свойства автопрокрутки
this.AutoScroll = true;// Включить автопрокрутку в форме
// Надбавка к области для скролирования формы
this.AutoScrollMargin = new Size(10, 10);
// Установить размеры свойства равными документу
SizeF size_F = new SizeF(
xCol + SysInfoStrings.MaxValueWidth(gr, Font),
linespacing * SysInfoStrings.Count);
// Округлить до целого
this.AutoScrollMinSize = Size.Ceiling(size_F);
// Освободить занимаемые временным графическим объектов ресурсы
gr.Dispose();
}
// Следующую строку написать вручную!!!
protected override void OnPaint(PaintEventArgs e)
{
Graphics gr = e.Graphics;
SolidBrush brush = new SolidBrush(this.ForeColor);
// Длина массива свойств
int count = SysInfoStrings.Count;
// Локальные ссылки на массивы через статические свойства
String[] strArrayLabels = SysInfoStrings.Labels;
String[] strArrayValues = SysInfoStrings.Values;
// Выводим все строки на клиентскую область формы. Если
// часть из них не поместится, то появятся полосы прокрутки
Point point = this.AutoScrollPosition; // Копируем в структуру
for(int i = 0; i < count; i++)
{
gr.DrawString(strArrayLabels[i],
Font, brush,
point.X, point.Y + i * linespacing);
gr.DrawString(strArrayValues[i],
Font, brush,
point.X + xCol, point.Y + i * linespacing);
}
base.OnPaint (e);
}
}
В данной программе мы вместо создания перегружаем метод OnPaint() формы, поэтому
Создайте
вручную в конце класса SysInfoScroll код
OnPaint() формы и заполните его тело такpublic class SysInfoScroll : Form
{
..............................................................
// Следующую строку написать вручную!!!
protected override void OnPaint(PaintEventArgs e)
{
Graphics gr = e.Graphics;
SolidBrush brush = new SolidBrush(this.ForeColor);
// Длина массива свойств
int count = SysInfoStrings.Count;
// Локальные ссылки на массивы через статические свойства
String[] strArrayLabels = SysInfoStrings.Labels;
String[] strArrayValues = SysInfoStrings.Values;
// Выводим все строки на клиентскую область формы. Если
// часть из них не поместится, то появятся полосы прокрутки
Point point = this.AutoScrollPosition; // Копируем в структуру
for(int i = 0; i < count; i++)
{
gr.DrawString(strArrayLabels[i],
Font, brush,
point.X, point.Y + i * linespacing);
gr.DrawString(strArrayValues[i],
Font, brush,
point.X + xCol, point.Y + i * linespacing);
}
base.OnPaint (e);
}
}
Генерируемая приведенным кодом форма будет выглядеть так

При появлении DrawString() объекта ничего не знает о AutoScrollPosition.
Наша форма выводит текущую информацию о настройках системы.
Давайте поизвращаемся и предположим, что наша форма видима
на экране, но одновременно пользователь через панель управления
изменил какие-то свойства системы. Если не производить скролирование
и не закрывать клиентскую часть формы другим окном, то событие
OnPaint().
Но можно проинформировать приложение о сделанных изменениях
при помощи событий класса Microsoft..

Класс содержит 12 событий, из которых мы воспользуемся только двумя:
UserPreferenceChanged - отслеживает большинство изменений,
которые пользователь может сделать в Панели управленияDisplaySettingsChanged - инициируется при изменении параметров
экрана
Откройте
в режиме кода созданную нами ранее заготовку файла SysInfoUpdate.cs
Заполните
класс SysInfoUpdate следующим
кодомpublic class SysInfoUpdate : Form
{
// Переменные-члены класса, видимые во всех методах-членах класса
Single xCol;
int linespacing, count;
String[] strArrayLabels, strArrayValues;
public SysInfoUpdate()
{
// Начальные настройки формы
this.Text = "События изменения настроек системы";
this.BackColor = SystemColors.Window;
this.ForeColor = SystemColors.WindowText;
this.AutoScroll = true;// Включить автопрокрутку в форме
// Объявления (делегаты) событий
SystemEvents.UserPreferenceChanged
+=new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
SystemEvents.DisplaySettingsChanged
+=new EventHandler(SystemEvents_DisplaySettingsChanged);
UpdateAllInfo(); // Наша функция, определена ниже!
}
private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
{
UpdateAllInfo();
this.Invalidate();
}
private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
UpdateAllInfo();
this.Invalidate();
}
private void UpdateAllInfo()
{
// Устанавливаем значения переменным уровня класса
count = SysInfoStrings.Count;
// Ссылки на массивы через статические свойства
strArrayLabels = SysInfoStrings.Labels;
strArrayValues = SysInfoStrings.Values;
// Временно создать, чтобы измерить
Graphics gr = this.CreateGraphics();
// Замерим длину пробела
SizeF sizeF = gr.MeasureString(" ", Font);
// Определим позицию второй колонки
xCol = sizeF.Width
+ SysInfoStrings.MaxLabelWidth(gr, Font);
linespacing = Font.Height;
// Установить свойства автопрокрутки
SizeF size_F = new SizeF(
xCol + SysInfoStrings.MaxValueWidth(gr, Font),
linespacing * count);
// Округлить до целого
this.AutoScrollMinSize = Size.Ceiling(size_F);
// Освободить занимаемые временным графическим объектов ресурсы
gr.Dispose();
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics gr = e.Graphics;
SolidBrush brush = new SolidBrush(this.ForeColor);
Point point = this.AutoScrollPosition; // Копируем в структуру
for(int i = 0; i < count; i++)
{
gr.DrawString(strArrayLabels[i],
Font, brush,
point.X, point.Y + i * linespacing);
gr.DrawString(strArrayValues[i],
Font, brush,
point.X + xCol, point.Y + i * linespacing);
}
base.OnPaint (e);
}
}
Добавьте
в начало файла SysInfoUpdate.cs ссылку
на пространство имен Microsoft.Win32 using Microsoft.Win32; using System; using System.Windows.Forms; using System.Drawing;
Проверить приложение можно в окне панели задач
на свойстве "Автоматически
убирать с экрана", разнеся это окно и окно формы. При щелчке
на кнопке "Применить" будет меняться значение последнего
свойства WorkingArea.
Обработчик OnPaint() формы срабатывает всякий раз,
когда клиентская область программы становится недействительной.
Недействительной она становится, если окно заслоняется другим
окном или при скролировании. В обработчике используется цикл,
который перебирает все строки массива и заставляет их рисоваться
в объекте даже и в том случае, когда они не видны
на экране. Это лишняя трата ресурсов. Давайте заставим обработчик
перерисовывать только видимые в данный момент на экране строки,
а закулисную информацию прорисовывать впустую не нужно.
Воспользуемся свойством ClipRectangle класса PaintEventArgs,
которое определяет наименьший прямоугольник в координатах клиентской
области, в который умещается недействительная зона.
Ниже приведен SysInfoEfficient, которая наследует форму SysInfoUpdate и
переопределяет метод OnPaint() его более эффективной версией.
В iFirst и iLast, которые затем используются в цикле
для отображения минимального количества строк, требуемых для
прорисовки клиентской области.
Перед циклом стоит выражение, которое с помощью метода
предотвращает выход значения iLast за пределы общего количества
отображаемых строк. Это может случится тогда, когда окно программы
выше, чем требуется для отображения всех строк.
Откройте
созданную нами ранее заготовку класса SysInfoEfficient.cs и наполните ее следующим кодомusing Microsoft.Win32;
using System;
using System.Windows.Forms;
using System.Drawing;
namespace Test
{
public class SysInfoEfficient : SysInfoUpdate // Наследует предыдущий!!!
{
public SysInfoEfficient()
{
// Начальные настройки формы
this.Text = "7) Оптимизация работы функции прорисовки";
this.Width += 50;
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics gr = e.Graphics;
SolidBrush brush = new SolidBrush(this.ForeColor);
Point point = this.AutoScrollPosition;
int iFirst = (e.ClipRectangle.Top - point.Y) / linespacing;
int iLast = (e.ClipRectangle.Bottom - point.Y) / linespacing;
iLast = Math.Min(count - 1, iLast);
for(int i = iFirst; i <= iLast; i++)
{
gr.DrawString(strArrayLabels[i],
Font, brush,
point.X, point.Y + i * linespacing);
gr.DrawString(strArrayValues[i],
Font, brush,
point.X + xCol, point.Y + i * linespacing);
}
}
}
}
Запустите
приложение и компилятор выдаст ошибки, что используемые в
форме переменные не имеют требуемого уровня доступа.В классе SysInfoEfficient мы используем код,
наследуемый из класса SysInfoUpdate, но непозаботились
о явном объявлении уровня доступа для переменных-членах базового
класса. А они в C# по умолчанию считаются private и
поэтому доступны только внутри класса, в котором объявлены.
Исправим это
Откройте
файл SysInfoUpdate.cs в режиме кода и добавьте
для переменных-членов модификаторы, обеспечивающие доступ
наследникамpublic class SysInfoUpdate : Form
{
// Переменные-члены класса, видимые во всех методах-членах класса
protected Single xCol;
protected int linespacing, count;
protected String[] strArrayLabels, strArrayValues;
................................................
}
,Запустите
приложение и проверьте работоспособность формы SysInfoEfficient и функциональность
во всех построенных нами режимах

Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.