Практическое занятие № 8

 

Тема: "Работа с графикой"

Цель работы: получить практические навыки по работе с компонентами отображения графических данных

 

Ход работы

 

 

Создайте форму для просмотра графических файлов вида:

 

 

Указания: для формы задайте свойства: Caption=Выбор изображения.

 

Установка компонентов для создания Проводника Windows на форме

Как видно на рисунке, просмотр графических файлов будем выполнять с помощью специальных компонентов, напоминающих Проводник Windows. Данные компоненты имеются в Delphi, но, по умолчанию, не установлены. Для их установки необходимо выполнить следующие действия:

- распакуйте архив с файлами компонентов;

- в среде Delphi из распакованной папки откройте файл vclshlctrls.dpk. В результате на панели Project manager в правом верхнем углу экрана отобразится проект vclshlctrls70.bpl. Щелкните на нем правой кнопкой мыши и выберите команду Compile;

-  в среде Delphi из распакованной папки откройте файл dclshlctrls.dpk. В результате на панели Project manager в правом верхнем углу экрана отобразится проект dclshlctrls70.bpl. Щелкните на нем правой кнопкой мыши и выберите команду Compile. Еще раз щелкните на нем правой кнопкой мыши и выберите команду Install;

- в результате в группе Samples появятся два новых компонента: TShellTreeView и TShellListView. Вы можете использовать их в будущем для создания своих проектов.

 

Нанесите на форму компонент ShellTreeView для отображения дерева папок.

Нанесите на форму компонент ShellListView для отображения списка элементов в выбранной папке. Для связывания компонента с деревом папок в его свойстве ShellTreeView укажите ссылку на компонент ShellTreeView1.

Для отображения в списке только графических файлов для компонента ShellListView в событии OnAddFolder введите код:

 

procedure TForm1.ShellListView1AddFolder(Sender: TObject; AFolder: TShellFolder; var CanAdd: Boolean);

      //переменная - признак добавления файла в список элеметов папки (1 - добавить, 0 - нет)

var yes:integer;

    //переменная для выделения расширения из файла

    ext:string;

begin

    //предполагаем, что текущий элемент не подходит для добавления

    yes:=0;

    //если очередной элемент - папка

    if AFolder.IsFolder then

        //то включаем признак добавления

        yes:=1

    else

    //иначе, если очередной элемент не папка, т.е. файл

    begin

        //извлекаем расширение из имени файла

        //преобразуем расширение в строчные буквы функцией LowerCase()

        //на случай,если расширения будут записаны в разном регистре

        ext:=LowerCase(ExtractFileExt(AFolder.PathName));

        //если расширение - это расширение графического файла

        if (ext='.jpg') or (ext='.bmp') or (ext='.gif') or (ext='.png') then

            //то включаем признак добавления

            yes:=1;

    end;

 

    //если признак добавления не включен

    if yes=0 then

        //отменяем добавление очередного элемента

        CanAdd:=false;

end;

 

Под деревом папок нужно отображать содержимое выбранного графического файла.

 

Указания: нанесите на форму компонент Image (Additional) и задайте свойства: Stretch = true - масштабирование рисунка, Proportional = true - масштабирование с сохранением пропорций сторон, Center = true - выравнивать изображение по центру компонента.

Для работы с 4 основными графическими форматами необходимо учитывать следующее:

- формат bmp поддерживается автоматически;

- формат jpg поддерживается, но для работы с ним нужно подключить модуль JPEG;

- формат gif не поддерживается. Для работы с ним скачайте файл GifImage.zip, поместите содержимое архива в папку с вашим проектом и подключите модуль GifImage;

- формат png не поддерживается. Для работы с ним скачайте файл PNGImage.zip, поместите содержимое архива в папку с вашим проектом и подключите модуль PngImage.

 

Отображение файла в компоненте Image должно выполняться после щелчка на файле в списке. Для этого в событии OnClick компонента ShellListView введите код:

 

procedure TForm1.ShellListView1Click(Sender: TObject);

