Создание Windows-приложений на основе Visual C#

         

Автоматическое преобразование размера и прокручивание изображения


При создании приложения Picture Viewer нашей задачей была печать содержимого PictureBox, и мы не слишком обращали внимание на внешний вид изображения, помещаемого в него. Между тем, единственным способом просмотра изображения полностью был выбор режима "Подогнать размер" (StretchImage), который приводил к довольно существенным искажениям (рис. 6.20).


увеличить изображение
Рис. 6.20.  Помещение рисунка в PictureBox без сохранения его пропорций (наверху, приложение Picture Viewer) и с сохранением (внизу)</p>

Кроме того, при выборе режима "Истинный размер" (Normal) на форме не появлялись полосы прокрутки, позволяющие просматривать изображение по частям (рис. 6.21).


Рис. 6.21.  При выходе изображения за границы формы необходимы полосы прокрутки

Конечно, вписанное изображение можно было просматривать, изменяя размер самой формы, но этот способ вряд ли будет устраивать пользователей. Займемся разработкой приложения, обладающего более удобным интерфейсом. Далее я снова местами буду пользоваться транслитом и называть режим Scroll Prokrutkoy: дело в том, что мы научимся создавать собственные свойства пользовательского элемента управления, и мне хочется, чтобы они бросались в глаза. Запускаем Visual Studio .NET, создаем новый проект, выбираем шаблон Windows Control Library и называем его PictureElement (рис. 6.22):


Рис. 6.22.  Создание проекта пользовательского элемента управления

В окне Properties появившейся формы в поле свойства Name вводим NamePictureElement. В окне Solution Explorer изменяем название UserControl1.cs на SolPictureElement.cs. Добавляем на форму элемент управления PictureBox — его размеры будут достаточно маленькими, но это не важно, в дальнейшем мы изменим его размер так, как будет нужно (рис. 6.23).


Рис. 6.23.  Элемент управления PictureElement в режиме дизайна

Свойству SizeMode элемента управления PictureBox устанавливаем значение StretchImage. Переходим в код формы, в пространстве имен PictureElement создаем перечисление RejimProsmotra:


При создании приложения Picture Viewer нашей задачей была печать содержимого PictureBox, и мы не слишком обращали внимание на внешний вид изображения, помещаемого в него. Между тем, единственным способом просмотра изображения полностью был выбор режима "Подогнать размер" (StretchImage), который приводил к довольно существенным искажениям (рис. 6.20).


увеличить изображение
Рис. 6.20.  Помещение рисунка в PictureBox без сохранения его пропорций (наверху, приложение Picture Viewer) и с сохранением (внизу)</p>

Кроме того, при выборе режима "Истинный размер" (Normal) на форме не появлялись полосы прокрутки, позволяющие просматривать изображение по частям (рис. 6.21).


Рис. 6.21.  При выходе изображения за границы формы необходимы полосы прокрутки

Конечно, вписанное изображение можно было просматривать, изменяя размер самой формы, но этот способ вряд ли будет устраивать пользователей. Займемся разработкой приложения, обладающего более удобным интерфейсом. Далее я снова местами буду пользоваться транслитом и называть режим Scroll Prokrutkoy: дело в том, что мы научимся создавать собственные свойства пользовательского элемента управления, и мне хочется, чтобы они бросались в глаза. Запускаем Visual Studio .NET, создаем новый проект, выбираем шаблон Windows Control Library и называем его PictureElement (рис. 6.22):


Рис. 6.22.  Создание проекта пользовательского элемента управления

В окне Properties появившейся формы в поле свойства Name вводим NamePictureElement. В окне Solution Explorer изменяем название UserControl1.cs на SolPictureElement.cs. Добавляем на форму элемент управления PictureBox — его размеры будут достаточно маленькими, но это не важно, в дальнейшем мы изменим его размер так, как будет нужно (рис. 6.23).


Рис. 6.23.  Элемент управления PictureElement в режиме дизайна

Свойству SizeMode элемента управления PictureBox устанавливаем значение StretchImage. Переходим в код формы, в пространстве имен PictureElement создаем перечисление RejimProsmotra:




