Перемещение image по форме во время работы программы

Содержание

Перемещение TImage по форме. Как это сделать?

Posted by Chas under Топик-обзор

dmitriegorovih:

Значит у меня Delphi 7
кидаем на форму image1 и кнопку, чтоб создавались image(ы)
во “всеобщий var” пишем следующие

var
x2,y2,n:integer;
nagata:boolean;

в обработчике onmousedown пишем следующие
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
nagata:=true;
x2:=x;
y2:=y;
end;

в обработчике onMouseMove пишем следующие
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if nagata=true then begin
if xx2 then begin
Timage(sender).Left:=Timage(sender).Left+(x-x2)
end;
if yy2 then begin
Timage(sender).Top:=Timage(sender).Top+(y-y2)
end;
end;
end;

в обработчике onMouseUp пишем следующие
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
nagata:=false;
end;

по нажатию кнопки пишем следующие
procedure TForm1.Button1Click(Sender: TObject);
Var K:Timage;
Begin
K:=Timage.create(self);
k.parent:=self;
k.picture:=image1.picture;
k.onMouseMove:=image1.onMouseMove;
k.onMouseDown:=image1. onMouseDown;
k.onMouseUp:=image1.onMouseUp;
k.name:=’Image_’+inttostr(n);
inc(n);
end;

Ещё один способ:

Кидаем на форму TPanel На нее кидаем TImage, и расстягиваем Image на AlClient чтоб оно заполнило всю панель.
Далее в в обработчике зажатия мышки для Image пишем:

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
const Sc_dragmove = $F012;
begin
ReleaseCapture;
Panel1.Perform(WM_SYSCOMMAND, Sc_dragmove, 0);
end;

Перемещение image по форме во время работы программы

Во время работы над одной программой предо мной встала задача организации перемещения нескольких изображений пользователем с помощью мыши. Я не крутой мастер DELPHI, и найденное мною решение не претендует на полноту, его недостатки я рассмотрю ниже, но я надеюсь, что опыт, приобретённый при решении будет полезен читателю.

Итак, задача. На форме размещены несколько изображений, загружаемых из внешних файлов (их имена 1.bmp, 2.bmp и т.д.).

Изображения должны быть перемещаемыми с помощью мыши.

Первое решение, пришедшее мне в голову — это решение «в лоб». Разместив на форме несколько Image, заставим их перемещаться вместе с мышью. Разместим на форме в нужных нам местах несколько (n) пустых Image, присвоим их свойству Tag значения от 1 до n — это пригодится при создании массива из них. Объявим следующие переменные:

var Pic: array[1..n] of TImage;//Сюда мы занесём наши Image
x0,y0:integer;//Это будут координаты нажатия мыши
flag:boolean;//а это тоже полезная переменная — флажок
Для первого из наших Image создадим обработчики следующих событий

procedure TMainForm.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
If buttonmbLeft Then
flag:=false
Else begin
flag:=true;
x0:=x;
y0:=y
end
end;
< При нажатии левой клавиши мыши над нашим Image запомним координаты нажатия
и установим флажок. Это делается для того, чтобы Image перемещался только при
опущенной левой кнопке мыши>

procedure TMainForm.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
flag:=false
end;

procedure TMainForm.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
If flag Then begin //Если флажок установлен, т.е. нажата левая копка мыши
(Sender As TImage).Left:=(Sender As TImage).Left+x-x0;
(Sender As TImage).Top:=(Sender As TImage).Top+y-y0
//Наш Image начинает перемещаться
end;
end;
Обратите внимание, что перемещается не Image1, а Sender. Созданные нами процедуры будут применены для обработки перемещений всех изображений на форме. Для этого в процедуре создания формы запишем все Image на форме в массив Pic

procedure TMainForm.FormCreate(Sender: TObject);
var i:byte;
begin
For i:=0 To MainForm.ComponentCount-1 Do
If (MainForm.Components[i] Is TImage) Then
Pic[MainForm.Components[i].Tag]:=(MainForm.Components[i] As TImage);
<Здесь мы просматриваем компоненты формы и если рассматриваемый компонент
— TImage присваеваем его в массив Pic c индексом Tag>
For i:=1 To n Do begin
Pic[i].Picture.LoadFromFile(IntToStr(i)+’.bmp’);//Загружаем изображение
Pic[i].OnMouseDown:=Image1MouseDown;
Pic[i].OnMouseMove:=Image1MouseMove;
Pic[i].OnMouseUp:= Image1MouseUp
<Присваеваем нужные процедуры нужным событиям>
end
end;
<В принципе можно было бы обойтись одним циклом For, но, на мой взгляд
два цикла наглядней и проще для понимания>
Итак, полученный код позволяет разместить на форме n изображений и перемещать их с помощью мыши. Можно удовлетвориться полученным решением,если бы не одна страшная проблема — МЕРЦАНИЕ.

Я не большой мастер DELPHI, и я не знаю общего способа, как победить мерцание. Вообще, у меня возникло ощущение, что при перемещеннии Image по форме мерцания не избежать. Буду благодарен тому, кто покажет обратное. Ну в общем применение известных способов, например

MainForm.ControlStyle:=MainForm.ControlStyle+[csOpaque];
или процедуры Invalidate мне не помогло.
Следующим моим шагом было посещение Мастеров Дельфи, где я прочёл статью Михаила Христосенко «Перемещение Image’a по форме во время работы программы». Применение метода

(Sender As TImage).SetBounds((Sender As TImage).Left+x-x0,(Sender As TImage).Top+
y-y0,(Sender As TImage).width,(Sender As TImage).height);
в процедуре Image1MouseMove, рекомендованое Михаилом привело к снижению мерцания, но не избавило от него. Более того, в взрослых программах, таких как например само DELPHI,применяется третий из описанных Михаилом способов — перемещение не изображения, а его рамки.
Тогда я задумался, а не является ли применение TImage для перемещения изображения по форме тупиком. И тут я понял, что знаю компонент, на котором можно разместить изображение, и который не мерцает «по определению». Этот компонент (да простят меня Мастера Дельфи) — форма.

Итак следующий проект состоит из двух форм — FormMain и ImageForm. На ImageForm размещён пустой Image1, занимающий всю клиентскую область ImageForm. ImageForm относится к Available forms — это действие не принципиально, но экономит во время запуска приложения около 100 кб памяти. Свойство BorderStyle для ImageForm устанавливаем bsNone.

Для того, чтобы ImageForm перемещалась за Image1 создаём следующую процедуру:

procedure TImageForm.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
const SC_DragMove = $F012;
begin
ReleaseCapture;
perform(WM_SysCommand, SC_DragMove, 0);
end;
На этом работа над ImageForm заканчивается.

Возвращаемся к FormMain.
Сделаем следующие объявления

implementation
const n=4; // Сколько нам нужно изображений
uses Unit2;
var Fa:array[1..n]of TImageForm;
Теперь нам нужно создать массив Fa, разместить его на форме и заполнить его изображениями. Всё это делается вручную — фокус с Tag тут уже не пройдёт. Делать это лучше не во время создания формы, а например во время активации.

procedure TFormMain.FormActivate(Sender: TObject);
var i:byte;
begin
for i:=1 to n do begin
Fa[i]:=TImageForm.Create(Self);// Создание формы
Fa[i].Parent:=Self;//Без этой строки наши формы будут бегать по всему экрану
Fa[i].Visible:=True; //Вывод формы на экран
Fa[i].Image1.Picture.LoadFromFile(IntToStr(i)+’.bmp’);// Загрузка картинки
Fa[i].Top:=i*50 //Выбор места расположения (здесь ставятся ваши значения)
end;
end;
Другой вариант — разместить на форме Timer с незначительным интервалом и разместить вышеприведённый код в процедуре OnTimer, указав в конце Timer1.Enabled:=false;

Последний штрих — установите «Отображать содержимое окна при его перетаскивании» с помощью следующей процедуры

B:Bool;//Объявите B где-нибудь после implementation
В FormCreate включите следующее
B:=True;
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, 0, @B, SPIF_SENDCHANGE)// Не проверял.
Ура! В созданная таким образом программе перемещаемые изображения не мерцают.

Однако объём памяти, занимаемый ею во время работы весьма велик. Программа состоящая из вышеприведённых процедур занимает на диске около 400 кб, а в ОП — порядка 2 мб. Попробую поискать менее ресурсоёмкое решение.

произвольное перемещение Image по форме

Основная переменная — позиция центра объекта (контейнера с изображением). Дополнительные: размер объекта, номер кадра анимации, количество кадров, частота смены кадров, видим ли объект, длительность его присутствия. Допустим, так:

Далее, все основные операции делятся на 2 категории: расчет позиции и расчет параметров вывода объекта на экран. По идее, можно реализовать данную задачу и без Image, выводя графику на Canvas формы, но подобный подход не исключает и использование данного компонента — просто вместо функции вывода графики на Canvas используйте функцию присваивания изображения компоненту (не помню, как там, возможно, Assign).

Нечто подобное (только в более расширенной версии) некогда было реализовано мною в открытой игре RoboTir (прямая ссылка). Там же реализованы и анимация, и возможность отскакивания изображений от краев экрана.

Перемещение image по форме во время работы программы

Профиль
Группа: Участник
Сообщений: 216
Регистрация: 16.9.2007

Репутация: нет
Всего: 1

Профиль
Группа: Участник
Сообщений: 13
Регистрация: 30.9.2014

Репутация: 0
Всего: 0

Основная переменная — позиция центра объекта (контейнера с изображением). Дополнительные: размер объекта, номер кадра анимации, количество кадров, частота смены кадров, видим ли объект, длительность его присутствия. Допустим, так:

SaiLight
Дата 25.10.2014, 00:01 (ссылка) | (нет голосов) Загрузка .
Код
TMyObject = Record
X, Y: Integer;//Позиция объекта
Width, Height: Integer;//Размеры объекта
FrameNum: Integer;//Номер кадра
FramesCount: Integer;//Количество кадров
FrameSpeed: Integer;//Частота смены кадров
LifeTime: Integer;//Время жизни объекта
LivedSteps: Integer;//Прожитое время
IsVisible: Integer;//Видим ли объект?
end;

Далее, все основные операции делятся на 2 категории: расчет позиции и расчет параметров вывода объекта на экран. По идее, можно реализовать данную задачу и без Image, выводя графику на Canvas формы, но подобный подход не исключает и использование данного компонента — просто вместо функции вывода графики на Canvas используйте функцию присваивания изображения компоненту (не помню, как там, возможно, Assign).

