Вверх ↑
Пакеты 
Разработка элемента - Класс Custom

Класс Custom
  Этот класс, как уже говорилось ранее, был введен для отображения пользовательских (а точнее, нестандартных) элементов в редакторе форм. Такими элементами являются, к примеру, График или Градиентная панель состояния. Эти интерфейсные элементы управления не являются стандартными для Windows и очевидно не могут быть выведены в редактор форм непосредственно. Для них (как и для всех подобных элементов) нужно устанавливать свои обработчики отрисовки на основе заданных св-тв и делать это непосредственно в HiAsm смысла нет, т.к. во-первых, при изменении компонента приходится перекомпилировать всю среду, ну и во-вторых, автор такого компонента лишается возможности правильно отобразить его в редакторе форм.

  В попытке решить эту проблему и был создан класс Custom, который предоставляет разработчику 4 процедуры для отображения своего компонента в редакторе форм. Эти процедуры должны быть экспортированы из стандартной Windows DLL с именем, совпадающим с названием компонента, и лежащей в папке Draw. Рассмотрим эти процедуры подробнее:

Init
  Процедура, вызываемая для каждой новой копии компонента, загружаемого в редактор форм. Синтаксис:
#pas
procedure Init(PRec:PParamRec; var EditData:pointer; DTools:PDrawTools); cdecl;
тут обработчик может выполнить какие-то подготовительные действия общего характера, либо исходя из начальных параметров компонента, доступ к которым осуществляется через первый аргумент (подробнее о типе PParamRec будет рассказано ниже). Так, например, обработчик компонента Grapher в теле этой процедуры создает новую BMP картинку на основе начальных размеров компонента и сохраняет её в параметре EditData (эта картинка используется в качестве буфера для предотвращения мигания). Сразу хочется обратить внимание на назначение этого параметра. Как известно DLL обладает той особенностью, что грузится только один раз для всей программы и как следствие все глобальные переменные будут общими для всех компонентов данного типа в редакторе форм. Поэтому если вам необходимо хранить какие-то свои данные для каждого компонента, то сохранять их надо как раз в параметре EditData. Что мы и видим в случае с !Grapher!:
#pas
type
TRPoint = record x,y:real; end;
TLoc = record
Bmp:PBitmap;
Values:array[0..100]of TRPoint;
end;
PLoc = ^TLoc;
procedure Init(PRec:PParamRec; var ed:pointer; DTools:PDrawTools); cdecl;
var
p:PLoc;
i:byte;
begin
new(p);
ed := p;
p.Bmp := NewBitmap(integer(PRec[2].value^),integer(PRec[3].value^));
for i := 0 to 100 do
begin
p.Values[i].x := i;
p.Values[i].y := Random(50);
end;
end;
опуская подробности реализации этого кода, вы должны увидеть главное - обработчик графиков должен оперировать двумя объектами, разными для каждой копии компонента в редакторе. Поэтому их нельзя делать глобальными. О том, что такое параметр DTools так же читайте ниже.

Close
Процедура, вызываемая для каждой копии компонента при закрытие редактора форм(или при уничтожение компонента). Синтаксис:
#pas
procedure Close(PRec:PParamRec; EditData:pointer); cdecl;
параметры тут точно такие же, как и у Init, только EditData в данном случае нужно использовать, а не инициализировать. В этом обработчике нужно удалять все динамические объекты, созданные в момент инициализации, а так же не забыть удалить EditData, если этот параметр был задан. Так обработчик Графика в теле этой процедуры удаляет созданную ранее BMP картинку и память, выделенную под EditData.

Change
Процедура вызывается при каждом изменение св-ва в редакторе. Синтаксис:
#pas
procedure Change(PRec:PParamRec; EditData:pointer; Index:integer); cdecl;
Index - это индекс изменяемого св-ва в массиве PRec. Этот индекс всегда определяется порядком расположения св-тв в редакторе и начинается с 0. Использовать этот обработчик можно для контроля значений св-тв (только нужно помнить, что действует этот контроль только в режиме редактора форм), а так же для изменения внутренних данных. Так обработчик Change компонента Grapher использует обе возможности. Он контролирует значение св-ва Step, которое не может быть 0, а так же изменяет размеры BMP картинки при изменении размеров компонента.

Draw
Основная процедура, вызываемая при каждой перерисовки компонента. Синтаксис:
#pas
procedure Draw(PRec:PParamRec; EditData:pointer; dc:HDC); cdecl;
в этот обработчик вставляется собственно код отрисовки компонента. Тут в последнем параметре dc передается указатель на контекст устройства вывода(в HiAsm это просто панель), на котором собственно и нужно рисовать.
Самое время рассмотреть структуру типа PParamRec. Объявлен он в модуле shareDraw.pas и выглядит следующим образом:
#pas
type
TParamRec = record
Name:string;
Value:pointer;
DataType:byte;
buf:pointer;
Index:byte;
end;
TParamRecArray = array[0..1024] of TParamRec;
PParamRec = ^TParamRecArray;
как следует из объявления это указатель на массив записей типа TParamRec. Размер массива стоит чисто условный и на самом деле равен количеству св-тв в компоненте. Так что при попытке задать индекс больше этого числа вы получите ошибку. TParamRec - это копия структуры, которую использует HiAsm для хранения данных о каждом св-ве компонента, поэтому вы не должны удивляться тому, что в ней есть поля, которые никогда и никем не будут использоваться. Связано это с тем, что при передаче этого аргумента все, что делает HiAsm это возвращает указатель на первый элемент массива параметров благодаря чему достигается максимальное быстродействие этой операции и у программиста появляется возможность изменять их значения непосредственно(однако менять любые другие поля, кроме Value строго не рекомендуется!). Учитывая выше написанное для доступа скажем к св-ву Width(третье по счету св-во) нужно использовать конструкцию: PRec[2].Value.

  Как вы заметили наверно, поле Value это указатель на данные. В таблице ниже указаны соответствия между типом и реальным значением св-ва:

Индекс Имя типа Преобразование
1 Integer Integer(Value^)
2 String String(Value^)
3 Data PData(Value)
4 List byte(Value^)
5 StrList String(Value^)
6 Icon TIcon(Value)
7 Real Real(Value^)
8 Color TColor(Value^)
9 Script String(Value^)
10 Stream TMemoryStream(Value^)
11 Bitmap TMemoryStream(Value^)
12 Wave TMemoryStream(Value^)
13 Array [none]
14 Enum byte(Value^)
15 Font PFontRec(Value)
16 Matr [none]
17 Jpeg TMemoryStream(Value^)


   Cв-ва Icon, Stream, Bitmap, Wave, Jpeg - использовать их напрямую не рекомендуется. Это связано с возможным изменением формата в будущем, и главное с резким увеличением размера DLL за счет включения модуля SysUtils. Так для работы с картинками HiAsm предоставляет специальный инструмент, благодаря которому обращаться непосредственно со значением св-ва Bitmap вам не придется. Доступ к этим ф-циям можно получить через поля объекта DTools, передаваемого последним параметром процедуры Init. Именно их и использует компонет ImgBtn для вывода катртинки.
BB-code статьи для вставки
Всего комментариев: 0
(комментарии к статье еще не добавлены)
Комментарий
...