public enum RejimProsmotra { Prokrutka, PodgonRazmera }

В классе формы создаем переменную prosmotrperemen, которая будет определять режим просмотра:

private RejimProsmotra prosmotrperemen;

Создаем свойство Izobrajenie, с помощью которого можно будет помещать изображение в PictureBox элемента:

public Image Izobrajenie { get{return this.pictureBox1.Image;} set { this.pictureBox1.Image = value; //Вызываем метод для установки режима просмотра this.UstanovkaRejima();

} }

Создаем свойство UserPropRejimProsmotra, в котором переменной prosmotrperemen устанавливается значение выбранного режима просмотра:

public RejimProsmotra UserPropRejimProsmotra { get{return this.prosmotrperemen;} set { this.prosmotrperemen = value; this.AutoScroll = (this.prosmotrperemen == RejimProsmotra.Prokrutka ); //Вызываем метод для установки режима просмотра this.UstanovkaRejima(); } }

В методе PodgonRazmera определяются различные возможные случаи отношений размеров изображения, PictureBox и самого элемента:

Листинг 6.12.

(html, txt)





В методе Prokrutka размеры PictureBox устанавливаются равными размерам загруженного изображения:

private void Prokrutka() { //Устанавливаем значение ширины pictureBox1, равное значению ширины изображения this.pictureBox1.Width = this.pictureBox1.Image.Width; //Устанавливаем значение высоты pictureBox1, равное значению высоты изображения this.pictureBox1.Height = this.pictureBox1.Image.Height; //Вызываем метод для установки режима просмотра this.PomeshenieIzobrajeniyavCenter(); }

public enum RejimProsmotra { Prokrutka, PodgonRazmera }

В классе формы создаем переменную prosmotrperemen, которая будет определять режим просмотра:

private RejimProsmotra prosmotrperemen;

Создаем свойство Izobrajenie, с помощью которого можно будет помещать изображение в PictureBox элемента:

public Image Izobrajenie { get{return this.pictureBox1.Image;} set { this.pictureBox1.Image = value; //Вызываем метод для установки режима просмотра this.UstanovkaRejima();

} }

Создаем свойство UserPropRejimProsmotra, в котором переменной prosmotrperemen устанавливается значение выбранного режима просмотра:

public RejimProsmotra UserPropRejimProsmotra { get{return this.prosmotrperemen;} set { this.prosmotrperemen = value; this.AutoScroll = (this.prosmotrperemen == RejimProsmotra.Prokrutka ); //Вызываем метод для установки режима просмотра this.UstanovkaRejima(); } }

В методе PodgonRazmera определяются различные возможные случаи отношений размеров изображения, PictureBox и самого элемента:

private void PodgonRazmera() { //Определяем переменную ProporciiElementa, которая равна //отношению ширины элемента к его высоте float ProporciiElementa = (float)this.Width/this.Height; //Определяем переменную ProporciiIzobrajeniya, которая равна //отношению ширины загруженного изображения к его высоте float ProporciiIzobrajeniya = (float)this.pictureBox1.Image.Width/this.pictureBox1.Image.Height; //Если ширина элемента больше или равна ширине изображения //и высота больше или равна высоте изображения, устанавливаем значения ширины //и высоты pictureBox1 равными ширине и высоте изображения if ( this.Width >= this.pictureBox1.Image.Width && this.Height >= this.pictureBox1.Image.Height ) { this.pictureBox1.Width = this.pictureBox1.Image.Width; this.pictureBox1.Height = this.pictureBox1.Image.Height; } //Иначе, если ширина элемента больше ширины изображения //и высота меньше высоты изображения, устанавливаем значение высоты // pictureBox1, равное высоте элемента, а значение ширины — равное значению //ширины изображения else if( this.Width > this.pictureBox1.Image.Width && this.Height < this.pictureBox1.Image.Height) { this.pictureBox1.Height = this.Height; this.pictureBox1.Width = (int)(this.Height * ProporciiIzobrajeniya); } //Иначе, если ширина элемента меньше ширины изображения //и высота больше высоты изображения, устанавливаем значение ширины // pictureBox1, равное ширине элемента, а значение высоты — равное значению //высоты изображения else if( this.Width < this.pictureBox1.Image.Width && this.Height > this.pictureBox1.Image.Height) { this.pictureBox1.Width = this.Width; this.pictureBox1.Height = (int)(this.Width / ProporciiIzobrajeniya); } //Иначе, если ширина элемента меньше ширины изображения //и высота меньше высоты изображения else if ( this.Width < this.pictureBox1.Image.Width && this.Height < this.pictureBox1.Image.Height ) { //если ширина элемента больше или равна его высоте if (this.Width >= this.Height ) { //Если ширина изображения больше или равна его высоте и переменная //ProporciiIzobrajeniya больше или равна переменной ProporciiElementa, //устанавливаем значение ширины pictureBox1, равное значению ширины элемента, //а значение высоты — равное значению высоты изображения if ( this.pictureBox1.Image.Width >= this.pictureBox1.Image.Height && ProporciiIzobrajeniya >= ProporciiElementa ) { this.pictureBox1.Width = this.Width; this.pictureBox1.Height = (int)(this.Width / ProporciiIzobrajeniya); } //Иначе, устанавливаем значение высоты pictureBox1, равное значению //высоты элемента, а значение ширины — равное значению ширины изображения else { this.pictureBox1.Height = this.Height; this.pictureBox1.Width = (int)(this.Height * ProporciiIzobrajeniya); } } //Иначе else { //Если ширина изображения меньше его высоты и переменная //ProporciiIzobrajeniya меньше переменной ProporciiElementa, //устанавливаем значение высоты pictureBox1, равное значению высоты элемента, //а значение ширины — равное значению ширины изображения if ( this.pictureBox1.Image.Width < this.pictureBox1.Image.Height && ProporciiIzobrajeniya < ProporciiElementa ) { this.pictureBox1.Height = this.Height; this.pictureBox1.Width = (int)(this.Height * ProporciiIzobrajeniya); } //Иначе, устанавливаем значение ширины pictureBox1, равное значению //ширины элемента, а значение высоты — равное значению высоты изображения else { this.pictureBox1.Width = this.Width; this.pictureBox1.Height = (int)(this.Width / ProporciiIzobrajeniya); } } } //Вызываем метод для размещения изображения в центре PomeshenieIzobrajeniyavCenter(); }



Листинг 6.12.

В методе Prokrutka размеры PictureBox устанавливаются равными размерам загруженного изображения:

private void Prokrutka() { //Устанавливаем значение ширины pictureBox1, равное значению ширины изображения this.pictureBox1.Width = this.pictureBox1.Image.Width; //Устанавливаем значение высоты pictureBox1, равное значению высоты изображения this.pictureBox1.Height = this.pictureBox1.Image.Height; //Вызываем метод для установки режима просмотра this.PomeshenieIzobrajeniyavCenter(); }

В методе UstanovkaRejima проверяется значение переменной prosmotrperemen и вызывается соответствующий метод:

private void UstanovkaRejima() { //если pictureBox1 не содержит изображения, возвращаемся назад if ( this.pictureBox1.Image == null ) return; //Если значение переменной prosmotrperemen равно PodgonRazmera, //вызываем метод PodgonRazmera if ( this.prosmotrperemen == RejimProsmotra.PodgonRazmera ) this.PodgonRazmera(); //Иначе вызываем метод Prokrutka else {

this.Prokrutka(); this.AutoScroll = true;

} }

В методе PomeshenieIzobrajeniyavCenter определяется положение элемента pictureBox1 и, соответственно, положение изображения:

private void PomeshenieIzobrajeniyavCenter() { //Переменная top равна разнице между высотой элемента //и высотой pictureBox1, деленной пополам int top = (int)((this.Height - this.pictureBox1.Height)/2.0); //Переменная left равна разнице между шириной элемента //и шириной pictureBox1, деленной пополам int left = (int)((this.Width - this.pictureBox1.Width)/2.0); if ( top < 0 ) top = 0; if ( left > 0 ) left = 0; this.pictureBox1.Top = top; this.pictureBox1.Left = left; }

Переключаемся в режим дизайна, выделяем форму, в окне Properties переключаемся на события и дважды щелкаем в поле Resize и Load:

private void NamePictureElement_Resize(object sender, System.EventArgs e) { //При изменении размеров элемента вызывается метод для установки режима просмотра: this.UstanovkaRejima(); }

private void NamePictureElement_Load(object sender, System.EventArgs e) { //при загрузке элемента устанавливаем нулевые ширину и высоту pictureBox1 this.pictureBox1.Width = 0; this.pictureBox1.Height = 0; //Вызываем метод для установки режима просмотра this.UstanovkaRejima(); }



Все! Компилируем проект, используя сочетания клавиш Ctrl+Shift+B, и закрываем его. Создаем новое Windows-приложение, которое называем AutoScroll_and_Constrain. В свойстве Text формы можно ввести надпись "Сохранение пропорций и прокрутка". Перетаскиваем на форму OpenFileDialog, а главное меню скопируем из приложения Picture Viewer, затем оставим следующие пункты:

mainMenu1, NameTextShortcut
mnuFile&Файл
mnuOpen&ОткрытьCtrlO
mnuView&Вид
mnuResize&Подогнать размер
mnuActual&Истинный размер


Теперь нам нужно добавить созданный пользовательский элемент управления. В окне Toolbox щелкаем правой кнопкой на закладке Windows Forms и выбираем пункт Add/Remove Items… . В окне Customize Toolbox на вкладке .NET Framework Components нажимаем кнопку Browse и выбираем файл PictureElement.dll из папки bin/Debug проекта PictureElement. В результате в окне компонент появляется элемент NamePictureElement, принадлежащий пространству имен PictureElement (рис. 6.24).


Рис. 6.24.  Элемент NamePictureElement

Закрываем окно Customize Toolbox и перетаскиваем на форму появившейся элемент управления NamePictureElement. Обратите внимание на название этого элемента — не случайно при работе с проектом PictureElement мы дали проекту, форме и объекту в Solution Explorer три разных названия. На вкладке Toolbox элемент управления будет называться так же, как и форма пользовательского элемента в режиме дизайна (рис. 6.25).


Рис. 6.25.  Свойство Name формы будет названием пользовательского элемента управления

В окне Properties элемента namePictureElement1 появились два новых свойства, которые мы создали сами (рис. 6.26)!


Рис. 6.26.  Слева приведены фрагменты кода пользовательского элемента управления, на основании которых и были созданы свойства в окне Properties

Устанавливаем свойству Dock значение Fill, а свойству UserPropRejimProsmotra — значение PodgonRazmera. В обработчике пункта меню "Открыть" свойству Izobrajenie элемента загружаемое изображение:



private void mnuOpen_Click(object sender, System.EventArgs e) { this.openFileDialog1.ShowDialog(); string path = this.openFileDialog1.FileName; this.namePictureElement1.Izobrajenie = Image.FromFile(path); }

В обработчиках пунктов меню изменения режима просмотра последовательно устанавливаем два значения свойства UserPropRejimProsmotra:

private void mnuResize_Click(object sender, System.EventArgs e) { this.namePictureElement1.UserPropRejimProsmotra = PictureElement.RejimProsmotra.PodgonRazmera; }

private void mnuActual_Click(object sender, System.EventArgs e) { this.namePictureElement1.UserPropRejimProsmotra = PictureElement.RejimProsmotra.Prokrutka; }

Строка кода в обработчике mnuResize_Click скопирована из области Windows Form Designer generated code:

// // namePictureElement1 // this.namePictureElement1.Dock = System.Windows.Forms.DockStyle.Fill; this.namePictureElement1.Izobrajenie = null; … this.namePictureElement1.UserPropRejimProsmotra = PictureElement.RejimProsmotra.PodgonRazmera;

Запускаем приложение. Два режима просмотра позволяют просматривать уменьшенное изображение с сохранением пропорций или его действительную часть с прокруткой (рис. 6.27).


Рис. 6.27.  Готовое приложение AutoScroll_and_Constrain

На диске, прилагаемом к книге, вы найдете приложения PictureElement и AutoScroll_and_Constrain (Code\Glava6\PictureElement и AutoScroll_and_Constrain ).


Содержание раздела