Нечто подобное (только в более расширенной версии) некогда было реализовано мною в открытой игре RoboTir (прямая ссылка). Там же реализованы и анимация, и возможность отскакивания изображений от краев экрана.

Профиль
Группа: Участник
Сообщений: 216
Регистрация: 16.9.2007

Репутация: нет
Всего: 1

Нет вы не поняли я поясню, мне ни анимацию двигать надо а сам Image по форме чтоб он в разных местах появлялся на форме через например 10 секунд) в эти десять секунд он пустой. надо его просто передвигать до очередной анимации сам компонент. Прикреплю проект чтоб понятней стало))
Я не когда не сталкивался с анимацией и с передвижением) если есть возможность дать исходник чтоб покопаться и понят буду благодарен!
Спасибо за внимание!
С уважением,
Денис!

Это сообщение отредактировал(а) Volkogriz — 25.10.2014, 00:39

Присоединённый файл ( Кол-во скачиваний: 3 )
Project.zip 428,91 Kb

Volkogriz
Дата 25.10.2014, 00:19 (ссылка) | (нет голосов) Загрузка .

Профиль
Группа: Участник
Сообщений: 13
Регистрация: 30.9.2014

Репутация: 0
Всего: 0

Ну тогда, опять же, работаем с его позицией, например, изменяя ее в таймере. В представленном мною выше проекте вычисление позиции идет при помощи переменной, отвечающей за направление движения объекта, а отскакивание объекта от краев формы — изменением этой переменной. Вот вырезка кода, отвечающего за эти действия:

SaiLight
Дата 25.10.2014, 00:40 (ссылка) | (нет голосов) Загрузка .
Код
//Пересчет позиции
vNewPos.X := Round(FPos.X + Cos(FMoveAngle * Pi) * (FSpeed — FSlowDown + FPower)) * FDeadSpeed;
vNewPos.Y := Round(FPos.Y + Sin(FMoveAngle * Pi) * (FSpeed — FSlowDown + FPower)) * FDeadSpeed;
//Столкновения
if (vNewPos.X = FBox.X) then FMoveAngle := Pi — FMoveAngle else
if (vNewPos.Y = FBox.Y) then FMoveAngle := -FMoveAngle else
FPos := vNewPos;
if (FMoveAngle > 2 * Pi) then FMoveAngle := 2 * Pi — FMoveAngle;
if (FMoveAngle

За правильность формул не ручаюсь — проект был написан несколько лет назад, но у меня все работало довольно неплохо. В вашем случае, FPos.X и FPos.Y — позиция Image, FSpeed — скорость перемещения объекта, а на FSlowDown, FPower и FDeadSpeed вообще можно не смотреть.

Это сообщение отредактировал(а) SaiLight — 25.10.2014, 00:41

Профиль
Группа: Участник
Сообщений: 216
Регистрация: 16.9.2007

Репутация: нет
Всего: 1

Благодарю за помощь!
Не сочтите за наглость!
Есть просьба не могли бы вы подставить переменные к коду или отредактировать мой проект? просто не могу честно понять (
Если есть время!
С уважением,
Денис!

Это сообщение отредактировал(а) Volkogriz — 25.10.2014, 00:57

Присоединённый файл ( Кол-во скачиваний: 2 )
Project.zip 379,38 Kb

Volkogriz
Дата 25.10.2014, 00:54 (ссылка) | (нет голосов) Загрузка .

Профиль
Группа: Участник
Сообщений: 13
Регистрация: 30.9.2014

Репутация: 0
Всего: 0

Volkogriz, ваш проект у меня не компилируется, поэтому решил реализовать задачу в отдельном проекте — простое перемещение компонента Image с отскакиванием от краев формы. Как я и предполагал, алгоритм не дает реалистичной физики при отражении, но вполне может быть применен уже так или с некоторыми незначительными дополнениями. Если честно, не понимаю, зачем вам нужно именно перемещение объекта в невидимом состоянии, когда можно просто создавать (показывать) его в случайном месте на форме.

Присоединённый файл ( Кол-во скачиваний: 13 )
ImageMove.zip 25,40 Kb

SaiLight
Дата 25.10.2014, 01:58 (ссылка) | (нет голосов) Загрузка .

Профиль
Группа: Участник
Сообщений: 216
Регистрация: 16.9.2007

Репутация: нет
Всего: 1

Я бы с удовольствием так бы и сделал!
Я просто ни когда не имел дела с графикой и без наглядного пособия я буду долго вкуривать)))
Огромное спасибо за помощь!
С уважением,
Денис!

Volkogriz
Дата 25.10.2014, 02:05 (ссылка) | (нет голосов) Загрузка .

Профиль
Группа: Участник
Сообщений: 13
Регистрация: 30.9.2014

Репутация: 0
Всего: 0

Обращайтесь любыми удобными вам способами — помогу, чем удастся. А со случайными координатами — вообще просто:

SaiLight
Дата 25.10.2014, 02:10 (ссылка) | (нет голосов) Загрузка .
Код
imgObject.Left := Random(ClientWidth — imgObject.Width);
imgObject.Top := Random(ClientHeight — imgObject.Height);

Профиль
Группа: Участник
Сообщений: 216
Регистрация: 16.9.2007

Репутация: нет
Всего: 1

Volkogriz
Дата 25.10.2014, 02:22 (ссылка) | (нет голосов) Загрузка .
Google
Дата 12.11.2020, 21:42 (ссылка)

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) — крупнейшем в рунете сборнике материалов по Дельфи
  • По вопросам разработки игр стоит заглянуть сюда

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Girder, Snowy.

Забавное программирование в Delphi

Приведённый здесь материал можно озаглавить не иначе как «Чем заняться программисту, если нечего делать». На самом деле, Delphi настолько интересная среда, что в ней наряду с разработкой серьёзных приложений можно легко увлечься созданием абсолютно бесполезных вещей.

Автоматически нажимающаяся кнопка

Этот компонент представляет из себя кнопку, на которую не надо нажимать, чтобы получить событие OnClick. Достаточно переместить курсор мышки на кнопку. При создании такого компонента традиционным способом, требуется довольно много времени, так как необходимо обрабатывать мышку, перехватывать её и т.д. Однако результат стоит того!

Предлагаю взглянуть на две версии данного компонента. В более простой версии обработчик перемещения мышки просто перехватывает сообщения Windows с нужным кодом и вызывает обработчик события OnClick:

type
TAutoButton1 = class(TButton)
private
procedure WmMouseMove (var Msg: TMessage);
message wm_MouseMove;
end;

procedure TAutoButton1.WmMouseMove (var Msg: TMessage);
begin
inherited;
if Assigned (OnClick) then
OnClick (self);
end;

Вторая версии имеет больше исходного кода, так как в ней я просто пытаюсь повторить событие мышки OnClick когда пользователь перемещает мышку над кнопкой либо по истечении определённого времени. Далее следует объявление класса:

type
TAutoKind = (akTime, akMovement, akBoth);

TAutoButton2 = class(TButton)
private
FAutoKind: TAutoKind;
FMovements: Integer;
FSeconds: Integer;
// really private
CurrMov: Integer;
Capture: Boolean;
MyTimer: TTimer;
procedure EndCapture;
// обработчики сообщений
procedure WmMouseMove (var Msg: TWMMouse);
message wm_MouseMove;
procedure TimerProc (Sender: TObject);
procedure WmLBUttonDown (var Msg: TMessage);
message wm_LBUttonDown;
procedure WmLButtonUp (var Msg: TMessage);
message wm_LButtonUp;
public
constructor Create (AOwner: TComponent); override;
published
property AutoKind: TAutoKind
read FAutoKind write FAutoKind default akTime;
property Movements: Integer
read FMovements write FMovements default 5;
property Seconds: Integer
read FSeconds write FSeconds default 10;
end;

Итак, когда курсор мышки попадает в область кнопки (WmMouseMove), то компонент запускает таймер либо счётчик количества сообщений о перемещении. По истечении определённого времени либо при получении нужного количества сообщений о перемещении, компонент эмулирует событие нажатия кнопкой.

