Советы по программированию на DELPHI (ч.2)

Михаил Христосенко

Как реализовать undo и redo в tmemo.

В текстовых редакторах, как правило, необходимо реализовать функции undo и redo. Ведь без них раьота с программой становится просто неудобной, а порой и опасной (можно случайно потерять какие-нибудь данные!!!). Поэтому в этот раз мы поговорим с вами о том как же это сделать.

Для начала нам надо узнать, можно ли выполнить undo. Для этого напишите:

if memo1.perform(em_canundo, 0, 0) <> 0 then

begin

{есть что отменять можно включить пункт меню с соответствующей надписью}

end;

Теперь реализуем функцию undo:

memo1.perform(em_undo, 0, 0);

Вставьте эту конструкцию между begin и end предыдущего примера.

Для того, чтобы реализовать функцию redo, вам необходимо еще раз вызвать функцию undo


Обработка исключительных ситуаций.

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

Для начала вам надо продумать те места, программы, которые могут вызвать ошибку и попытаться проконтролировать этот участок кода. Например, при вводе числа в текстовое поле необходимо делать проверку вводимых символов. Это можно осуществить с помощью оператора case. В обработчик события onkeypress для edit'a напишите:

case key of
'0'..'9': {указываем, что ничего не нужно делать, пользователь ввел число}
else key:=#0; {введенный символ не добавится в поле!}
end;

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

Синтаксис первого блока:

try

{тут ваши операторы, которые могут повлечь появление ошибки}

finally

{а здесь операторы, которые выполняться в любом случае, независимо от ошибки}

Второй блок:

try

{тут ваши операторы, которые могут повлечь появление ошибки}

except

{код, который будет выполняться в случае ошибки}

Реализация интерфейса Плавающих окон (drag & dock)

В первую очередь для этого нам понадобится Дельфи, начиная с 4-ой версии. Кстати примером такого интерфейса является редактор кода в Дельфи. Попробуем сделать подобный.

Поместите на форму четыре панели (tpanel). Первая будет приемником остальных. Для этого установите свойство docksite первой панели в true. А у трех других панелей установите свойство dragmode в dmautomatic, а свойство dragkind в dock. Вот и все, запустите ваше приложение. При щелчке по какой-нибудь из трех панелей (не по первой) у нее появятся атрибуты плавающего окна, и ее спокойно можно будет перемещать по экрану, а можно поместить внутрь первой панели.

Вот так мы реализовали интерфейс drag & dock, не написав ни одной строчки кода!!!

Список всех запущенных приложений.

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

procedure tform1.button1click(sender: tobject);
var
wnd : hwnd;
buff: array [0..127] of char;
begin
listbox1.clear;
wnd := getwindow(handle, gw_hwndfirst);
while wnd <> 0 do begin {hе показываем:}
if (wnd <> application.handle) and {-Собственное окно}
iswindowvisible(wnd) and {-hевидимые окна}
(getwindow(wnd, gw_owner) = 0) and {-Дочернии окна}
(getwindowtext(wnd, buff, sizeof(buff)) <> 0)
then begin
getwindowtext(wnd, buff, sizeof(buff));
listbox1.items.add(strpas(buff));
end;
wnd := getwindow(wnd, gw_hwndnext);
end;
listbox1.itemindex := 0;
end;

При нажатии на кнопку listbox заполнится списком запущенных в данный момент приложений!

Преобразование bmp в jpg.

Для того, чтобы преобразовать картиеку в bmp-формате в jpg-формат вам необходимо подключить к программе (в uses) модуль jpeg.

Затем вам надо объявить переменную типа tjpegimage. Ну а затем проделать следующие действия:

Например, при нажатии кнопки создадим jpeg-файл из bmp-файла. Обработчик события onclick может иметь такой вид:

