Использование диалогов для загрузки и сохранения графических файлов

Для удобства открытия картинок существует пара компонентов-диалогов: TOpenPictureDialog и TSavePictureDialog.

Список форматов открываемых файлов определяется свойством Filter. Можно, как в случае со стандартными диалогами TOpenDiaiog или TSaveDialog, сформировать их вручную с помощью редактора свойства Filter. Можно поступить проще, воспользовавшись готовыми средствами. Для удобства формирования строк графических фильтров существуют три специальные функции:

Формирует строку с полным текстом графического фильтра, позволяющего открывать все файлы, форматы которых являются потомками параметра GraphicClass. Если в качестве параметра этой функции будет передан класс TGraphic, то в строке будут перечислены все форматы:

'Аll (*.jpg;*.jpeg;*.bmp;*.ico;*.emf;*.wmf} I *.jpg;*.jpeg;*.bmp;*.ico; *.emf;*.wmfIJPEG Image File (*.jpg) I *.jpgI JPEG Image File (*.jpeg) I *.jpeg|Bitmaps (*.bmp) I *.bmplIcons (*.ico) I*.ico|Enhanced Metafiles (*.emf) |*.emf[Metafiles (*.wmf) I *.wmf'

Формат JPEG появляется в перечне, если в приложении используется модуль с тем же названием — JPEG. В приводимом ниже примере возникла необходимость совместить фильтры только для классов TBitmap и TJPEGimage, которые не являются предками друг друга. В этом случае получившиеся строки нужно соединить, использовав символ конкатенации "|":

S := GraphicFilter(TBitmap)+'|'+

GraphicFilter(TJpeglmage) 

Возвращает расширение файла, формат которого соответствует графическому классу GraphicClass. Так, если передать в качестве параметра класс TBitmap, то функция вернет строку 'BMP';

Эта функция возвращает перечень расширений файлов с форматами — потомками GraphicClass, перечисленных через точку с запятой.

Для диалогов предусмотрено несколько событий, которые программист может обработать самостоятельно. Первые три — достаточно тривиальные: OnShow, oncanciose и enclose. Нужно предостеречь программиста: по чьему-то недосмотру последние два вызываются только в случае нормального завершения диалога (нажатием кнопки Open или Save), а если завершить диалог нажатием кнопки Cancel или "крестика" на заголовке диалога, то управления они не получат.

Другие три события связаны с изменениями, которые осуществляет пользователь во время выбора нужного файла. Они происходят в момент изменения формата открываемого файла (событие onTypeChange), изменения текущей папки (OnFolderChange) и текущего файла (OnSelectionChange).

Но разработчики диалогов не предусмотрели одну очень нужную возможность. Дело в том, что у разных графических форматов возможны различные опции и варианты. Если вы имеете опыт работы с графическими пакетами вроде Adobe Photoshop или Corel, то знаете, что, в зависимости от выбранного формата сохранения данных, диалог изменяет свой внешний вид — к нему добавляются элементы управления, соответствующие параметрам формата.

Поступим так и мы, предусмотрев настройку при сохранении файлов формата JPEG. Для этого будет использовано событие OnTypeChange компонента TSavePictureDialog. Для события нужно проверить значение свойства Filterindex. Если оно больше 1 (т. е. выбраны файлы формата JPEG), нужно увеличить высоту окна диалога и разместить на нем дополнительные компоненты: флажок, соответствующий свойству ProgressiveEncoding, и редактор свойства compressionQuaiity (рис. 10.2). Если тип файла снова поменялся и стал равным 1, нужно эти компоненты убрать.

Рис. 10.2. Внешний вид модифицированного компонента TSavePictureDiaiog

Поможет нам в этом внимательное изучение исходных кодов диалогов, находящихся в модуле EXTDLGS.PAS. Программисты Borland пошли по пути модернизации внешнего вида стандартных диалогов, добавив к ним справа панель для отображения внешнего вида открываемых (записываемых) картинок. Можно пойти дальше и добавить таким же образом и свои элементы управления.