procedure TAutoButton2.WmMouseMove (var Msg: TWMMouse);
begin
inherited;
if not Capture then
begin
SetCapture (Handle);
Capture := True;
CurrMov := 0;
if FAutoKind <> akMovement then
begin
MyTimer := TTimer.Create (Parent);
if FSeconds <> 0 then
MyTimer.Interval := 3000
else
MyTimer.Interval := FSeconds * 1000;
MyTimer.OnTimer := TimerProc;
MyTimer.Enabled := True;
end;
end
else // захватываем
begin
if (Msg.XPos > 0) and (Msg.XPos 0) and (Msg.YPos akTime then
begin
Inc (CurrMov);
if CurrMov >= FMovements then
begin
if Assigned (OnClick) then
OnClick (self);
EndCapture;
end;
end;
end
else // за пределами. стоп!
EndCapture;
end;
end;

procedure TAutoButton2.EndCapture;
begin
Capture := False;
ReleaseCapture;
if Assigned (MyTimer) then
begin
MyTimer.Enabled := False;
MyTimer.Free;
MyTimer := nil;
end;
end;

procedure TAutoButton2.TimerProc (Sender: TObject);
begin
if Assigned (OnClick) then
OnClick (self);
EndCapture;
end;

procedure TAutoButton2.WmLBUttonDown (var Msg: TMessage);
begin
if not Capture then
inherited;
end;

procedure TAutoButton2.WmLButtonUp (var Msg: TMessage);
begin
if not Capture then
inherited;
end;

Как осуществить ввод текста в компоненте Label?

Многие программисты задавая такой вопрос получают на него стандартный ответ «используй edit box.» На самом же деле этот вопрос вполне решаем, хотя лейблы и не основаны на окне и, соответственно не могут получать фокус ввода и, соответственно не могут получать символы, вводимые с клавиатуры. Давайте рассмотрим шаги, которые были предприняты мной для разработки данного компонента.

Первый шаг — это кнопка, которая может отображать вводимый текст:

type
TInputButton = class(TButton)
private
procedure WmChar (var Msg: TWMChar);
message wm_Char;
end;

procedure TInputButton.WmChar (var Msg: TWMChar);
var
Temp: String;
begin
if Char (Msg.CharCode) = #8 then
begin
Temp := Caption;
Delete (Temp, Length (Temp), 1);
Caption := Temp;
end
else
Caption := Caption + Char (Msg.CharCode);
end;

С меткой (label) дела обстоят немного сложнее, так как прийдётся создать некоторые ухищрения, чтобы обойти её внутреннюю структуру. Впринципе, проблему можно решить созданием других скрытых компонент (кстати, тот же edit box). Итак, посмотрим на объявление класса:

type
TInputLabel = class (TLabel)
private
MyEdit: TEdit;
procedure WMLButtonDown (var Msg: TMessage);
message wm_LButtonDown;
protected
procedure EditChange (Sender: TObject);
procedure EditExit (Sender: TObject);
public
constructor Create (AOwner: TComponent); override;
end;

Когда метка (label) создана, то она в свою очередь создаёт edit box и устанавливает несколько обработчиков событий для него. Фактически, если пользователь кликает по метке, то фокус перемещается на (невидимый) edit box, и мы используем его события для обновления метки. Обратите внимание на ту часть кода, которая подражает фокусу для метки (рисует прямоугольничек), основанная на API функции DrawFocusRect:

constructor TInputLabel.Create (AOwner: TComponent);
begin
inherited Create (AOwner);

MyEdit := TEdit.Create (AOwner);
MyEdit.Parent := AOwner as TForm;
MyEdit.W > MyEdit.Height := 0;
MyEdit.TabStop := False;
MyEdit.OnChange := EditChange;
MyEdit.OnExit := EditExit;
end;

procedure TInputLabel.WMLButtonDown (var Msg: TMessage);
begin
MyEdit.SetFocus;
MyEdit.Text := Caption;
(Owner as TForm).Canvas.DrawFocusRect (BoundsRect);
end;

procedure TInputLabel.EditChange (Sender: TObject);
begin
Caption := MyEdit.Text;
Invalidate;
Update;
(Owner as TForm).Canvas.DrawFocusRect (BoundsRect);
end;

procedure TInputLabel.EditExit (Sender: TObject);
begin
(Owner as TForm).Invalidate;
end;

Кнопка со звуком

Когда Вы нажимаете на кнопку, то видите трёхмерный эффект нажатия. А как же насчёт четвёртого измерения, например звука? Ну тогда нам понадобится звук для нажатия и звук для отпускания кнопки. Если есть желание, то можно добавить даже речевую подсказку, однако не будем сильно углубляться.

Компонент звуковой кнопки имеет два новых свойства:

type
TDdhSoundButton = class(TButton)
private
FSoundUp, FSoundDown: string;
protected
procedure MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); override;
published
property SoundUp: string
read FSoundUp write FSoundUp;
property SoundDown: string
read FSoundDown write FSoundDown;
end;

Звуки будут проигрываться при нажатии и отпускании кнопки:

