Лекция 16. Кнопки с изображениями и маскировочное поле ввода
В этой лекции вы научитесь работать с компонентами, улучшающими внешний вид программы. Изучите компоненты BitBtn и MaskEdit, научитесь добавлять на форму кнопки с изображениями рядом с текстом, а также освоите маски компонента MaskEdit, облегчающие пользователю ввод данных в нужном формате.
Кнопки BitBtn
Такие кнопки используют, в основном, для украшательства приложения. Они отличаются от обычной кнопки Button прежде всего тем, что вместе с надписью на кнопку можно вывести и картинку. Кнопка с картинкой, безусловно, выглядит нарядней.
Откройте новый проект и установите на нее кнопку BitBtn с вкладки Additional палитры компонентов. В свойстве Caption этой кнопки напишите "Открыть файл". Далее, выберите свойство Glyph – это свойство раскрывающееся, нужно щелкнуть по кнопочке с тремя точками в этом свойстве, чтобы открылся список. Открылся редактор картинок. Нажмем кнопку Load (Загрузить). По умолчанию открывается стандартная папка с проектами Delphi, но картинок здесь нет. При установке Delphi-7 картинки устанавливаются в папку
C:\Program Files\Common Files\Borland Shared\Images\Buttons
Откройте эту папку в редакторе. Как только вы выберите картинку (то есть, один раз щелкните по ней), в правой части окна отобразится рисунок этой картинки. Здесь вы видите два изображения для каждой кнопки – первое изображение будет у активной (доступной) кнопки, второе – для неактивной. Теперь у вас есть возможность прогуляться по коллекции изображений с помощью кнопок управления курсором, выбирая подходящее для кнопки изображение. Поскольку мы хотим сделать кнопку для открытия файла, то выберем стандартное для этого изображение в файле "FILEOPEN". Картинка не очень привлекательна, но пока что воспользуемся ей. Выбрав файл, нажмите кнопку "Открыть". Изображение попало в редактор картинок. Теперь, чтобы принять изображение, нажмем кнопку "ОК". Если картинка вместе с надписью не помещается на кнопке, то увеличьте ширину кнопки.
Бросьте еще одну кнопку BitBtn, в свойстве Caption укажите "Закрыть файл", и попробуйте самостоятельно подобрать картинку для этой кнопки.
В этой кнопке нам может пригодиться несколько свойств. Свойство Layout определяет, где будет находиться картинка. По умолчанию она слева – blGlyphLeft, но можно установить картинку и справа, а также сверху или снизу, правда в этом случае придется корректировать высоту кнопки.
Свойство Margin также определяет положение изображения и надписи. По умолчанию оно равно "-1". Если же указать значение больше нуля, то надпись и изображение будут сдвигаться вправо на указанное количество пикселей.
Свойство Spacing по умолчанию равно 4. Это количество пикселей, отделяющих изображение от надписи. Вы имеете возможность менять это расстояние по своему усмотрению.
Еще одно интересное свойство – Kind. Это свойство определяет поведение кнопки в некоторых случаях. По умолчанию оно равно bkCustom (заказной). То есть, в данном случае вы сами определяете поведение кнопки – как выглядит изображение, что написано на кнопке, что будет указано в обработчике нажатий на кнопку. Однако попробуйте установить на форму еще одну такую кнопку, и в свойстве Kind выбрать bkClose. Сразу же появилось стандартное изображение Delphi закрытия формы, и на кнопке написано Close (Закрыть). Поменяйте текст в свойстве Caption на русский вариант, затем сохраните проект и откомпилируйте его. Нажмите на эту кнопку, и форма закроется.
Вообще то обычно не рекомендуют использовать свойство Kind, желательно самим программировать поведение кнопки. Во-первых, вы можете захотеть для этой кнопки выбрать другое изображение, во-вторых, процедура закрытия формы может быть гораздо сложней обычной строки "Close;", ведь если есть открытый файл или база данных, их вначале нужно закрыть, если есть какие то несохраненные данные, их нужно сохранить перед закрытием формы. Впрочем, использовать это свойство или нет – дело вкуса каждого программиста.
О картинках. Стандартная коллекция изображений для кнопок у Delphi не блещет красотой и богатым выбором. Однако вы можете найти в Интернете очень много бесплатных коллекций таких картинок, и скачать их. Далее выбирайте те картинки, которые на ваш взгляд выглядят привлекательно. Если же вы чувствуете в себе талант художника, можете нарисовать изображение сами, воспользовавшись редактором картинок Image Editor, который устанавливается вместе с Delphi.
Совет. Помните, что вся программа должна выглядеть в общем стиле. Если вы изменили цвет главной формы, желательно изменить его и у всех дочерних форм на такой же. Если на главной форме вы используете вместо простых кнопок кнопки TBitBtn, и выбрали для них какую-то стороннюю коллекцию, то желательно использовать такие же кнопки и в других формах, и картинки использовать из той же коллекции.
Другие свойства кнопок
Есть еще несколько свойств, общих для всех кнопок, которые вам необходимо знать.
Измените свойство Caption у кнопки "Открыть файл" - поставьте перед первой буквой символ "&". На кнопке буква "О" оказалась подчеркнутой. Этим вы задали для кнопки "горячие клавиши", то есть теперь все равно – нажать ли на эту кнопку, или нажать клавиши <Alt + O>. Запомните – символ "&" перед буквой задает горячую клавишу. Вы можете поставить его перед любой буквой, не обязательно перед первой. Попробуйте сами!
Свойство Cancel по умолчанию равно False. Если же в нем установить True, то при выполнении программы нажатие кнопки <Esc> будет выполнять то же действие, что и нажатие на эту кнопку. Это свойство желательно изменять для кнопок "Отменить" в разных диалоговых окнах.
Свойство Default, установленное в True, делает кнопку главной по умолчанию. Если пользователь нажмет <Enter>, это будет эквивалентно нажатию на данную кнопку. Здесь есть исключение – если в этот момент в фокусе будет другая кнопка, то нажатие на <Enter> вызовет все же обработчик события той кнопки, что была в фокусе.
Свойство ModalResult иногда используется в модальных формах. По умолчанию оно равно mrNone, то есть, ничего. Однако вы можете выбрать любое значение из этого списка. Предположим, в модальной форме вы установили кнопки "Да", "Нет" и "Отмена". Тогда в свойстве ModalResult этих кнопок вы можете установить значения mrYes, mrNo и mrCancel. При этом обработчик события для этих кнопок создавать не нужно – нажатие на любую кнопку закроет форму. А в момент закрытия модальной формы, свойству ModalResultэтой формы запишется значение ModalResult той кнопки, которая закрыла форму. Далее, после вызова этой формы вы можете написать проверку, какая кнопка была нажата:
Form2.ShowModal;
if Form2.ModalResult = mrIgnore then
ShowMessage('Нажали "Игнорировать"');
Вот, собственно, и все, что нужно знать о кнопках. Остались еще кнопки SpeedButton, они предназначены для создания панелей инструментов, и о них мы поговорим позже.
Компонент MaskEdit
Этот компонент подобен обычному Edit, но предназначен для задания маски ввода пользователем данных. Очень часто возникает необходимость задать правильный формат для ввода пользователем каких-то данных, и тут MaskEdit будет незаменима.
Действие этого компонента лучше изучать на примере. Создайте новое приложение. На форму установите компонент Label, в свойстве Caption которого пропишите "Введите дату:". Слева от него поместите компонент MaskEdit. Как видите, большинство свойств этого компонента соответствуют компоненту Edit, и это неудивительно – ведь MaskEdit произошел от простого Edit и унаследовал все его свойства.
Самое интересное свойство этого компонента – EditMask. Щелкните по нему, а затем по кнопочке, которая открывает редактор.
Рис. 16.1. Редактор маски компонента MaskEdit
В строке Input Mask вы можете задать нужный формат (маску). В поле Sample Mask вы видите типы масок и примеры формата. Выбрав здесь нужный тип, вы сразу же зададите маску для ввода. В строке Test Input вы можете увидеть, как будет происходить ввод данных, то есть, протестировать ввод. Задать маску можно не только выбором ее типа, но и указав ее самостоятельно. Например, вы желаете создать маску для ввода телефонного номера. Тогда в строке Input Mask вы пишете строку "999-99-99". Цифра 9 указывает, что в этом месте должна быть любая цифра.
Поле Character for Blanks указывает, какой символ здесь будет указываться в месте ввода. По умолчанию это знак подчеркивания. То есть, если мы оставим этот символ и выберем тип Date, пользователь увидит:
__.__.__
Здесь есть один минус: маску для ввода мы задали, однако проверка на правильность не производится, то есть пользователь может вписать "20.20.07", а 20-го месяца не бывает. Так что проверку правильности нужно будет проводить самостоятельно.
Давайте изменим маску в поле Input Mask, и напишем "99.99.9999 г.". Создайте такую маску, скомпилируйте программу и увидите, что пользователь сможет ввести только цифры, причем "г." уже будет присутствовать в строке.
Попробуйте самостоятельно сделать маску для ввода номера телефона вместе с кодом вашего города.
Подсказка: 8(3742) 999-99-99
Еще одно интересное свойство для компонентов Edit и MaskEdit, это свойство PasswordChar – символ ввода пароля. По умолчанию он равен "#0", то есть никакого символа. Если же мы укажем символ "*", как это принято по умолчанию в Windows, то во время работы программы все символы, которые будет вводить пользователь, в этой строке будет отображаться как звездочки. Причем на сам текст это не окажет никакого влияния, просто его не будет видно в момент ввода.
Установите на форму компонент Edit. В свойстве Font выберите шрифт Windings. А в свойстве PasswordChar укажите "#74". Тогда все вводимые символы будут отображаться, как улыбающиеся рожицы. Выбрать нужные шрифт и символ вы можете с помощью MS Word, например. Выберите там команду "Вставка - символ". В открывшемся окне выберите шрифт, затем выберите символ. В поле "код символа" будет отображаться код выбранного символа, его и укажите после знака "#" в PasswordChar. Вы можете указать там любой символ, но лучше придерживаться общепринятых стандартов, чтобы не смущать пользователя.
Самостоятельно придумайте и реализуйте приложение, используя кнопки с изображениями и хотя бы одно маскировочное поле ввода.
Лекция 17. Даты
В этой лекции вы познакомитесь с функциями преобразования дат, познакомитесь с глобальными переменными DateSeparator и ShortDateFormat, с компонентами выбора дат DateTimePicker и MonthCalendar и напишите приложение, использующее новые темы. Кроме того, познакомитесь с условными операндами AND, OR и NOT.
Логические операнды
В условных проверках, таких как if, while или repeat часто бывает недостаточным проверять только одно условие. Можно воспользоваться вложением проверок, как в приведенной в примере конструкции:
if a > 0 then
if b <> a then begin
команда 1;
команда 2;
end; //if 2
В этом коде мы проверяем, правда ли a больше нуля. Если да, то проверяем, не равно ли b и a. И только в том случае, если второе условие также вернет Истину, выполнятся указанные команды. Таких вложений может быть сколько угодно, и ими нередко пользуются.
Есть и другой способ множественных проверок. Для того, чтобы можно было проверять более одного условия, существуют логические операторы AND, OR и NOT. Поскольку эти операторы имеют наивысший приоритет в вычислениях, условия необходимо заключать в скобки.
Оператор AND (И) проверяет два условия, и возвращает истину только в том случае, если оба условия вернут истину. Взгляните на предыдущий пример, и посмотрите, как его можно написать с оператором AND:
if (a > 0) and (b <> a) then begin
команда 1;
команда 2;
end; //if
Оператор OR (Или) возвращает истину в том случае, если хотя бы одно из условий вернет истину:
if (3 > 5) or (5 > 4) then... //результат – истина, так как 5 больше 4
Оператор OR проверяет вначале левое значение. Если оно истинно, то OR не будет делать дальнейших проверок, и сразу вернет истину. Если левое значение ложное, то OR проверяет правое значение. В данном случае, если правое значение вернет истину, то и ORвернет истину, в противном случае OR вернет ложь.
Оператор NOT (Не) вернет истину только в том случае, если значение есть ложь. Фактически, это оператор – перевертыш. Если общее значение будет истинно, он возвращает ложь, а если ложно – то истину. Поэтому очень часто его используют в коде, чтобы поменять какое либо логическое свойство объектов на противоположное, например:
Button1.Enabled := not Button1.Enabled;
Edit1.Visible := not Edit1.Visible;
В этих примерах берется значение свойств объектов. Если это свойство истинно, то оператор not возвращает ложь, и этому свойству присваивается ложь. И наоборот, если свойство ложно, not заставляет его принять истинное значение. Очень удобно, когда вы не знаете заранее, что именно в свойстве хранится, истина или ложь, но при этом нужно присвоить свойству противоположное значение.
Кроме того, оператор NOT часто применяют в проверках, если нужно выполнить какой-то код в том случае, если условие ложно:
if not Edit1.Text = Label1.Caption then...
То есть, условие выполнится лишь в том случае, если тексты в Edit1 и в Label1 разные. Обратите внимание, в приведенном примере скобок нет. Ведь условная проверка у нас одна, поэтому скобок не требуется, хотя если Вы их поставите, это тоже не будет ошибкой. Оператор Not применяется очень часто, поэтому запомните его.
Преобразование даты
До сих пор мы еще не сталкивались с типом данных Дата. Тем не менее, этот тип очень широко используется в программировании. В Delphi он называется TDateTime, то есть, возвращает одновременно и дату, и время. Из-за такой его универсальности часто приходится применять функции преобразования, чтобы вернуть только дату, или только время, причем в разных форматах.
Date()
Эта функция возвращает текущие дату и время в формате TDateTime. Ее можно применять с другими функциями, задавая им в качестве параметра текущую дату. Пример:
DateToStr(Date());
DateToStr()
Возвращает указанную в параметре дату в виде строки. Например,
ShowMessage(DateToStr(Date()));
выведет сообщение с текущей датой в виде строки. Создайте новое приложение, установите на форму кнопку и в обработчике нажатия укажите эту строку. Скомпилируйте и посмотрите результат.
StrToDate()
Эта функция напротив, принимает в качестве параметра строку, в которой записали дату в правильном формате, и возвращает эту дату в виде TDateTime. Сложность заключается в том, что форматов для предоставления даты может быть много. У нас, например, принято вначале указывать день, потом месяц, и в конце год. А американцы первым указывают месяц, затем число и год. Причем год может быть как 4-х символьным (2007), так и 2-х символьным (07). Еще проблема с разделителями. Разделителем может служить и точка (20.09.2007), и знак слэш (20/09/2007).
Правильную настройку можно увидеть в окне Панель управления – Язык и региональные стандарты. Кроме того, пример
ShowMessage(DateToStr(Date()));
также вернет вам дату в виде строки в правильном формате. Если же вы желаете использовать эти функции для программ на продажу, и не знаете, какие настройки на компьютере покупателя, то придется использовать неявные глобальные переменные. ПеременнаяDateSeparator содержит символ – разделитель дат. Порядок следования дня, месяца и года определяется глобальной переменной ShortDateFormat. Возможны следующие комбинации: месяц/день/год, день/месяц/год и год/месяц/день.
Например:
procedure TForm1.Button1Click(Sender: TObject);
begin
DateSeparator := '-';
ShortDateFormat := 'm/d/yyyy';
Label1.Caption := DateToStr(Date);
end;
Здесь мы не просто смотрим значение DateSeparator и ShortDateFormat, а присваиваем им новое значение. В дальнейшем, вывод дат будет осуществляться уже по новым правилам. Так, для даты 15.09.1994 в свойство Caption компонента Label1 будет записан текст "9-15-1994". Если бы мы указали
ShortDateFormat := 'mm/dd/yyyy';
То выводимые месяц и день были бы с нулями, если они меньше 10: "09-15-1994"
FormatDateTime()
Эта функция возвращает дату и время в виде строки в указанном формате. Очень интересная функция, чаще всего используют именно ее, чтобы вывести строку нужного формата. У функции есть два параметра, первым указывается формат строки, в котором нужно вернуть дату. Второй параметр – переменная типа TDateTime, которую нужно преобразовать в строку. В качестве второго параметра также можно использовать функцию Date(), если требуется преобразовать текущие дату и время. Эту функцию можно сравнить с функцией FormatFloat(), которую мы изучали ранее. Самое интересное в этой функции – формат строки, или маска. Он может содержать следующие символы:
- d – показать день, не подставляя нули в начале: 1, 2, 12
- dd – показать день с подстановкой нулей в начале: 01, 02, 12
- ddd – показать день недели в коротком формате: Пн, Вт, Ср
- dddd – показать полный день недели: Понедельник, Вторник, Среда
- m – показать месяц без нулей: 1, 2, 10
- mm – показать месяц с нулями: 01, 02, 10
- mmm – показать короткое название месяца: Янв, Фев
- mmmm – показать полное название месяца: Январь, Февраль
- yy – показать короткий год: 07, 98, 00
- yyyy – показать полный год: 2007, 1998, 2000
- h – показать часы, не добавляя нулей: 3, 5, 12
- hh – показать часы с нулями: 03, 05, 12
- n – минуты без нулей: 3, 5, 12
- nn – минуты с нулями: 03, 05, 12
- s – секунды без нуля впереди: 3, 7, 30
- ss – секунды с нулями: 03, 07, 30
Это практически полный набор форматов, которые вам могут пригодиться. Примеры использования:
ShowMessage (FormatDateTime('Сегодня dddd dd mmm yyyy г.', Date));
//Результат: Сегодня Среда 06 Фев 2008 г.
ShowMessage (FormatDateTime('Сегодня dd.mm.yyyy г.', Date));
//Результат: Сегодня 06.02.2008 г.
Обратите внимание, что после функции Date не указаны скобки. Это не ошибка. Если у функции нет параметров, ее можно указывать и без скобок.
Время можно указывать с разделителями:
ShowMessage(FormatDateTime('Текущее время: hh:nn:ss', Date));
//Результат: Текущее время: 05:28:15
Компоненты для ввода дат
В программах очень часто требуется предоставить пользователю возможность ввести дату. Но мы знаем о проблемах, которые могут возникнуть, вдруг даты идут в формате mm/dd/yy, а пользователь наберет 15.08.2008? Получится ошибка. Чтобы облегчить пользователю ввод дат, существует несколько компонентов. Создайте новый проект, установите на форму компоненты DateTimePicker и MonthCalendar с вкладки Win32 в Палитре компонентов. Скомпилируйте проект и посмотрите, как он работает:
Рис. 17.1. Внешний вид приложения
Обратите внимание на то, как работают эти календари. Если вы щелкните мышью по номеру года, то откроется окошко, в котором год можно прокрутить до нужного. Если щелкните по месяцу, то откроется список месяцев, в котором пользователь может выбрать нужный. А если он щелкнет по дню, то в свойстве Date обоих компонентов установится выбранная дата в формате TDateTime. Эту дату затем можно преобразовывать в функциях преобразования дат в строку, подставляя это свойство в качестве значений.
Еще обратите внимание на нижнюю строку. Там указана текущая дата, а слева от нее красный овал. Если щелкнуть по нему, то выбранная дата перескочит с любой даты на текущую.
А у компонента DateTimePicker есть еще интересное свойство: DateFormat. Оно может выводить дату в коротком или в длинном формате. Свойство Time этого компонента показывает время в формате TDateTime.
Эти компоненты удобно устанавливать на форму, чтобы пользователь вместо ввода нужной даты просто выбрал ее на форме. Кроме того, такой подход обеспечит вам гарантию того, что дата будет указана в нужном формате.
Самостоятельное задание
Создайте новое приложение. Установите на форму компоненты DateTimePicker, Memo и кнопку, чтобы добавлять в Memo1 строки. Вначале добавьте строку с текущей датой в формате, принятом в русских версиях Windows (функция DateToStr(Date)). Затем добавьте пустую строку, чтобы отделить ее от выводимых далее форматов. Затем придумайте 10 разных форматов для функции FormatDateTime(),и поочередно добавьте их в Memo1 с той датой, которая указана в DateTimePicker1. Кстати, чтобы не писать длинные названия, вроде
DateTimePicker1.Date
переименуйте компонент (свойство Name) в более короткое имя, например, DTP1, тогда обращение получится короче:
DTP1.Date