Приводимый ниже пример ModifDlg — усовершенствованная программа просмотра и сохранения файлов растровой графики, к которым относятся файлы форматов JPEG и BMP. Чтобы исключить метафайлы и значки (*.wmf, *.emf, *.ico), соответствующим образом настраиваются фильтры в диалогах открытия и сохранения.

Для изменения размеров диалогового окна нужно отыскать среди входящих в его состав компонентов панель picturePanel (так назвали ее разработчики Borland) и увеличить ее высоту. Следует также поменять и размеры родительских окон. Поскольку они не являются компонентами Delphi (стандартные диалоги являются составными частями Windows) для этой цели используются функции API GetWindowRect И SetWindowPos.

Обратите также внимание, что при загрузке используется событие OnProgress класса TGraphic. В его обработчике информация об объеме проделанной работы отображается на компоненте progressBar1. Для маленьких картинок обработчик вызывается только в начале и в конце операции, пользователь ничего не заметит. Зато при загрузке большого изображения он будет спокоен, видя, что процесс загрузки идет и машина не зависла.

Листинг 10.1. Исходный текст главного модуля программы ModifDlg 

unit mainUnit; 

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,

 Dialogs,

ExtDlgs, StdCtrls, ComCtrls, ExtCtrls, Buttons; 

type

TForml = class(TForm)

SavePictureDialogl: TSavePictureDialog; 

OpenPictureDialogl: TOpenPictureDialog;

 ScrollBoxl: TScrollBox; Imagel: TImage; 

ProgressBari: TProgressBar;

 OpenBitBtn: TBitBtn;

 SaveBitBtn: TBitBtn;

procedure SavePictureDialoglTypeChange(Sender: TObject); 

procedure ImagelProgress(Sender: TObject; Stage: TProgressStage;

 PercentDone: Byte; 

RedrawNow: Boolean; 

const R: TRect;

 const Msg: String);

procedure SavePictureDialoglClose(Sender: TObject); 

procedure FormCreate(Sender: TObject);

procedure SavePictureDialoglShow(Sender: TObject);

 procedure OpenBitBtnClick(Sender: TObject);

 procedure SaveBitBtnClick(Sender: TObject); 

private 

public 

end;

var

Forml: TForml;

implementation

{$R *.DFM} 

uses jpeg;

const DeltaH : Integer = 80; 

var Quality : TJpegQualityRange; 

ProgressiveEnc : Boolean;

procedure TForml.OpenBitBtnClick(Sender: TObject);

begin

if OpenPictureDialogl.Execute

then Imagel.Picture.LoadFromFile

(OpenPictureDialogl.FileName); 

end;

procedure TForml.SaveBitBtnClick(Sender: TObject);

var ji : TJpeglmage;

begin

if SavePictureDialogl.Execute then

begin

ji := TJpeglmage.Create;

ji.CompressionQuality := Quality;

ji.ProgressiveEncoding := ProgressiveEnc;

j i.Assign(Imagel.Picture.Bitmap);

ji.SaveToFile(SavePictureDialogl.FileName);

ji.Free;

end;

 end;

procedure TForml.SavePictureDialoglTypeChange(Sender: TObject);

 var ParentHandle:THandle;wRect:TRect;

PicPanel,PaintPanel:TPanel;JEdit : TEdit; 

Expanded : boolean;

begin

With Sender as TSavePictureDialog do

 begin

PicPanel := (FindComponent('PicturePanel') as TPanel);

if not Assigned(PicPanel) then Exit;

ParentHandle:=GetParent(Handle);

PaintPanel:=(FindComponent('PaintPanel') as TPanel); 

PaintPanel.Align := alNone;

 Expanded := FindComponent('JLabel') <> nil;

 if Filterlndex >1 then begin if not Expanded then

begin

GetWindowRect(ParentHandle,WRect);