procedure TDdhSoundButton.MouseDown(
Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
inherited;
PlaySound (PChar (FSoundDown), 0, snd_Async);
end;

procedure TDdhSoundButton.MouseUp(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
inherited;
PlaySound (PChar (FSoundUp), 0, snd_Async);
end;

Экранный вирус

Никогда не видели экранного вируса? Представьте, что Ваш экран заболел и покрылся красными пятнами :) А если эта болезнь нападёт на какое-нибудь окно? Всё, что нам надо, это получить контекст устройства при помощи API функции GetWindowDC и рисовать, что душе угодно.

К исходному коду особых комментариев не требуется, скажу лишь только то, что основная часть кода находится в обработчике события OnTimer:

type
TScreenVirus = class(TComponent)
private
FTimer: TTimer;
FInterval: Cardinal;
FColor: TColor;
FRadius: Integer;
protected
procedure OnTimer (Sender: TObject);
procedure SetInterval (Value: Cardinal);
public
constructor Create (AOwner: TComponent); override;
procedure StartInfection;
published
property Interval: Cardinal
read FInterval write SetInterval;
property Color: TColor
read FColor write FColor default clRed;
property Radius: Integer
read FRadius write FRadius default 10;
end;

constructor TScreenVirus.Create (AOwner: TComponent);
begin
inherited Create (AOwner);
FTimer := TTimer.Create (Owner);
FInterval := FTimer.Interval;
FTimer.Enabled := False;
FTimer.OnTimer := OnTimer;
FColor := clRed;
FRadius := 10;
end;

procedure TScreenVirus.StartInfection;
begin
if Assigned (FTimer) then
FTimer.Enabled := True;
end;

procedure TScreenVirus.SetInterval (Value: Cardinal);
begin
if Value <> FInterval then
begin
FInterval := Value;
FTimer.Interval := Interval;
end;
end;

procedure TScreenVirus.OnTimer (Sender: TObject);
var
hdcDesk: THandle;
Brush: TBrush;
X, Y: Integer;
begin
hdcDesk := GetWindowDC (GetDesktopWindow);
Brush := TBrush.Create;
Brush.Color := FColor;
SelectObject (hdcDesk, Brush.Handle);
X := Random (Screen.Width);
Y := Random (Screen.Height);
Ellipse (hdcDesk, X — FRadius, Y — FRadius,
X + FRadius, Y + FRadius);
ReleaseDC (hdcDesk, GetDesktopWindow);
Brush.Free;
end;

Шутки над пользователем

Некоторых пользователей вряд ли можно будет испугать экранным вирусом, однако можно воспользоваться другими способами запугивания, например: прозрачные окошки, недоступные пункты меню с большим количеством подуровней, а так же сообщения об ошибках, которые нельзя убрать.

В приведённом ниже примере при помощи обычного диалогового окна пользователю показывается сообщение об ошибке, причём кнопка «close» накак не хочет нажиматься. У этого диалога есть зависимое окно, которое показывается, при нажатии кнопки «details».

Поддельная форма с сообщением об ошибке имеет кнопку «details», которая открывает вторую
часть формы. Это достигается путём добавления компонента за пределы самой формы:

object Form2: TForm2
AutoScroll = False
Caption = ‘Error’
ClientHeight = 93
ClientW > OnShow = FormShow
object Label1: TLabel
Left = 56
Top = 16
W > Height = 65
AutoSize = False
Caption =
‘Программа выполнила недопустимую ‘ +
‘операцию. Если проблема повторится, ‘ +
‘то обратитесь к разработчику программного обеспечения.’
WordWrap = True
end
object Image1: TImage
Left = 8
Top = 16
W > Height = 41
Picture.Data = <. >
end
object Button1: TButton
Left = 240
Top = 16
W > Height = 25
Caption = ‘Close’
TabOrder = 0
OnClick = Button1Click
end
object Button2: TButton
Left = 240
Top = 56
W > Height = 25
Caption = ‘Details >>’
TabOrder = 1
OnClick = Button2Click
end
object Memo1: TMemo // за пределами формы!
Left = 24
Top = 104
W > Height = 89
Color = clBtnFace
Lines.Strings = (
‘AX:BX 73A5:495B’
‘SX:PK 676F:FFFF’
‘OH:OH 7645:2347’
‘Crash 3485:9874’
»
‘What’#39’s going on here?’)
TabOrder = 2
end
end

Когда пользователь нажимает кнопку «details», то программа просто изменяет размер формы:

procedure TForm2.Button2Click(Sender: TObject);
begin
Height := 231;
end;

Вторая форма, которая наследуется от первой имеет перемещающуюся кнопку «close»:

procedure TForm3.Button1Click(Sender: TObject);
begin
Button1.Left := Random (ClientWidth — Button1.Width);
Button1.Top := Random (ClientHeight — Button1.Height);
end;

В заключении, можно сделать дырку в окне, используя API функцию SetWindowRgn:

procedure TForm1.Button4Click(Sender: TObject);
var
HRegion1, Hreg2, Hreg3: THandle;
Col: TColor;
begin
ShowMessage (‘Ready for a real crash?’);
Col := Color;
Color := clRed;
PlaySound (‘boom.wav’, 0, snd_sync);
HRegion1 := CreatePolygonRgn (Pts,
sizeof (Pts) div 8,
alternate);
SetWindowRgn (
Handle, HRegion1, True);
ShowMessage (‘Now, what have you done?’);
Color := Col;
ShowMessage (‘Вам лучше купить новый монитор’);

Перемещение Image’a по форме во время работы приложения средствами Delphi

Многие, наверно, сталкивались с проблемой перемещения Image’a по форме. Решить ее можно тремя способами (может есть и больше, но я знаю только три).

Способ первый. Его суть заключается в том, что свойства Left и Top картинки изменяются на разницу между начальными и конечными координатами (нажатия и отпускания мыши соответственно). Этот способ самый простой и надежный, но у него есть один недостаток: left и top изменяются по очереди, что приводит к заметному мерцанию картинки. Тем не менее мы этот способ рассмотрим. Не забудьте положить на форму Image и вставить в нее какую-нибудь картинку. Для начала необходимо объявить глобальные переменные (они объявляются в разделе Implementation) x0, y0:integer — они будут запоминать начальные координаты. И еще нам понадобится переменная move типа boolean, чтобы нам отличать перемещение мыши над картинкой, от попытки ее сдвинуть. Эти объявления делаются примерно так (участок кода):

var x0,y0:integer;
move:boolean;

Теперь напишем обработчик OnMouseDown для нашей картинки:

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if button<>mbLeft then move:=false //если нажали не левой кнопкой, то перемещать не будем!
else begin
move:=true;
x0:=x; //запоминаем начальные координаты
y0:=y; //запоминаем начальные координаты
end;
end;

В этом участке кода проверяется какой кнопкой нажали на картинку. Если левой, то запоминаем координаты, а если любой другой, то перемещать нельзя.

Теперь напишем обработчик OnMouseMove для нашей картинки:

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if move then begin
image1.Left:=image1.Left+x-x0; // Изменяем позицию левого края
image1.Top:=image1.Top+y-y0; // Изменяем позицию верхнего края
end;
end;

Ну и, наконец, обработчик OnMouseUp для нашей картинки будет таким:

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
move:=false;
end;

Здесь все очень просто. Когда кнопка отпускается, то переменной move присваивается значение false, чтобы до следующего клика по картинке ее нельзя было сдвинуть.

Этот способ довольно прост, как для понимания, так и для реализации. Но такой же алгоритм перемещения можно реализовать немного красивее. У некоторых компонентов, в том числе и Image, есть такая классная процедура SetBounds(Left,Top,Width,Height), которая может изменять сразу все четыре параметра. Таким образом событие OnMouseMove можно изменить так:

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if move then begin
image1.SetBounds(image1.Left+x-x0,image1.Top+y-y0,image1.width,image1.height);
end;
end;

Но есть еще один очень интересный выход: по экрану можно перемещать не саму картинку, а только ее рамку, когда пользователь выберет место для картинки и отпустит кнопку — она туда переместиться. Для этого нам понадобится еще одна глобальная переменная: rec: TRect, которая будет хранить параметры картинки. Теперь слегка изменим обработчики событий для картинки. Таким образом все в целом будет выглядеть так:

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if button<>mbLeft then move:=false
else begin
move:=true;
x0:=x;
y0:=y;
rec:=image1.BoundsRect; //запоминаем контур картинки
end;
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if move then begin
Form1.Canvas.DrawFocusRect(rec); //рисуем рамку
with rec do begin
left:=Left+x-x0;
top:=Top+y-y0;
right:=right+x-x0;
bottom:=bottom+y-y0;
x0:=x;
y0:=y; // изменяем координаты
end;
Form1.Canvas.DrawFocusRect(rec); // рисуем рамку на новом месте
end;
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Form1.Canvas.DrawFocusRect(rec);
with image1 do begin
setbounds(rec.left+x-x0,rec.top+y-y0,width,height); //перемещаем картинку
move:=false;
end;
end;

Поскольку DrawFocusRect рисует рамку методом Xor, то при повторном вызове этой функции с теми же параметрами, рамка стирается.

Этот очень красивый метод добавит в ваши программы много интересного. Так что пользуйтесь.

Пособие по написанию своих компонентов на Delphi для начинающих

Теперь изучим более сложные вещи:

Во-первых, потому что когда я очень хотел написать свой первый компонент, я прочитал две книги, и у меня ничего интересного собственно не вышло. Потом я прочитал еще одну книгу (в ней хотя бы пример рабочий был), вроде разобрался. Но там был разобран такой простой компонент, что все более сложное мне приходилось делать самому, иногда методом тыка, иногда сидел разбирался и так далее. Результат — разобрался, чего и вам желаю и надеюсь помочь этим пособием.

Все мои готовые компоненты можно найти на сайте http://delphid.dax.ru.

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

К стандартным наборам компонентов, которые поставляются вместе с Дельфи можно создать еще массу своих интересных компонентов, которые заметно упростят вам жизнь (это я вам гарантирую). А еще можно зайти на какой-нибудь крутой сайт о Дельфи и там скачать кучу крутых компонентов, и на их основе сделать какую-нибудь крутую прогу. Так же компоненты освобождают вас от написания «тысячи тонн словесной руды». Пример: вы создали компонент — кнопку, при щелчке на которую данные из Memo сохранятся во временный файл. Теперь как только вам понадобится эта функция вы просто ставите этот компонент на форму и наслаждаетесь результатом. И не надо будет каждый раз прописывать это, для ваших новых программ — просто воспользуйтесь компонентом.

Первым шагом нужно ответить себе на вопрос: «Для чего мне этот компонент и что он будет делать?». Затем необходимо в общих чертах продумать его свойства, события, на которые он будет реагировать и те функции и процедуры, которыми компонент должен обладать. Затем очень важно выбрать «предка» компонента, то есть наследником какого класса он будет являться. Тут есть два пути. Либо в качестве наследника взять уже готовый компонент (то есть модифицировать уже существующий класс), либо создать новый класс.

Для создания нового класса можно выделить 4 случая:

1. Создание Windows-элемента управления (TWinControl)

2. Создание графического элемента управления (TGraphicControl)

3. Создание нового класса или элемента управления (TCustomControl)

4. Создание невизуального компонента (не видимого) (TComponent)

Теперь попробую объяснить что же такое визуальные и невизуальные компоненты. Визуальные компоненты видны во время работы приложения, с ними напрямую может взаимодействовать пользователь, например кнопка Button — является визуальным компонентом.

Невизуальные компоненты видны только во время разработки приложения (Design-Time), а во время работы приложения (Run-Time) их не видно, но они могут выполнять какую-нибудь работу. Наиболее часто используемый невизуальный компонент — это Timer.

Итак, что бы приступить от слов к делу, попробуем сделать какой-нибудь супер простой компонент (только в целях ознакомления с техникой создания компонентов), а потом будем его усложнять.

Рассматривать этот шаг я буду исходя из устройства Дельфи 3, в других версиях этот процесс не сильно отличается. Давайте попробуем создать кнопку, у которой будет доступна информация о количестве кликов по ней.

Чтобы приступить к непосредственному написанию компонента, вам необходимо сделать следующее:

  • Закройте проекты, которые вы разрабатывали (формы и модули)
  • В основном меню выберите Component -> New Component.
  • Перед вами откроется диалоговое окно с названием «New Component»
  • В поле Ancestor Type (тип предка) выберите класс компонента, который вы хотите модифицировать. В нашем случае вам надо выбрать класс TButton
  • В поле Class Name введите имя класса, который вы хотите получить. Имя обязательно должно начинаться с буквы «T». Мы напишем туда, например, TCountBtn
  • В поле Palette Page укажите имя закладки на которой этот компонент появиться после установки. Введем туда MyComponents (теперь у вас в Делфьи будет своя закладка с компонентами!).
  • Поле Unit File Name заполняется автоматически, в зависимости от выбранного имени компонента. Это путь куда будет сохранен ваш модуль.
  • В поле Search Path ничего изменять не нужно.
  • Теперь нажмите на кнопку Create Unit и получите следующее:

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TCountBtn = class(TButton)

procedure Register;
begin
RegisterComponents(‘MyComponents’, [TCountBtn]);
end;

Что же здесь написано? да собственно пока ничего интересного. Здесь объявлен новый класс TCountBtn и процедура регистрации вашего компонента в палитре компонентов.

Директива Private Здесь вы будете писать все скрытые поля которые вам понадобятся для создания компонента. Так же в этой директиве описываются процедуры и функции, необходимые для работы своего компонента, эти процедуры и функции пользователю не доступны. Для нашего компонент мы напишем туда следующее (запись должна состоять из буквы «F» имени поля: тип этого поля):

Буква «F» должна присутсвовать обязательно. Здесь мы создали скрытое поле Count, в котором и будет храниться число кликов по кнопке.

Директива Protected . Обычно я здесь пишу различные обработчики событий мыши и клавиатуры. Мы напишем здесь следующую строку:

procedure Click; override;

Это указывает на то, что мы будем обрабатывать щелчок мыши по компоненту. Слово «override» указывает на то, что мы перекроем стандартное событие OnClick для компонента предка.

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

Осталась последняя директива Published. В ней также используется объявления доступных пользователю, свойств и методов компонента. Для того, чтобы наш компонент появился на форме необходимо описать метод создания компонента (конструктор), можно прописать и деструктор, но это не обязательно. Следует обратить внимание на то, что если вы хотите, чтобы какие-то свойства вашего компонента появились в Инспекторе Объектов (Object Inspector) вам необходимо описать эти свойства в директиве Published. Это делается так: property Имя_свойства (но помните здесь букву «F» уже не нужно писать), затем ставиться двоеточие «:» тип свойства, read процедура для чтения значения, write функция для записи значения;. Но похоже это все сильно запутано. Посмотрите, что нужно написать для нашего компонента и все поймете:

constructor Create(aowner:Tcomponent);override; //Конструктор
property Count:integer read FCount write FCount; //Свойство Count

Итак все объявления сделаны и мы можем приступить к написанию непосредственно всех объявленных процедур.

Начнем с написания конструктора. Это делается примерно так:

constructor TCountBtn.Create(aowner:Tcomponent);
begin
inherited create(Aowner);
end;

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

Теперь мы напишем процедуру обработки щелчка мышкой по кнопке:

procedure Tcountbtn.Click;
begin
inherited click;
FCount:=FCount+1;
end;

«Inherited click» означает, что мы повторяем стандартные методы обработки щелчка мышью (зачем напрягаться и делать лишнюю работу:)).

У нас осталась последняя процедура ShowCount. Она может выглядеть примерно так:

procedure TCountBtn.ShowCount;
begin
Showmessage(‘По кнопке ‘+ caption+’ вы сделали: ‘+inttostr(FCount)+’ клик(а/ов)’);
end;

Здесь выводится сообщение в котором показывается количество кликов по кнопке (к тому же выводится имя этой кнопки, ну это я добавил только с эстетической целью).

И если вы все поняли и сделали правильно, то у вас должно получится следующее:

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;

type
TCountBtn = class(TButton)
private
< Private declarations >
FCount:integer;
protected
< Protected declarations >
procedure Click;override;
public
< Public declarations >
procedure ShowCount;
published
< Published declarations >
property Count:integer read FCount write FCount;
constructor Create(aowner:Tcomponent);override;
end;

procedure Register;
begin
RegisterComponents(‘Mihan Components’, [TCountBtn]);
end;

constructor TCountBtn.Create(aowner:Tcomponent);
begin
inherited create(Aowner);
end;

procedure Tcountbtn.Click;
begin
inherited click;
FCount:=FCount+1;
end;

procedure TCountBtn.ShowCount;
begin
Showmessage(‘По кнопке ‘+ caption+’ вы сделали: ‘+inttostr(FCount)+’ клик(а/ов)’);
end;
end.

Скорее сохраняйтесь, дабы не потерять случайным образом байты набранного кода:)).

Если вы сумели написать и понять, все то что здесь предложено, то установка компонента не должна вызвать у вас никаких проблем. Все здесь делается очень просто. В главном меню выберите пункт Component -> Install Component. перед вами открылось диалоговое окно Install Component. В нем вы увидите две закладки: Into exsisting Package и Into new Package. Вам предоставляется выбор установить ваш компонент в уже существующий пакет или в новый пакет соответственно. Мы выберем в уже существующий пакет.

В поле Unit File Name напишите имя вашего сохранненого модуля (естественно необходимо еще и указать путь к нему), а лучше воспользуйтесь кнопкой Browse и выберите ваш файл в открывшемся окне.

В Search Path ничего изменять не нужно, Делфьи сама за вас все туда добавит.

В поле Package File Name выберите имя пакета, в который будет установлен ваш компонент. Мы согласимся с предложенным по умолчанию пакетом.