begin

    //если в списке выбран не пустой элемент (щелкнули не на пустом фоне окна)

    if (ShellListView1.Selected<>nil) and

        //и выбранный элемент в списке не папка

        not (ShellListView1.SelectedFolder.IsFolder) then

            //в компонент Image1 загружаем выбранный файл

            Image1.Picture.LoadFromFile(ShellListView1.SelectedFolder.PathName)

end;

 

По двойному щелчку на компоненте Image открывается новое окно с увеличенным изображением.

 

Указания: добавьте в проект новую форму. Для формы задайте свойства: Caption = Просмотр изображения, Position = poDesktopCenter. В свойствах проекта перенесите созданную форму в список Available Forms.

Нанесите на форму компонент Image и задайте для него свойства: Align = alClient - компонент заполняет всю форму, Stretch = true - масштабирование рисунка, Proportional = true - масштабирование с сохранением пропорций сторон, Center = true - выравнивать изображение по центру компонента.

Перейдите на главную форму и для компонента Image в событии OnDblClick введите код:

 

procedure TForm1.Image1DblClick(Sender: TObject);

begin

    //если изображения в компоненте Image нет, то конец работы процедуры

    if Image1.Picture.Graphic=nil then

        exit;

    //создаем в памяти экземпляр формы

    Form2:=TForm2.Create(nil);

    //отображаем форму как модальную

    Form2.ShowModal;

end;

 

При отображении второй формы на ней в компоненте Image должно отображаться изображение из Image на главной форме. Для этого в событии OnShow второй формы введите код:

 

procedure TForm2.FormShow(Sender: TObject);

begin

    //загружаем в компонент Image содержимое компонента Image главной формы

    Image1.Picture.Assign(Form1.Image1.Picture);

end;

 

Для удаления созданной формы из памяти перейдите на вторую форму и в событии OnClick введите код:

 

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);

begin

    Action:=caFree;

end;

 

Для выполнения работы с изображением на главной форме для компонента Image создадим контекстное меню.

 

 

Указания: нанесите на форму компонент PopupMenu. Двойным щелчком на нем откройте редактор меню и введите команды: Сохранить..., Разделитель, Вырезать, Копировать, Вставить, Разделитель, Изменить размер...

Для присваивания созданного меню для компонента Image в свойстве PopupMenu укажите созданное меню.

Команды контекстного меню нужно блокировать и разблокировать в зависимости от состояния изображения и буфера обмена.

 

В событии OnPopup компонента PopupMenu введите код:

 

procedure TForm1.PopupMenu1Popup(Sender: TObject);

begin

    //если изображения в Image нет

    if Image1.Picture.Graphic=nil then

    begin

        //блокируем команды Сохранить..., Вырезать, Копировать, Изменить размер...

        n1.Enabled:=false;

        n3.Enabled:=false;

        n4.Enabled:=false;

        n7.Enabled:=false;

    end

    //иначе, если изображения в Image есть

    else

    begin

        //разблокируем команды Сохранить..., Вырезать, Копировать, Изменить размер...

        n1.Enabled:=true;

        n3.Enabled:=true;

        n4.Enabled:=true;

        n7.Enabled:=true;

    end;

 

    //если в буфере обмена графическая информация   

    if not Clipboard.HasFormat(CF_PICTURE) then

        //команда Вставить разблокируется       

        n5.Enabled:=false

    //иначе, если в буфере обмена не графическая информация       

    else

        //команда Вставить блокируется          

        n5.Enabled:=true;

end;
 

 

Команда Сохранить... должна выдавать диалог и предлагать пользователю выбрать один из 4 типов файлов.

 

Указания: нанесите на форму компонент SavePictureDialog. Для компонента задайте свойства: Filter = Bitmaps (*.bmp)|*.bmp|JPEG Image (*.jpg)|*.jpg|GIF Image (*.gif)|*.gif|PNG Image (*.png)|*.png - список форматов для сохранения, DefaultExt = bmp - тип файла по умолчанию.

При изменении типа файла в диалоге нужно менять расширение по умолчанию. Для этого в событии OnTypeChange диалога введите код:

 

procedure TForm1.SavePictureDialog1TypeChange(Sender: TObject);