procedure tform1.button1click(sender: tobject);
var jpg:tjpegimage; {создаем переменную}
begin
image1.picture.loadfromfile('c:\windows\1stboot.bmp'); {здесь загружаем какую-нибудь картинку, советую вам изменить имя картинки приведенное в этом примере!}
jpg:=tjpegimage.create; {создаем экземпляр объекта}
jpg.assign(image1.picture.graphic); {присваиваем переменной jpg картинку, хранящуюся в image'e}
jpg.compressionquality:=75; {устанавливаем параметры качества. Должно быть от 1 до 100. Если 100, то качество наилучшее, 1 наихудшее}
jpg.compress; {производим сжатие данных картинки}
jpg.savetofile('d:\1.jpg'); {и сохраняем уже готовую jpg картинку в файл}
jpg.free; {уничтожаем объект, чтобы память не засорял!}
end;

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

Перезагрузка компьютера.

Для того, чтобы перезагрузить windows вам необходимо где-нибудь написать этот код:

exitwindowsex(ewx_force+ewx_reboot,0);

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

exitwindowsex(ewx_shutdown,0);

а затем протянуться ручками к кнопке power...

Извлечение иконок из exe и dll. (api)

Решить эту задачу нам поможет функция function extracticon(hinstance, filename, iconindex):integer

где hinstance - глобальная переменная приложения, ее изменять не надо. Тип integer.

filename - имя программы или dll из которой надо извлекать иконки. Тип pchar.

iconindex - порядковый номер иконки в файле (начинается с 0). В одном файле может находится несколько иконок. Тип integer.

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

Данная функция возвращает handle иконки, поэтому применять ее нужно так:

image1.picture.icon.handle:=extracticon(hinstance, pchar(paramstr(0)), 0);

данное объявление нарисует в image'e картинку вашего приложения.

Директория вашей программы.

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

Первое решение: воспользоваться таким объявлением application.exename:string;

Второе решение: я чаще им пользуюсь paramstr(0); так же возвратит полный путь к вашей программе. Ну а чтобы узнать директорию вашей программы воспользуемся функцией extractfilepath(filename:string):string;

То есть узнать директорию можно так: extractfilepath(paramstr(0));

Удаление директории, содержащей файлы.

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

function myremovedir(sdir : string) : boolean;
var
iindex : integer;
searchrec : tsearchrec;
sfilename : string;
begin
result := false;
sdir := sdir + '\*.*';
iindex := findfirst(sdir, faanyfile, searchrec);

while iindex = 0 do begin
sfilename := extractfiledir(sdir)+'\'+searchrec.name;
if searchrec.attr = fadirectory then begin
if (searchrec.name <> '' ) and
(searchrec.name <> '.') and
(searchrec.name <> '..') then
myremovedir(sfilename);
end else begin
if searchrec.attr <> faarchive then
filesetattr(sfilename, faarchive);
if not deletefile(sfilename) then
showmessage('could not delete ' + sfilename);
end;
iindex := findnext(searchrec);
end;

findclose(searchrec);

removedir(extractfiledir(sdir));
result := true;
end;

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

if not myremovedir('c:\mydir') then
showmessage('can not delete dir');

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

Манипуляции с кнопкой ПУСК.

- Отключить пуск
enablewindow(findwindowex(findwindow('shell_traywnd',nil),0,'button',nil),false);

- Включтиь пуск
enablewindow(findwindowex(findwindow('shell_traywnd',nil),0,'button',nil),true);

- Нажать пуск
var
htaskbar, hbutton: hwnd;
o:boolean;
begin
htaskbar:= findwindow('shell_traywnd', nil);
hbutton:= getwindow(htaskbar, gw_child);
sendmessage(hbutton, wm_lbuttondown,
mk_lbutton,loword(5)+hiword(screen.height-20));

end;

Добавляем программу в авторан.

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

var reg: tregistry;
begin
reg := tregistry.create;
reg.rootkey := hkey_local_machine;
reg.lazywrite := false;
reg.openkey('software\microsoft\windows\currentversion\run', false);
reg.writestring('my program', application.exename); {вместо my program можно и что-нибудь другое вставить}
reg.closekey;
reg.free;
end;


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=3836