Теперь нажимаем кнопочку Ok. И тут появиться предупреждение Package dclusr30.dpk will be rebuilt. Continue? Дельфи спрашивает: «Пакет такой-то будет изменен. Продолжить?». Конечно же надо ответить «Да». И если вы все сделали правильно, то появиться сообщение, что ваш компонент установлен. Что ж можно кричать Ура! Это ваш первый компонент.

Теперь мы попробуем создать свойство нестандартного типа. Рассмотрим это на примере метки — TLabel. У этого компонента есть такое свойство: Alignment. Оно может принимать следующие значения: taLeftJustify, taCenter, taRightJustify. Приступаем к созданию свойства. Ничего интересного мне придумать не удалось, но тем не менее я вам покажу это на примере того свойства, которое я придумал. Оно очень простое и поможет вам разобраться. Свойство будет называться ShowType (тип TShowTp), в нашем компоненте оно будет отвечать за отображение свойства Count. Если пользователь установит свойство ShowType в Normal, то кнопка будет работать, как и работала. А если пользователь присвоит этому свойтсву значение CountToCaption, то количество кликов, будет отображаться на самой кнопке.

Для начале нам необходимо объявить новый тип. Описание типа нужно добавить после слова Type. Вот так это выглядело вначале:

type
TCountBtn = class(TButton)

Вот так это должно выглядеть:

TShowTp = (Normal, CountToCaption);

Здесь мы объявили новый тип TShowTp, который может принимать только два значения. Все значения, которые вы хотите добавить перечисляются через запятую.

Теперь нам понадобиться создать поле этого типа. Это мы уже умеем и делать и поэтому не должно вызвать никаких сложностей. В директиву Private напишите:

Мы создали поле ShowType, типа TShowTp.

Конечно же необходимо добавить это свойство в инспектор объектов:

property ShowType: TshowTp read FshowType write FShowType;

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

procedure Tcountbtn.Click;
begin
inherited click;
FCount:=Fcount+1;
if ShowType = Normal then
Caption:=Caption;
if ShowType = CountToCaption then
Caption:=’Count= ‘+inttostr(count);
end;

Объясню что произошло. Вначале мы увеличиваем счетчик на единицу. Затем проверяем какое значение имеет свойство ShowType. Если Normal, то ничего не делаем, а если CountToCaption, то в надпись на кнопке выводим количество кликов. Не так уж и сложно как это могло показаться с первого раза.

Очень часто бывает, что вам необходимо вставить в компонент, какой-нибудь другой компонент, например, таймер. Как обычно будем рассматривать этот процесс на конкретном примере. Сделаем так, что через каждые 10 секунд значение счетчика кликов будет удваиваться. Для этого мы встроим таймер в нашу кнопку. Нам понадобиться сделать несколько несложных шагов.

После раздела uses, где описаны добавленные в программу модули, объявите переменную типа TTimer. Назовем ее Timer. Приведу небольшой участок кода:

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;

var Timer: TTimer;
type

Дальше в директиву Protected необходимо добавить обработчик события OnTimer для нашего таймера. Это делается так:

procedure OnTimer(Sender: TObject);

Поскольку наш таймер это не переменная, а компонент, его тоже надо создать, для этого в конструктор нашей кнопки напишем:

constructor TCountBtn.Create(aowner:Tcomponent);
begin
inherited create(Aowner);
Timer:=TTimer.Create(self);
Timer.Enabled:=true;
Timer.OnTimer:=OnTimer;
Timer.Interval:=10000;
end;

Здесь создается экземпляр нашего таймера и его свойству Iterval (измеряется в миллисекундах) присваивается значение 10000 (то есть 10 секунд если по простому).

Собственно осталось написать саму процедуру OnTimer. Я сделал это так:

procedure TCountBtn.OnTimer(Sender: TObject);
begin
FCount:=FCount*2;
end;

Вот примерно то, что у вас должно получиться в конце:

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;

var Timer: TTimer;
type
TShowTp = (Normal, CountToCaption);
TCountBtn = class(TButton)

FCount:integer;
FShowType:TShowTp;
protected
< Protected declarations >
procedure OnTimer(Sender: TObject);
procedure Click;override;
public
< Public declarations >
procedure ShowCount;
published
< Published declarations >
property Count:integer read FCount write FCount;
constructor Create(aowner:Tcomponent);override;
property ShowType: TshowTp read FshowType write FShowType;
end;

procedure Register;
begin
RegisterComponents(‘Mihan Components’, [TCountBtn]);
end;

constructor TCountBtn.Create(aowner:Tcomponent);
begin
inherited create(Aowner);
Timer:=TTimer.Create(self);
Timer.Enabled:=false;
Timer.OnTimer:=OnTimer;
Timer.Interval:=1000;
end;

procedure Tcountbtn.Click;
begin
inherited click;
FCount:=Fcount+1;
Timer.Enabled:=true;
if ShowType = Normal then
Caption:=Caption;
if ShowType = CountToCaption then
Caption:=’Count= ‘+inttostr(count);
end;

procedure TCountBtn.ShowCount;
begin
Showmessage(‘По кнопке ‘+ caption+’ вы сделали: ‘+inttostr(FCount)+’ клик(а/ов)’);
end;

procedure TCountBtn.OnTimer(Sender: TObject);
begin
FCount:=FCount*2;
end;

Если у вас что-то не сработало, то в начале проверьте все ли у вас написано правильно. Затем проверьте может у вас не хватает какого-нибудь модуля в разделе Uses.

Очень часто бывает необходимо переустановить ваш компонент.

Если вы попробуете сделать это путем выбора Component->Install Component, то Дельфи вас честно предупредит о том, что пакет уже содержит модуль с таким именем. Перед вами открывается окно с содержимым пакета. В нем вы должны найти имя вашего компонента и удалить его (либо нажать кнопочку Remove). Теперь в пакете уже нет вашего компонента. Затем проделайте стандартную процедуру по установке компонента.

Работа с буфером обмена в Delphi

Правила форума «Delphi: Звук, графика и видео»

Андрей Таманцев
WinSov.com

Каждый юзер наверняка сталкивался с помещением информации в буфер и извлечением ее оттуда. Тот же пресловутый Ворд при нажатии кнопки «копировать» помещает выделенный текст в буфер, а при нажатии «вставить» — извлекает его. Таким же образом помещаться в буфер могут изображения и данные разных форматов. Итак, буфер — это специальная область оперативной памяти в которую Windows помещает пользовательские данные для обмена между разными приложениями или внутри одного приложения.

Для того, чтобы работать с буфером обмена из Delphi, необходимо подключить к своему приложению модуль clipbrd.pas, то есть пишем в uses clipbrd.pas.

РАБОТА С ТЕКСТОМ

Самый простой способ поместить в буфер обмена какой-либо текст — это добавить следующий код:

Чтобы извлечь текст из буфера, можно сделать так (поместим текст в Memo1:TMemo):

РАБОТА С ИЗОБРАЖЕНИЯМИ

Если вы работаете с компонентом Image1:Timage, то самым простым способом поместить в него изображение из буфера будет присвоение хэндла данных Clipboard’a хэндлу Tbitmap:

КАК УЗНАТЬ ФОРМАТ ДАННЫХ БУФЕРА В ДАННЫЙ МОМЕНТ

Для этого существует специальная функция Clipboard.HasFormat(Format: WORD):boolean;
Функция возвращает true, если в буфере именно этот формат, в противном случает возвращает false.
Описание форматов:
CF_TEXT — Обычный текст, заканчивающийся
CF_BITMAP — Битмап изображение *.bmp
CF_METAFILEPICT — Метафайл изображение *.wmf
CF_PICTURE — Объект типа TPicture
CF_COMPONENT — Компонента Delphi (Tbutton, например)
CF_OBJECT — Любой объект в Delphi типа TPersistent

Чтобы очистить буфер обмена от содержащихся в нем данных, используйте процедуру Clipboard.clear;

ОТКРЫВАЕМ // ЗАКРЫВАЕМ

Если вы хотите, чтобы все приложения, кроме вашего не могли изменять содержимое буфера, используйте

После пользования буфером, его необходимо закрывать процедурой Clipboard.Close;

З.Ы. Многие объекты в Delphi изначально имеют методы, позволяющие помещать данные в буфер и извлекать их оттуда, примером может служить Tpicture.

Как писать Win32API приложения на Delphi

Sergey Stolyarov
WinSov.com

Главная проблема, возникающая при написании WinAPI приложений — это неудобство ручного создания всех окон приложения. Требуется вызывать функцию CreateWindow для каждого (в том числе и дочернего) окна программы, а затем еще и менять шрифт в некоторых из них. Лучшим на мой взгляд выходом из этой ситуации является использование ресурсов диалоговых окон (dialog box resources) для соэдания всех окон приложения. В этой статье я расскажу как это делается в Delphi на примере простого приложения с одним главным и двумя (модальными) окнами.

Шаг 1. Создание ресурсов диалоговых окон

Для создания ресурсов я использовал редактор ресурсов из состава Borland C++ 5.02. В Borland Resource Workshop 4.5 все почти аналогично. Создаем главное окно, вот его код:

500 DIALOGEX 0, 0, 240, 117
EXSTYLE WS_EX_DLGMODALFRAME | WS_EX_APPWINDOW | WS_EX_CLIENTEDGE
STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_OVERLAPPED | WS_VISIBLE | WS_CAPTION |
WS_SYSMENU | WS_MINIMIZEBOX
CLASS «WndClass1»
CAPTION «Главное окно приложения»
MENU 300
FONT 8, «MS Sans Serif», 400, 0
LANGUAGE LANG_RUSSIAN , 0
<
CONTROL «OK», IDOK, «BUTTON», BS_DEFPUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP,
19, 94, 50, 14, WS_EX_CLIENTEDGE
CONTROL «Cancel», IDCANCEL, «BUTTON», BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP,
96, 94, 50, 14, WS_EX_CLIENTEDGE
CONTROL «Help», IDHELP, «BUTTON», BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP,
172, 94, 50, 14, WS_EX_CLIENTEDGE
CONTROL «Группа», -1, «button», BS_GROUPBOX | BS_RIGHT | WS_CHILD | WS_VISIBLE | WS_GROUP,
20, 9, 100, 76
CONTROL «Кнопка 1», 105, «button», BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP,
28, 21, 60, 12
CONTROL «Кнопка 2», 106, «button», BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP,
28, 37, 60, 12
CONTROL «Кнопка 3», 107, «button», BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP,
28, 53, 60, 12
CONTROL «ListBox1», 108, «listbox», LBS_NOTIFY | LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_CHILD |
WS_VISIBLE | WS_BORDER | WS_TABSTOP,
132, 13, 92, 72
>