SetWindowPos(ParentHandle,0,0,0,

WRect.Right-WRect.Left,

WRect.Bottom-WRect.Top+DeltaH,

SWP_NOMOVE+SWP_NOZORDER);

GetWindowRect(Handle,WRect);

SetWindowPos(handle,0,0,0,WRect.Right-

WRect.Left,

WRect.Bottom-WRect.Top+DeltaH,

SWP_NOMOVE+SWP_NOZORDER);

Expanded:=True;

PicPanel.Height := PicPanel.Height+DeltaH;

if FindComponent('JLabel')=nil

 then with TLabel.Create(Sender as TSavePictureDialog) do

 begin

Parent := PicPanel;

Name := 'JLabel';

Caption := 'Quality';

Left := 5;

Height := 25;

Top := PaintPanel.Top+PaintPanel.Height+5; end;

if FindComponent('JEdit')=nil then 

begin

JEdit := TEdit.Create(Sender as TSavePictureDialog);

 with JEdit do 

begin

Parent := PicPanel;

Name:='JEdit';

Text := '75';

Left:-50;Width := 50;

Height := 25;

Top := PaintPanel.Top+PaintPanel.Height+5; 

end;

 end;

if FindComponent('JUpDown')=nil then 

with TUpDown.Create(Sender as TSavePictureDialog) do

 begin

Parent := PicPanel;

Name:='JUpDown';

Associate := JEdit;

Increment := 5;

Min := 1; Max := 100;

Position := 75; end;

if FindComponent('JCheck')=nil then

with TCheckBox.Create(Sender as TSavePictureDialog) do

 begin

Name: = 'JCheck';

Caption:='Progressive Encoding'; Parent:=PicPanel;

Left:=5;Width := PicPanel.Width - 10; Height:=25;

Top := PaintPanel.Top+PaintPanel.Height+35; 

end;

 end; 

end 

else

SavePictureDialoglClose(Sender);

 end; 

end;

procedure TForml.ImagelProgress(Sender: TObject; Stage: TProgressStage;

 PercentDone: Byte; RedrawNow: Boolean; const R: TRect; 

const Msg: String); 

begin

case Stage of psStarting: 

begin

Progressbarl.Position := 0;

 Progressbarl.Max := 100;

 end;

 psEnding: begin

Progressbarl.Position := 0; 

end;

psRunning: begin

Progressbarl.Position := PercentDone;

end; 

end;

 end;

procedure TForml.SavePictureDialoglClose(Sender: TObject);

 var PicPanel : TPanel; ParentHandle : THandle; WRect : TRect;

 begin

With Sender as TSavePictureDialog do

 begin

PicPanel := (FindComponent('PicturePanel') as TPanel);

 if not Assigned(PicPanel) then Exit; ParentHandle:=GetParent(Handle);

 if ParentHandle=0 then Exit;

 if FindComponent('JLabel')onil then 

begin

FindComponent('JLabel').Free; 

FindComponent('JEdit').Free;