begin

    //номер типа файла находится в свойстве FilterIndex (нумерация с 1)

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

    case SavePictureDialog1.FilterIndex of

        1: SavePictureDialog1.DefaultExt:='bmp';

        2: SavePictureDialog1.DefaultExt:='jpg';

        3: SavePictureDialog1.DefaultExt:='gif';

        4: SavePictureDialog1.DefaultExt:='png';

    end;

end;

 

Напишем код для команды Сохранить... Двойным щелчком откройте меню PopupMenu и двойным щелчком откройте код команды Сохранить... Введите код:

 

procedure TForm1.N1Click(Sender: TObject);

    //переменные для работы с файлами в разных форматах

var bmp:TBitmap;

    jpg:TJpegImage;

    gif:TGifImage;

    png:TPngObject;

begin

    //очищаем предыдущее имя файла

    SavePictureDialog1.FileName:='';

   

    //если файл в диалоге сохранения не указан, конец работы процедуры

    if not SavePictureDialog1.Execute then

        Exit;

 

    //в зависимости от выбранного типа файла (свойство FilterIndex)

    //сохраняем содержимое Image в соотвествующий формат

    case SavePictureDialog1.FilterIndex of

    //если выбран первый формат (bmp)

    1: begin

            //создаем экземпляр класса для работы с форматом bmp

            bmp:=TBitmap.Create;

            //загружаем в класс содержимое компонента Image (конвертируем изображение)

            bmp.Assign(Image1.Picture.Graphic);

            //сохраняем полученное изображение в файл

            bmp.SaveToFile(SavePictureDialog1.FileName);

            //удаляем экземпляр класса из памяти       

            bmp.Free;

        end;

    //аналогично формат jpg

    2: begin

            jpg:=TJpegImage.Create;

            jpg.Assign(Image1.Picture.Graphic);

            jpg.SaveToFile(SavePictureDialog1.FileName);

            jpg.Free;

        end;

    //аналогично формат gif

    3: begin

            gif:=TGifImage.Create;

            gif.Assign(Image1.Picture.Graphic);

            gif.SaveToFile(SavePictureDialog1.FileName);

            gif.Free;

        end;

    //формат png можно получить только из bmp формата

    4: begin

            //создаем экземпляр класса для работы с форматом bmp

            bmp:=TBitmap.Create;

            //загружаем в класс содержимое компонента Image (конвертируем изображение)

            bmp.Assign(Image1.Picture.Graphic);

            //создаем экземпляр класса для работы с форматом png           

            png:=TPngObject.Create;

            //загружаем в png изображение bmp (происходит конвертирование)           

            png.Assign(bmp);

            //сохраняем полученное изображение           

            png.SaveToFile(SavePictureDialog1.FileName);

            //удаляем созданные экземпляры классов

            png.Free; bmp.Free;

        end;

    end;

end;

 

Реализуйте возможность работы с графикой через буфер обмена.

 

Указания: для работы с буфером обмена подключите модуль ClipBrd..

Двойным щелчком откройте меню PopupMenu и двойным щелчком откройте процедуру команды Вырезать. Введите код:

 

procedure TForm1.N3Click(Sender: TObject);

begin

    //копируем содержимое Image в буфер обмена

    Clipboard.Assign(Image1.Picture);

    //очищаем содержимое Image

    Image1.Picture:=nil;

end;

 

Для команды Копировать напишите код:

 

procedure TForm1.N4Click(Sender: TObject);

begin

    //копируем содержимое Image в буфер обмена

    Clipboard.Assign(Image1.Picture);

end;

 

Для команды Вставить напишите код:

 

procedure TForm1.N5Click(Sender: TObject);

begin

    //в компонент Image помещается содержимое буфера обмена   

    Image1.Picture.Assign(Clipboard);

end;

 

Для команды Изменить размер... организуйте вывод новой формы с возможностью задания нового размера изображения.

 

Указания: создайте новую форму и задайте для нее свойства: Caption = Новый размер, BorderStyle = bsDialog, Position = poDesktopCenter. В окне свойств проекта перенесите форму в список Available Forms. Двойным щелчком откройте меню PopupMenu и двойным щелчком откройте процедуру команды Изменить размер... Введите код:

 

procedure TForm1.N7Click(Sender: TObject);