Обратите внимание на поле CLASS. В нем должно стоять то же значение, что и в поле lpszClassName записи TWndClassEx основной программы. В редакторе ресурсов значение этого поля можно изменить в окне свойств ресурса.

Два других окна создаются как обычные ресурсы, поэтому их код я здесь не привожу.

Шаг 2. Основная программа.

Текст программы в нашем случае несколько отличается от текста, например, winmin. Регистрация оконного класса:

wc.cbSize:=sizeof(wc);
wc.style:=cs_hredraw or cs_vredraw;
wc.lpfnWndProc:=@WindowProc;
wc.cbClsExtra:=0;
wc.cbWndExtra:=DLGWINDOWEXTRA;
wc.hInstance:=HInstance;
wc.hIcon:=LoadIcon(hInstance, ‘MAINICON’);
wc.hCursor:=LoadCursor(0,idc_arrow);
wc.hbrBackground:=COLOR_BTNFACE+1;
wc.lpszMenuName:=nil;
wc.lpsz ;
RegisterClassEx(wc);

Обратите внимание, что в поле cbWindowExtra стоит константа DLGWINDOWEXTRA, если бы её там не было, нам не удалось бы создать главное окно, основанное на ресурсе Dialog Box. Кроме того, в поле lpszClassName стоит то же значение, что и в соответствующем поле описания ресурса окна.