ProgressiveEnc := (FindComponent('JCheck1) as TCheckBox).Checked; FindComponent('JCheck').Free;

Quality := (FindComponent('JUpDown') as TUpDown).Position; FindComponent('JUpDown').Free;

PicPanel.Height:=PicPanel.Height-DeltaH; 

GetWindowRect(Handle,WRect);

SetWindowPos(Handle,0,0,0,WRect.Right-WRect.Left, WRect.Bottom-WRect.Top-DeltaH,

SWP_NOMOVE+SWP_NOZORDER); GetWindowRect(ParentHandle,WRect);

SetWindowPos(ParentHandle,0,0,0,

WRect.Right-WRect.Left, WRect.Bottom-WRect.Top-DeltaH,

SWP_NOMOVE+SWP_NOZORDER); Filterlndex := 1;

 end; 

end; 

end;

procedure TForml.FormCreate(Sender: TObject);

var s: string;

begin

s :=GraphicFilter(TBitmap)+'|'+

GraphicFilter(TJpeglmage);

OpenPictureDialogl.Filter := s;

SavePictureDialogl.Filter := s; 

end;

procedure TForml.SavePictureDialoglShow(Sender: TObject); 

begin

with Sender as TSavePictureDialog do

 begin

if FindComponent('JLabel')Onil then

 begin

FilterIndex := 2;

SavePictureDialoglTypeChange(Sender) ;

 end;

 end; 

end;

end.

Приведенный пример может послужить толчком, во-первых, к углубленному изучению формата JPEG, а во-вторых, — к модификации стандартных диалогов. На его базе можно создать диалоги открытия аудиозаписей, документов и других специализированных видов файлов.

 


Знаете ли Вы, что cогласно релятивистской мифологии "гравитационное линзирование - это физическое явление, связанное с отклонением лучей света в поле тяжести. Гравитационные линзы обясняют образование кратных изображений одного и того же астрономического объекта (квазаров, галактик), когда на луч зрения от источника к наблюдателю попадает другая галактика или скопление галактик (собственно линза). В некоторых изображениях происходит усиление яркости оригинального источника." (Релятивисты приводят примеры искажения изображений галактик в качестве подтверждения ОТО - воздействия гравитации на свет)
При этом они забывают, что поле действия эффекта ОТО - это малые углы вблизи поверхности звезд, где на самом деле этот эффект не наблюдается (затменные двойные). Разница в шкалах явлений реального искажения изображений галактик и мифического отклонения вблизи звезд - 1011 раз. Приведу аналогию. Можно говорить о воздействии поверхностного натяжения на форму капель, но нельзя серьезно говорить о силе поверхностного натяжения, как о причине океанских приливов.
Эфирная физика находит ответ на наблюдаемое явление искажения изображений галактик. Это результат нагрева эфира вблизи галактик, изменения его плотности и, следовательно, изменения скорости света на галактических расстояниях вследствие преломления света в эфире различной плотности. Подтверждением термической природы искажения изображений галактик является прямая связь этого искажения с радиоизлучением пространства, то есть эфира в этом месте, смещение спектра CMB (космическое микроволновое излучение) в данном направлении в высокочастотную область. Подробнее читайте в FAQ по эфирной физике.

НОВОСТИ ФОРУМА

Форум Рыцари теории эфира


Рыцари теории эфира
 10.11.2021 - 12:37: ПЕРСОНАЛИИ - Personalias -> WHO IS WHO - КТО ЕСТЬ КТО - Карим_Хайдаров.
10.11.2021 - 12:36: СОВЕСТЬ - Conscience -> РАСЧЕЛОВЕЧИВАНИЕ ЧЕЛОВЕКА. КОМУ ЭТО НАДО? - Карим_Хайдаров.
10.11.2021 - 12:36: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от д.м.н. Александра Алексеевича Редько - Карим_Хайдаров.
10.11.2021 - 12:35: ЭКОЛОГИЯ - Ecology -> Биологическая безопасность населения - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> Проблема государственного терроризма - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> ПРАВОСУДИЯ.НЕТ - Карим_Хайдаров.
10.11.2021 - 12:34: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вадима Глогера, США - Карим_Хайдаров.
10.11.2021 - 09:18: НОВЫЕ ТЕХНОЛОГИИ - New Technologies -> Волновая генетика Петра Гаряева, 5G-контроль и управление - Карим_Хайдаров.
10.11.2021 - 09:18: ЭКОЛОГИЯ - Ecology -> ЭКОЛОГИЯ ДЛЯ ВСЕХ - Карим_Хайдаров.
10.11.2021 - 09:16: ЭКОЛОГИЯ - Ecology -> ПРОБЛЕМЫ МЕДИЦИНЫ - Карим_Хайдаров.
10.11.2021 - 09:15: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Екатерины Коваленко - Карим_Хайдаров.
10.11.2021 - 09:13: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вильгельма Варкентина - Карим_Хайдаров.
Bourabai Research - Технологии XXI века Bourabai Research Institution