begin

    //создаем экземпляр формы в памяти

    form3:=TForm3.Create(nil);

    //отображаем созданную форму как модальную

    Form3.ShowModal;

end;

 

При закрытии формы она должна удаляться из памяти. Перейдите на созданную форму и в событии OnClose ведите код:

 

procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);

begin

    Action:=caFree;

end;

 

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

 

 

Указания: нанесите на форму две надписи, два текстовых поля и две кнопки. Для перовой кнопки задайте свойство Default = true, для второй - Cancel = true.

Для сохранение пропорций сторон рисунка опишем глобальную переменную для хранения коэффициента соотношения сторон:

 

prop:real;

 

В событии OnCreate формы заполним поля  реальными размерами изображения и вычислим коэффициент пропорции.

 

procedure TForm3.FormCreate(Sender: TObject);

begin

    //первое поле - ширина изображения из Image на главной форме

    Edit1.Text:=IntToStr(Form1.Image1.Picture.Width);

    //второе поле - высота изображения из Image на главной форме

    Edit2.Text:=IntToStr(Form1.Image1.Picture.Height);

    //коэффициент пропорции = ширина/высота

    prop:=Form1.Image1.Picture.Width/Form1.Image1.Picture.Height;

end;

 

При изменении значения ширины высота должна автоматически пересчитываться с учетом коэффициента. В событии OnKeyDown поля Edit1 введите код:

 

procedure TForm3.Edit1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);

begin

    Edit2.Text:=FloatToStr(Round(StrToInt(Edit1.Text)/prop));

end;

 

При изменении значения  высоты ширина должна автоматически пересчитываться с учетом коэффициента. В событии OnKeyDown поля Edit2 введите код:

 

procedure TForm3.Edit2KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);

begin

    Edit1.Text:=FloatToStr(Int(StrToInt(Edit2.Text)*prop));

end;

 

Кнопка Отмена закрывает окно.

 

procedure TForm3.Button2Click(Sender: TObject);

begin

    Close;

end;

 

Кнопка ОК изменяет размер рисунка и помещает его в компонент Image на главной форме.

 

procedure TForm3.Button1Click(Sender: TObject);

//переменные для работы с изображением

//bmp - исходное изображение

//tempbmp - полученное изображение после изменения размера

var

    bmp,tempbmp:TBitMap;

begin

    //если один из размеров изображения не указан   

    if (Edit1.Text='') or (Edit2.Text='') then

    begin

        //выдаем сообщение об ошибке    

        Application.MessageBox('Выполнение операции невозможно. Укажите правильно размер изображения',

                               'Ошибка',MB_OK+MB_IconError);

        //завершаем работу процедуры

        Exit;

    end;

   

    //создаем экземпляр класса для исходного изображения

    bmp:=TBitMap.Create;

    //помещаем в класс изображение из  компонента Image на главной форме

    bmp.Assign(Form1.Image1.Picture.Graphic);

    //создаем экземпляр класса для нового изображения

    tempbmp:=TBitMap.Create;

    //задаем новому изображению ширину и высоту из полей на форме

    tempbmp.Width:=StrToInt(Edit1.Text);

    tempbmp.Height:=StrToInt(Edit2.Text);

    //задаем параметры нового изображения

    tempbmp.PixelFormat:=pf24bit;

    //задаем для нового изображения гладкое масштабирование

    SetStretchBltMode(tempbmp.Canvas.Handle,4);

    //копируем исходное изображение в новое (происходит увеличение)

    StretchBlt(tempbmp.Canvas.Handle,0,0,tempbmp.Width,tempbmp.Height,

               bmp.Canvas.Handle, 0,0,bmp.Width,bmp.Height,SRCCOPY);

    //в компонент Image на главной форме помещаем полученное изображение

    Form1.Image1.Picture.Assign(tempbmp);

    //удаляем из памяти экземпляры класса

    tempbmp.Free;

    bmp.Free;

    //выдаем сообщение об успешном завершении операции

    Application.MessageBox('Обработка завершена. Можете сохранить изображение в файл',

                           'Операция завершена',MB_OK+MB_IconInformation);

    //закрываем форму

    Close;

end;