Итак, класс создан и зарегистрирован, теперь создаем главное окно из ресурса: MainWnd:=CreateDialog(hInstance, ‘#500’, 0, nil);

Напоминаю, что ‘#500’ значит имя ресурса окна. Не забудьте подключить откомпилированный файл сценария ресурса к программе при помощи директивы

Шаг 3. Оконная функция.

Оконная функция ничем не отличается от обычной:

function WindowProc(wnd:HWND; Msg : Integer; Wparam:Wparam; Lparam:Lparam):Lresult; stdcall;
var nCode, ctrlID, size : word;
pt : TPoint;
s : string;
Begin
case msg of
wm_command :
Begin
nCode:=hiWord(wParam);
ctrl > case ctrlID of
IDHELP : begin
DialogBox(hInstance,’#501′,wnd,@DialogFunc);
end;

DialogBoxParam(hInstance,’#503′,wnd,@DialogFunc2, Integer(pd));
s := ‘Login: ‘+pd^.login;
s := s + ‘ ‘ + ‘Pass: ‘+pd^.pass;
ListBox_AddString(lb, s);

IDCANCEL : begin
DestroyWindow(wnd);
end;
end;
End;

wm_destroy :
Begin
Dispose(pd);
postquitmessage(0); exit;
Result:=0;
End;

else Result:=DefWindowProc(wnd,msg,wparam,lparam);
end;
end;

Шаг 4. Цикл сбора сообщений.

Цикл сбора сообщений следует изменить следующим образом, как при использовании немодальных диалоговых окон. Можно, правда, оставить все как есть, но тогда вы не сможете использовать клавиатуру для перемещения между дочерними окнами, использования кнопок «по умолчанию» и т.д.

While GetMessage(Mesg,0,0,0) do
begin
if mainWnd<>0 then
if IsDialogMessage(mainWnd,Mesg) then continue;
TranslateMessage(Mesg);
DispatchMessage(Mesg);
end;

После нажатия кнопки «ОК» появляется еще одно окно. Если в нем ввести текст и нажать «ОК», этот текст будет добавлен в Listbox.

Создание рамки для перемещения Image

При создании одной из своих программ, мне потребовалось организовать возможность перемещения элементов Image внутри формы и возможность изменять их размеры. Сама по себе задача не сложная, сложность заключалась в том, как все это делать при помощи мышки, в лучших традициях фотошопа и еже с ним. Как и любой другой начинающий программист, я полез в Интернет. Там я нашел, по меньшей мере, четыре способа решения моей проблемы, но все они обладали различными недостатками, в результате чего пришлось писать свой собственный код. Получился достаточно длинный код, но зато сама рамка не хуже, чем у профессионалов.

Создадим новый проект. Название формы делаем MainForm. Кидаем на форму один Image и восемь Shape. В раздел uses добавляем модуль jpeg. Это необходимо, что бы наше приложение понимало данный формат. Загружаем в Image любую картинку. Элементы Shape будут играть роль флажков, при помощи которых мы будем изменять размер нашей картинки. Первоначально элемент Shape представляет собой белый квадрат с черной рамкой. Лично я предпочитаю оставить данное сочетание цветов как есть. А вот размеры всех Shape (свойства Width и Height) сделаем 8 на 8 пикселей.

Саму рамку мы будем рисовать на канве формы. Но, прежде всего, нам нужны переменные, куда мы будем сохранять ее размеры. Для этой цели мы воспользуемся записью (представление). В раздел type, перед строкой TMainForm = class(TForm) записываем соответствующий код. Должно получиться вот так:

В данной программе нам не обойтись без своих собственных подпрограмм. Давайте напишем их. В раздел private пишем:

А вот и сами подпрограммы:

Подпрограмма PaintFlagi выстраивает элементы Shape по периметру Image вне зависимости от его расположения на форме и размеров. По ходу выполнения программы будет необходимость делать Shape видимыми или невидимыми, и этим займутся подпрограммы FlagNoVisible и FlagVisible.

Нам также понадобятся переменные. Опишем их:

Как я уже писал, саму рамку мы будем рисовать на канве. Но для этого необходима предварительная подготовка. В событие Activate нашей формы пишем код:

Первая строка делает невидимыми Shape. Вторая строка устанавливает такой режим карандаша, что при первой прорисовки рамки она будет рисоваться, а при повторной прорисовки рамка будет удаляться, восстанавливая первоначальную картинку. Третья строка делает заливку рамки бесцветной. При желании сюда же можно прописать код ширины рамки и ее цвета:

MainForm.Canvas.Pen.Color := цвет.
MainForm.Canvas.Pen.W >А теперь заставим Image перемещаться по форме. В событие MouseDown элемента Image пишем такой код:

В событие MouseMove мы пишем:

В событие MouseUp пишем:

Хотелось бы обратить внимание на две вещи: программа реагирует только на нажатие левой кнопки мыши, и при нажатии левой кнопки мыши рамка появляется, а при отжатии (без перемещения) исчезает. Весьма полезные свойства. Дело в том, что вторым свойством не обладает ни один из четырёх примеров, которые я нашёл в Интернете. А что касается первого свойства, то у одного примера есть такой недостаток: перенесешь картинку из одного места в другое, нажмешь на картинку правой кнопкой мыши или колёсиком, и картинка перемещается на своё старое место. Весьма удручающая картина.

А теперь заставим картинку менять свои размеры. Так как этот код ну очень похож на тот код, который я уже описал, я не буду его объяснять так же подробно.

Здесь мы изменяем высоту Image по верхнему флажку. Но следует отметить, что у прямоугольника, нарисованного на канве, в отличие от Image нет таких свойств как высота и ширина. Есть ближние точки и дальние точки. И что бы иметь возможность изменять координату ближней точки, не изменяя координаты дальней точки, мы пользуемся кодом:

А что бы вычислить новую высоту картинки, мы используем код:

Что бы изменять ширину картинки левым флагом, мы проделываем тот же самый фокус.

Совмещаем код левого и верхнего флагов, и получаем код верхнего левого флага.

Верхний левый флаг:

Для изменения ширины картинки правым флагом, необходимо просто изменять ширину.

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

Нижний правый флаг:

Верхний правый флаг:

Нижний левый флаг:

И в заключении я хотел бы сказать про эффект, который я назвал «ломаная рамка». Визуально это выглядит так. При нажатии кнопки на картинке, рамка вырисовывается частично: в тех местах, где рамка пересекает флажки, линия рамки отсутствует. В том примере, который я написал, данный эффект отсутствует вследствие того, что я вынес флажки за пределы рамки. Но если флажки расставить так, что бы линия рамки пересекала их по середине, как это реализовано в Delphi, то мы обязательно столкнёмся с данным эффектом. А дело вот в чем. Посмотрим код, который реализовывается при нажатии левой кнопки мыши на Image:

Как видно из кода, команда, которая делает элементы Shape невидимыми, выполняется раньше, чем команда, которая рисует рамку. Но в реальности в начале рисуется рамка, а только потом элементы Shape становятся невидимыми вместе с той частью рамки, где линия рамки проходит через флаги. Почему происходит так, я могу только догадываться. Этого эффекта можно избежать, если при помощи таймера искусственно отстрочить выполнение команды:

на одну миллисекунду (минимальное значение таймера). Но тогда вылезет другая проблема. Если слишком резко переместить картинку, то первой уже выполниться команда, которая должна состирать рамку. Вот тот код:

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

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

Перемещение image по форме во время работы программы

Рисунок 14.122. Инструмент « Перемещение » на панели инструментов

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

4.3.1. Активация инструмента

Инструмент можно активировать несколькими способами:

через меню изображения Инструменты → Преобразование → Перемещение .

щелчком по значку инструмента на панели инструментов,

либо используя клавишу быстрого доступа M .

Инструмент перемещения автоматически активируется при создании направляющей.

Holding down the Space bar changes the active tool to Move temporarily. The Move tool remains active as long as the space bar is held down. The original tool is reactivated after releasing the space bar. This behavior exists only if the Switch to Move tool option is enabled in Edit → Preferences → Image Windows → Space Bar .

4.3.2. Параметры

Рисунок 14.123. Параметры инструмента « Перемещение »

Обычно параметры инструмента отображаются в панели, присоединенной к панели инструментов, как только вы активируете его. Если их там нет, вы можете перейти к этой панели, выбрав в меню пункт Окна → Панели → Параметры инструмента .

Выбор этого параметра сохраняется после деактивации инструмента.

Переключатель инструмента (Shift)

Если инструмент работает со слоями

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

Если в изображении есть направляющая, она будет подсвечена красным цветом при прохождении указателя мыши над ней. Подсвеченную направляющую можно переместить.

At the point of intersection of two guides, you can click-and-drag to move them together. This is useful when the guides are used to mark a point, rather than a pair of lines (e.g, as is the case for the mandala symmetry guides, which mark the symmetry point of origin).

Переместить активный слой

Only the current layer will be moved (if smaller than canvas). This may be useful if you want to move a layer with transparent areas, where you can easily pick the wrong layer through these transparent areas.

You also can move the active layer by setting its offset in the Edit Layer Attributes dialog.

Если инструмент работает с выделениями

Если инструмент работает с контурами

Используемый по умолчанию вариант. При прохождении над видимым контуром значок указателя мыши принимает форму кисти с указующим пальцем. Этот контур можно щелкнуть и перетащить (на время перемещения контур становится активным).

Переместить активный контур

Можно перемещать только активный контур. Любой контур можно сделать активным в диалоге контуров.

4.3.3. Общее о работе инструмента перемещения

Инструмент перемещения позволяет передвигать только рамку выделения. Для этого в режиме перемещения « Слой » при перетаскивании выделения необходимо удерживать нажатыми клавиши Ctrl + Alt .

Если режимом перемещения является « Выделение » , вы можете щелкнуть по любой точке холста для перемещения рамки выделения. Вы также можете использовать клавиши-стрелки для точного перемещения. При удерживании нажатой клавиши Shift шаг перемещения равен 25 точкам растра.

При перемещении выделения этим инструментом центр выделения помечен крестиком. Этот крестик, как и границы выделения, может прилипать к направляющим или сетке, если включены параметры Вид → Прилипать к направляющим (или сетке) : выравнивать выделения таким образом существенно проще.

За более подробной информацией обратитесь к главе Перемещение выделений.

Режим перемещения должен быть установлен на « Слой » . Тогда можно выбрать между перемещением активного слоя и, если есть много слоёв указать на слой или направляющую .

Перемещение сгруппированных слоев

Все сгруппированные (значком цепочки) слои будут перемещаться вне зависимости от того, какой из них в настоящее время активен.

При отрыве направляющей от линейки инструмент перемещения автоматически активизируется. Это не работает с другими инструментами, которых надо активизировать вручную. Когда курсор мышки проходит над направляющей, направляющая становится красной, и её можно передвигать обычным нажатием.

В диалоге параметров инструмента Контуры есть собственная функция перемещения активного контура (см. Раздел 5.2, «Контуры»), но можно использовать и инструмент перемещения, для чего режим перемещения должен быть переключен на « Контур » . Заметьте, что если сразу после рисования контура переключиться на инструмент перемещения, контур станет невидимым, поэтому придется сначала сделать его видимым в диалоге контуров. Вы можете выбрать перемещаемый контур или просто переместить активный контур.

Каждый текстовый блок находится в своем собственном слое и потому может перемещаться как слой. См. Раздел 5.6, «Текст».

Перемещение image по форме во время работы программы

Графические возможности Delphi. Image.

Этот компонент служит для размещения на форме одного из трех поддерживаемых Delphi типов изображений: растровой картинки, пиктограммы или метафайла. Любой из этих типов изображения содержится в центральном свойстве компонента — picture. В свойстве canvas содержится канва, с помощью которой при необходимости программа может отредактировать растровое изображение (но не пиктограмму или метафайл!).

property Center: Boolean;

Указывает, надо ли центрировать изображение в границах компонента. Игнорируется, если Autosize=True или если Stretch =True и изображение не является пиктограммой (ICO)

property Canvas : TCanvas;

Содержит канву для прорисовки изображения

property Transparent: Boolean;

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

property Proportional: Boolean; property Stretch: Boolean;

Разрешает/запрещает изменять размер изображения так, чтобы оно целиком заполнило клиентскую область компонента.

property Picture: TPicture;

Разрешает/запрещает пропорционально уменьшать высоту и ширину изображения, если оно не может целиком уместиться в рабочей зоне компонента

property IncrementalDisplay: Boolean;

Разрешает/запрещает показ большого изображения по мере его загрузки Центральное свойство класса. Служит контейнером изображения

Никаких специальных методов у Image нет.

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

Во время разработки формы иллюстрация задается установкой значения свойства picture путем выбора файла иллюстрации в стандартном диалоговом окне, которое появляется в результате щелчка на командной кнопке Load окна Picture Editor . Чтобы запустить Image Editor, нужно в окне Object Inspector выбрать свойство Picture и щелкнуть на кнопке с тремя точками.

Если размер иллюстрации больше размера компонента, то свойству strech нужно присвоить значение True и установить значения свойств width и Height пропорционально реальным размерам иллюстрации.

Чтобы вывести иллюстрацию в поле компонента image во время работы программы, нужно применить метод LoadFromFile к свойству Picture, указав в качестве параметра имя файла иллюстрации. Например, инструкция

загружает иллюстрацию из файла bart.bmp и выводит ее в поле вывода иллюстрации (imagel).

Метод LoadFromFile позволяет отображать иллюстрации различных графических форматов: BMP, WMF, JPEG (файлы с расширением jpg).

Написать программу-фотоальбом, которая позволяет просматривать фотографии и оставлять к ним записи.

Замечание . Для работоспособности программы необходимо создать в папке программы текстовый файл comment. txt и сменить ему расширение на .dat ( comment . dat ); также необходимо разместить 10 графических файлов с расширением .bmp и имеющих имена от 1 до 10.

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

Копирование и перемещение объектов

Задание

1.В предлагаемом тексте перепутаны слова из 4 фраз. Соберите эти фразы, используя команду перемещения. Каждую фразу оформите отдельным абзацем.

2.Скопируйте получившийся текст на 3-ю страницу. Для каждого из абзацев задайте следующие параметры форматирования:

Для первого – шрифт Times New Roman, 15, выравнивание по левому краю с отступом слева 2см, межстрочный интервал – 10пт, интервалы перед и после абзаца – 8пт. Для каждого слова первого предложения установить разное начертание. Обрамить абзац двойной чертой толщиной 0,75 пт

Для второго – шрифт Arial, 16, уплотненный на 0.6пт; выравнивание по правому краю с отступом справа 2см, межстрочный интервал – 10пт, интервалы перед и после абзаца – 14пт. Обрамить слева и сверху нестандартной линией оранжевого цвета толщиной 3 пт

Для третьего – шрифт Verdana, 12, жирный; выравнивание по ширине с висячей первой строкой и отступом слева 5 см, справа 2см, межстрочный интервал – 1.3 интервала, интервалы перед и после абзаца – 10 пт. Обрамить сверху и снизу одинарной чертой синего цвета толщиной 2,25 пт.

Для четвертого – шрифт Courier New, 17; выравнивание по левому краю, межстрочный интервал – полуторный, интервалы перед и после абзаца – 12пт. Первую букву этого абзаца оформите буквицей бирюзового цвета шрифт Monitype Corsiva в тексте высотой 4 строки. Обрамить справа и снизу двойной толстой и тонкой линией лилового цвета толщиной 3 пт.

3. Скопируйте текст на следующую страницу. Создайте 2 стиля (3 балла): Пример 1: шрифт полужирный Arial Cyr в 16 пунктов зеленого цвета, 2 межстрочный интервал, рамка желтого цвета с тенью толщиной 2,25 и пример 2: Шрифт Courier 14, отступ слева 2 см, справа 1,5 см, полуторный межстрочный интервал, отступ красной строки, отступ перед абзацем 14 пт, выравнивание по ширине. Примените стиль пример1 к 1 и 3 абзацам и стиль пример2 ко 2 и 4 абзацу.

Переопределите эти стили, изменив размер букв на 20, используя 3 и 4 абзацы.

4. Оформите титульный лист и оглавление. При оформлении титульного листа используйте форматы абзаца (отступы слева, интервал перед и после абзаца, и др.).

5. Дайте заголовок каждой странице (например, задание, редактирование, колонки, форматирование, стили). Для оформления заголовков используйте подходящий стиль, например, стиль Заголовок 1. Сформируйте автоматически оглавление, поместив его в начало документа (после титульного листа).

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

Теоретические сведения

Редактирование – процесс изменения содержания документа. Выполняется путем

– набора с клавиатуры новых фрагментов

– вставки фрагментов из других документов

– копирования фрагментов в текущем документе

– удаления фрагментов документа.

Принцип выполнения всех команд, в том числе и команд редактирования, в офисных приложениях Windows одинаковый: на первом шаге надо указать (выделить) объект, над которым будет выполняться какая-либо операция, на втором шаге в меню (главном, инструментальном или контекстном) выбрать необходимую команду либо использовать «горячие клавиши».

Применительно к текстовому процессору под объектом будемподразумевать часть слова, слово, несколько слов, предложение, строку, абзац или весь текст.

Для Выделенияпроизвольного объекта можно воспользоваться одним из следующих способов:

a) с помощью мыши: необходимо установить курсор в начало объекта, совместить с ним курсор мыши и при нажатой левой кнопке мыши перемещать его в конец выделяемого объекта.

b) с помощью клавиатуры: переместить курсор в начало объекта, нажать клавишу Shift и не отпуская её перемещать курсор с помощью клавиш управления курсором в конец объекта.

Вместо этого можно воспользоваться более быстрыми способами выделения конкретных фрагментов текста.

Фрагмент текста Возможный вариант выполнения операции
Слово Двойной щелчок мыши на слове
Два раза нажать клавишу F8
Строка Щелкнуть слева от строки
От позиции курсора до конца строки Удерживая клавишу Shift , нажать End (Shift+ End)
Предложение Ctrl+щелчок в любом месте предложения
Три раза нажать клавишу F8 в любом месте предложения
Абзац Протащить мышь по левому полю
Двойной щелчок мыши на левом поле
Тройной щелчок мыши на абзаце
Четыре раза нажать клавишу F8 в любом месте абзаца
Ctrl+ Shift+ ®
Документ Ctrl+щелчок на левом поле
Тройной щелчок мыши на левом поле
Ctrl+А(латинское)
Пять раз нажать клавишу F8
От позиции курсора до конца документа Ctrl+ Shift+ End

Внимание! Если Вы использовали клавишу F8, обязательно нажмите клавишу Esc для выхода из режима выделения.

Копирование и перемещение объектов

Для копирования и перемещения объектов внутри одного документа или между приложениями можно использовать буфер обмена (ClipBoard). Буфер обмена — это область памяти компьютера, доступная приложениям Windows, в которой хранятся вырезанные или скопированные данные. После выполнения команд Copy (Копировать) или Cut (Вырезать) Windows помещает выделенный фрагмент документа в буфер обмена, откуда он может быть вставлен в тот же самый или другой документ или в другую программу с помощью команды Paste (Вставить). Команда Paste (Вставить) может выполняться многократно до тех пор, пока буфер обмена не будет очищен или на место скопированного фрагмента не будет помещен другой.

Способы копирования/перемещения фрагментов текста.

Вариант выполнения Технология работы
Через главное меню 1. Выделите фрагмент текста. 2. Поместите выделенный фрагмент в буфер обмена, выбрав в главном меню ПравкаÞ Копировать/Вырезать. 3. Установите курсор на место назначения. 4. Выберите в главном меню ПравкаÞ Вставить, или нажмите клавишу Insert.
Через панель инструментов 1. Выделите фрагмент текста. 2. Поместите выделенный фрагмент в буфер обмена, щелкнув по соответствующей кнопке в панели инструментов. 3. Установите курсор на место назначения. 4. Щелкните по кнопке Вставить в панели инструментов, или нажать клавишу Insert.
Через контекстно-зависимое меню 1. Выделите фрагмент текста. 2. Поместите выделенный фрагмент в буфер обмена. Для этого щелкните правой кнопкой мыши и в появившемся контекстном меню выберите Копировать/Вырезать. 3. Установите курсор на место назначения. 4. Щелкните правой кнопкой мыши и в появившемся контекстном меню выберите Вставить.
Используя клавиатуру 1. Выделите фрагмент текста. 2. Поместите выделенный фрагмент в буфер обмена, нажав одновременно клавиши CTRL+C для копирования или CTRL+X для перемещения. 3. Установите курсор на место назначения. 4. Нажмите клавиши CTRL +V, чтобы Вставить фрагмент теста.
Используя мышь Выделите фрагмент текста. Для перемещения: Поместите указатель мыши на выделенном фрагменте, удерживайте нажатой левую кнопку мыши и перетаскивайте указатель на место назначения. Внимание! Во время перетаскивания объекта к указателю мыши добавляется прямоугольник. Для копирования выделенного фрагмента удерживайте нажатой клавишу CTRL во время перетаскивания объекта. Внешне о копировании будут сообщать две детали экрана: плюсик в указателе и строка состояния, где появляется соответствующий вопрос (Куда копировать?).

Для удаления фрагмента текста:

¨ выделите нужный фрагмент

¨ нажмите клавишу Delete или в главном меню выберите Правка Þ Удалить.

Внимание! После этой операции фрагмент текста исчезнет.

Форматирование

Форматирование — процесс придания документам надлежащего вида.

К стандартному форматированию документов можно отнести такие операции с фрагментами текста, как изменение положения на листе, изменение правых и левых отступов, красной и выступающей строки, выравнивание текста, изменение межстрочных интервалов, обрамление и затенение абзацев, применение различных шрифтов.

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

– выбрать гарнитуру (внешний вид символов) из списка Шрифт.

– выбрать Начертание (стиль) шрифта.

– сообщить Word требуемые Размеры символов

– выбрать Цвет

– при желании применить специальные Эффекты

Для этих же целей можно использовать соответствующие кнопки на стандартной панели форматирования.

На вкладке Интервал окна диалога Формат Þ Шрифт можно задать интервал между символами и некоторые другие параметры.

Варианты выравнивания, отступы, оформление первой строки, межстрочные интервалы задаются в меню Формат Þ Абзац:

Границы и заливка

Для обрамления абзаца необходимо выделить его и выбрать пункт меню Формат Þ Границы и заливка. В открывшемся окне на вкладке Граница можно выбрать тип, цвет и толщину линии, указать вид обрамления (сверху, снизу слева, справа, вокруг и т.п.), а на вкладке Заливка – выбирать цвет и тип заливки. Обратите внимание: применять заданные параметры надо к абзацу, а не к тексту.

Работа со стилями

Стиль — это совокупность всех элементов форматирования. Word использует два типа стилей:

¨ Стили символов хранят наборы информации об отдельных символах (например, шрифты, цвета)

¨ Стили абзацев позволяют собрать информацию, которая имеет отношение к абзацам — выравнивание, межстрочные интервалы, установки табуляции и т.п.

Word содержит набор стилей, которыми можно пользоваться для оформления своего документа. Для этого надо выделить абзац, затем на панели инструментов из раскрывающегося списка стилей выбрать нужный и нажать Enter.

Можно создавать свои стили одним из способов:

I. создание нового стиля

II. переопределение стиля на ходу.

Чтобы создать новый стиль (с нуля), нужно выбрать в главном меню ФорматÞ Стильдля вызова диалогового окна Стиль:

Теперь нужно щёлкнуть на кнопке Создать, ввести имя своего стиля, выбрать стиль, на котором будет основываться новый стиль, и щёлкнуть на кнопке Формати задать необходимые параметры.Данный способ является очень сложным.

Проще переопределить стиль на ходу. Для этого нужно сделать следующее: отформатировать один абзац нужным образом, поместить курсор в любое место этого абзаца, затем на инструментальной панели щёлкнуть на поле списка стилей, ввести имя нового стиля и нажать Enter.

Создание оглавления

Если создан большой документ, то к нему требуется оглавление и оформление одним стилем заголовков разного уровня. В Word существует разбивка заголовков на 9 уровней, автоматическая нумерация заголовков, подзаголовков, ссылка на различные рисунки и приложения. Но перед этим с помощью панели инструментов надо:

1) Определить и обозначить соответствующие уровни (выделить фразу и применить к ней стиль заголовка соответствующего уровня)

2) Установить курсор в место вставки оглавления

3) В меню ВставкаÞ Оглавление и указателина вкладкеОглавлениевыбрать стиль оглавления

Колонтитулы

Колонтитулы — это та часть поля листа, которая расположена над текстом или после него. В колонтитулы обычно помещают нумерацию страниц, название раздела или документа, дату, фамилию автора. Колонтитулы автоматически воспроизводятся на каждой странице. Чтобы вставить текст в колонтитулы или отредактировать имеющийся, надо войти в меню ВидÞКолонтитулы, написать текст. В этом окне можно менять колонтитул четной или нечетной страницы, верхний или нижний. Если для каждого раздела документа используется свой колонтитул, надо:

1) Разбить предварительно текст на разделы (Вставка Þ РазрывÞ Новый раздел)

2) В окнеКолонтитулыотключить опцию Как в предыдущем

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Студент — человек, постоянно откладывающий неизбежность. 10532 — | 7319 — или читать все.

188.64.174.135 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.

Отключите adBlock!
и обновите страницу (F5)

очень нужно

Как пользоваться инструментом Перемещение в фотошопе

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

На панели инструментов Перемещение (Горячая клавиша — V ) располагается вторым по счету в гордом одиночестве (обозначен иконкой в виде указателя мыши со стрелочками направления):

Для чего нужен инструмент Перемещение

1. Двигать содержимое слоя

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

Как это выглядит на примере

Допустим, была открыта некая картинка, к которой мы добавили свой логотип. Логотип расположен на отдельном слое. Выделите этот слой на палитре, выберите инструмент Перемещение и начинайте двигать логотип в любое место:

Например вниз. Вот что получилось:

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

Если не зажимать эту клавишу, а просто пользоваться стрелками клавиатуры, то картинка будет двигаться с шагом в 1 пиксель.

2. Двигать содержимое выделенной области

Создав выделенную область, можно подвинуть ее содержимое. Но для начала рекомендую ознакомиться со статьей о том, что такое выделение и выделенные области в фотошопе.

В этом действии есть два возможных сценария:

1. Просто переместить фрагмент. В этом случае инструмент будет работать как команда Вырезать, то есть после перемещение в данном месте останется пустота.

Пример

Допустим, нужно выделить на картинке слово (которое является частью картинки) и переместить его куда-нибудь в другое место:

Напомню, чтобы создать такое выделение, как правило, используют инструмент Прямоугольная и Овальная области.

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

Пример

Тот же случай, когда нужно переместить текст, но при этом задача автоматически создать его копию:

При перемещении содержимого слоя или выделенной области, следите за тем, чтобы на палитре слоев был правильно выбран слой. Если это содержимое выделенной области, то выберите сперва слой, которой содержит этот фрагмент.

Если вы выбрали пустой слой, или в выбранную выделенную область не входит ни единого пиксела, то фотошоп покажет вам ошибку «Выделенная область пуста».

Если вам нужен фрагмент, который создан путем наложения двух и более слоев, то для начала эти слои нужно объединить, чтобы получился один слой, к которому вы и будете применять перемещение фрагмента выделенной области.

3. Перемещать объекты из одной вкладки в другую

В фотошопе существует множество способов как добавить картинку к картинке. Один из таких способов — это использование инструмента Перемещение.

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

Пример

4. Выравнивать объекты по центру и краям

На панели параметров находятся команды, позволяющие автоматически выравнивать объекты относительно всего изображения, либо его отдельного фрагмента.

Подробнее как это можно сделать смотрите в отдельном уроке.

На панели параметров большую часть функций отнимают кнопки выравнивания. Но помимо них есть и другие настройки.

Автовыбор

Поставив галочку напротив этого параметра, вы измените способ выбора объекта для перемещения. Если в обычном режиме (без галочки) сначала нужно выбрать слой на палитре, а потом его двигать, то с активированным режимом Автовыбора, фотошоп будет двигать тот слой, на который вы навели указатель мыши на самом изображении.

Это удобно, когда на изображении расположено много слоев с небольшими деталями, которые приходится постоянно перемещать. Движение руки до палитры слоев и обратно, а еще надо найти миниатюру нужного слоя, отнимает много времени. Данный режим значительно ускорит производительность работы. Главное ясно понимать какие объекты находятся на отдельных слоях и четко прицеливаться указателем мыши до их пикселей.

Сюда бы я еще добавил другую аналогичную опцию инструмента по выбору слоев для перемещения — клик правой кнопкой мыши по изображению вызывает меню слоев . То есть это меню показывает имена всех слоев, которые имеют свои пиксели в этой точке, а самым верхним в списке будет тот, чьи пиксели находятся выше остальных.

Показать управляющие элементы

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

Илон Маск рекомендует:  Обработка ввода
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL