Студопедия

КАТЕГОРИИ:

АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника


ЧАСТНОЕ УЧРЕЖДЕНИЕ ОБРАЗОВАНИЯ




Безусловно, календарь будет очень полезен пользователям. Однако было бы желательно не только выбирать даты, но и вводить их в элементы управления. Компонент TDateTimePicker совмещает календарь и однострочный текстовый редактор, причем календарь полностью совпадает с рассмотренным выше (оба компонента являются наследниками класса TCommonCaiendar). Свойства и методы компонента представлены в табл. 5.7.

Таблица 5.7.Основные свойства и методы компонента TDateTimePicker

Объявление Описание
type TDTCalAlignment = (dtaLeft, dtaRight) ; property CalAlignment : TDTCalAlignment; Выравнивает панель календаря по левой или правой стороне компонента
property Checked: Boolean; Возвращает True, если флажок в редакторе включен
type TDTDateFormat = (df Short, dfLong) ; property DateFormat: TDTDateFormat; Определяет формат представления даты
type TDTDateMode = (dmComboBox, dmUpDown) ; property DateMode: TDTDateMode; Задает стиль компонента
property DroppedDown: Boolean; Возвращает True, если панель календаря включена
type TDateTimeKind = (dtkDate, dtkTime) ; property Kind: TDateTimeKind; Определяет возвращаемый результат — дату или время. Время можно вводить только в стиле dmUpDown
property Parselnput: Boolean; Включает или отключает метод-обработчик OnUserlnput
property ShowCheckbox: Boolean; Управляет видимостью флажка
type TTime = type TDateTime; property Time: TTime; Содержит установленное время
property OnChange: TNotifyEvent; Вызывается при вводе даты или времени
property OnCloseUp: TNotifyEvent; Вызывается при сворачивании панели календаря
property OnDropDown: TNotifyEvent; Вызывается при разворачивании панели календаря
type TDTParselnputEvent = procedure (Sender : TObject; const UserString: string; var DateAndTime: TDateTime; var AllowChange: Boolean) of object; property OnUser Input: TDTParselnputEvent; Вызывается при прямом вводе значения в редактор. Параметр UserString содержит вводимое значение. Параметр DateAndTime содержит значение даты или времени. Параметр AllowChange управляет изменением значения

Компонент TDateTimePicker может обеспечивать ввод даты или времени.

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

В зависимости от значения свойства Kind элемент управления настраивается на ввод даты или времени. Результат ввода даты сохраняется в свойстве Date. Дату можно выбирать из всплывающего календаря или путем перебора. Результат ввода времени сохраняется в свойстве Time.

Свойство Parseinput при значении True разрешает ручной ввод значения. В этом случае разработчик может использовать метод-обработчик

type TDTParselnputEvent = procedure(Sender: TObject; const UserString: string; var DateAndTime: TDateTime; var AllowChange: Boolean) of object; property OnUserlnput: TDTParselnputEvent;

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

procedure TForml.DateTimePicker2UserInput(Sender: TObject;

const UserString: String; var DateAndTime: TDateTime; var AllowChange: Boolean);

begin

try

DateAndTime := StrToDateTime(UserString);

except

on E: EConvertError do ShowMessage('Неверное значение');

end;

end;

Обратите внимание, что здесь обязательно должно присутствовать присвоение результата ввода параметру DateAndTime, иначе элемент управления не получит новое значение.

Панель состояния TStatusBar

Этот вид элементов управления применяется уже достаточно давно. Его роль заключается в отображении различного рода справочной информации. Панель состояния инкапсулирована в компоненте TStatusBar.

Обычно панель состояния размещается в нижней части окна. Поэтому при переносе на форму свойство Align всегда имеет значение alBottom. Панель состояния можно разделить на произвольное число самостоятельных частей. Каждая часть описывается объектом TStatusPanel. Коллекция всех таких объектов находится в свойстве

property Panels: TStatusPanels;

Например, для того чтобы показать на панели состояния текущую дату и время, в методе-обработчике OnTimer компонента TTimer достаточно предусмотреть следующий код:

procedure TForml.TimerITimer(Sender: TObject);

begin

StatusBar1.Panels[0].Text := DateToStr(Now);

StatusBarl.Panels[1].Text := TimeToStr(Now);

end;

Впрочем, панель состояния можно сделать сплошной. Для этого свойство SimplePanel должно иметь значение True. В данном случае текст панели должен содержаться в свойстве SimpleText.

Расширенный комбинированный список TComboBoxEx

Такой выпадающий список знаком пользователям со времен Windows 95 (например, список всех элементов оболочки Shell: папки My Computer, My Documents и т. п.) Соответствующий элемент управления появился в библиотеке ComCtl32 несколько позже, а в компонент он превратился только в Delphi 7.

Что отличает этот "продвинутый" выпадающий список от обычного TCоmbоВох? С функциональной точки зрения основных отличий два: возможность добавлять картинки к элементам и выравнивать последние с разным отступом, имитируя иерархию.

Реализовано это следующим образом.

У компонента TComboBoxEx, помимо свойства items, есть свойство

property ItemsEx: TComboExItems;

которое представляет собой коллекцию элементов типа TComboExitem. Щелкнув на этом свойстве в Инспекторе объектов, увидим типичный редактор коллекций, где каждый элемент обладает такими опубликованными свойствами:

  • свойство Caption отвечает за заголовок элемента, каким он буден виден в списке;
  • свойство Data — это нетипизированный указатель на прикрепляемые к элементу данные;
  • отступ от левого края списка задается свойством indent. В документации написано, что оно задается в пикселах. Это почти так: на самом деле одна единица значения свойства соответствует десятку пикселов;
  • три номера картинок: обычный imageindex, номер для выбранного элемента Selected Imageindex И Overlaylmagelndex. Последнее свойство задает номер картинки, используемой как накладываемая маска для первых двух. Она должна быть черно-белой: белые области прозрачны для исходной картинки, черные — нет. Все три индекса указывают на один и тот же список картинок, задаваемый свойством images родительского компонента.

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

Создание нового компонента на базе элементов управления из библиотеки ComCtl32

С каждой версией Internet Explorer Microsoft поставляет новую библиотеку ComQ132 с новыми элементами управления. Программисты Borland пытаются поспеть за ними, но получается это не всегда. Так что полезно было бы и самому научиться создавать оболочку для новых и необходимых элементов управления, тем более, что это несложно. Рассмотрим это на примере.

Подходящей кандидатурой может служить редактор IP-адресов, появившийся в версии библиотеки 4.71 (Internet Explorer 4.0). Это элемент, упрощающий редактирование адресов для многих Internet-компонентов и приложений.

Рис. 5.8.Мастер создания новых компонентов Delphi 7

Мастер создания новых компонентов (рис. 5.8) создаст для нас шаблон. Поскольку элементы из состава библиотеки ComCtl32 есть не что иное, как окна со специфическими свойствами, наш компонент мы породим от TWinControl. IP-редактор представляет собой окно класса WC_IPADDRESS.

Название нового компонента выбрано TCustomiPEdit. Такая схема принята разработчиками Delphi для большинства компонентов VCL. Непосредственным предком, допустим, TEdit является компонент TCustomEdit.

Первым делом при создании компонента — особо не раздумывая — следует опубликовать типовые свойства и события, которые есть у большинства визуальных компонентов. Чтобы не занимать место в книге, позаимствуем их список у любого другого компонента из модуля ComCtrls.pas.

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

Рис. 5.9.Тестовое приложение, содержащее IP-редактор (внизу)

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

Элемент управления обрабатывает шесть сообщений (см. документацию MSDN), которые сведены в табл. 5.8.

Таблица 5.8.Сообщения, обрабатываемые элементом управления IP Address Control

Сообщение Назначение
IPM CLEARADDRESS Очистить поле адреса
IPM GETADDRESS Считать адрес
IPM_ISBLANK Проверить, не пустое ли поле адреса
IPM SETADDRESS Установить адрес
IPM_SETFOCUS Передать фокус заданному полю элемента управления
IPM_SETRANGE Установить ограничения на значения в заданном поле

Кроме перечисленных, IP-редактор извещает приложение об изменениях, произведенных пользователем, путем посылки ему сообщения WM_NOTIFY.

Следует иметь в виду, что IP-редактор не является потомком обычного редактора (TCustomEdit) и не обрабатывает характерные для того сообщения ЕМ_ХХХХ, так что название TCustomipEdit отражает только внешнее сходство.

В создаваемом коде компонента первым делом нужно переписать конструктор Create и метод createParams. Последний метод вызывается перед созданием окна для установки его будущих параметров. Именно здесь нужно инициализировать библиотеку общих элементов управления ComCtl32 и породить новый класс окна.

constructor TIPEditor.Create(AOwner: TComponent);

begin

inherited Create(AOwner);

ControlStyle := [csCaptureMouse, csClickEvents, csDoubleClicks, csOpaque];

Color := clBtnFace;

Width := 160;

Height := 25;

Align := alNone;

end;

procedure TIPEditor.CreateParams(var Params: TCreateParams);

begin

InitCommonControl(ICC_INTERNET_CLASSES);

inherited CreateParams(Params);

CreateSubClass(Params, WC_IPADDRESS);

end;

После создания свое значение получает дескриптор окна Handle (это свойство унаследовано от TwinControl). Все чтение/запись свойств элемента происходит путем обмена сообщениями с использованием этого дескриптора. Минимально необходимыми для работы являются свойства IP (задает IP-адрес в редакторе), ipstring (отображает его в виде текстовой строки) и процедура clear (очищает редактор).

Реализовано это следующим образом:

Листинг 5.2.Исходный код компонента TCustomlPEdit

unit uIPEdit;

interface

uses

Windows, Messages, SysUtils, Classes, Controls;

type

TCustomlPEdit = class(TWinControl)

private

{ Private declarations }

FIPAddress: DWORD;

FIPLimits: array [0..3] of word;

FCurrentField : Integer;

//procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey);

message CM_WANTSPECIALKEY;

procedure WMGetDlgCode(var Message: TWMGetDlgCode);

message WM_GETDLGCODE;

procedure CMDialogChar(var Message: TCMDialogChar);

message CM_DIALOGCHAR;

//procedure CMDialogKey(var Message: TCMDialogKey);

message CM_DIALOGKEY;

procedure CNNotify(var Message: TWMNotify);

message CN_NOTIFY;

protected

{ Protected declarations }

function GetIP(Index: Integer): Byte;

procedure SetIP(Index: Integer; Value: Byte);

function GetMinIP(Index: Integer): Byte;

procedure SetMinIP(Index: Integer; Value: Byte);

function GetMaxIP(Index: Integer): Byte;

procedure SetMaxIP(Index: Integer; Value: Byte);

function GetlPString: string;

procedure SetlPString(Value: string);

function IsBlank: boolean;

procedure SetCurrentFieldfIndex: Integer);

//

procedure CreateParams(var Params: TCreateParams); override;

procedure CreateWnd; override;

//procedure KeyDown(var Key: Word; Shift: TShiftState);override;

function IPDwordToString(dw: DWORD): string;

function IPStringToDword(s: string): DWORD;

public

{ Public declarations }

constructor Create(AOwner: TComponent);

override;

property IP[Index: Integer]: byte read GetIP write SetIP;

property MinIP[Index: Integer]: byte read GetMinIP write SetMinIP;

property MaxIP[Index: Integer]: byte read GetMaxIP write SetMaxIP;

property IPString : string read GetlPString write SetlPString;

property CurrentField : Integer read FCurrentField write SetCurrentField;

procedure Clear;

end;

TIPEdit = class(TCustomlPEdit)

published

property Align;

property Anchors;

property BorderWidth;

property DragCursor;

property DragKind;

property DragMode;

property Enabled;

property Font;

property Hint;

property Constraints;

property ParentShowHint;

property PopupMenu;

property ShowHint;

property TabOrder;

property TabStop;

property Visible;

property OnContextPopup;

property OnDragDrop;

property OnDragOver;

property OnEndDock;

property OnEndDrag;

property OnEnter;

property OnExit;

property OnMouseDown;

property OnMouseMove;

property OnMouseUp;

property OnStartDock;

property OnStartDrag;

{ Published declarations }

property IPString;

end;

procedure Register;

implementation

uses Graphics, commctrl, comctrls;

constructor TCustomlPEdit.Create(AOwner: TComponent);

begin

inherited Create(AOwner);

FIPAddress := 0;

ControlStyle := [csCaptureMouse, csClickEvents, csDoubleClicks, csOpaque];

Color := clBtnFace;

Width := 160;

Height := 25;

Align := alNone;

TabStop := True; end;

procedure TCustomlPEdit.CreateParams(var Params: TCreateParams);

begin

InitCommonControl(ICC_INTERNET_CLASSES);

inherited CreateParams(Params); CreateSubClass(Params, WC_IPADDRESS);

with Params do

begin

Style := WS_VISIBLE or WS_BORDER or WS_CHILD;

if NewStyleControls and CtlSD then

begin

Style := Style and not WS_BORDER; ExStyle := ExStyle or WS_EX_CLIENTEDGE;

end;

end;

end;

procedure TCustomlPEdit.CreateWnd;

var i: Integer;

begin

inherited CreateWnd; Clear;

{ for i := 0 to 3 do

begin

MinIP[i] := 0; MaxIP[i] := $FF; end; }

CurrentField := 0;

end;

procedure TCustomlPEdit.WMGetDlgCode(var Message: TWMGetDlgCode);

begin

inherited;

Message.Result := {Message.Result or} DLGC_WANTTAB;

end;

procedure TCustomlPEdit.CNNotify(var Message: TWMNotify);

begin

with Message.NMHdr" do

begin case Code of

IPN_FIELDCHANGED : begin

FCurrentField := PNMIPAddress(Message.NMHdr)~.iField; {if Assigned(OnlpFieldChange) then

with PNMIPAdress(Message.NMHdr)^ do begin

OnIPFieldChange(Self, iField, iValue);}

end;

end;

end;

end;

(procedure TCustomlPEdit.KeyDown(var Key: Word; Shift: TShiftState);

begin

inherited KeyDown(Key, Shift);

if Key = VKJTAB then if ssShift in Shift then

CurrentField := (CurrentField -1+4) mod 4

else

CurrentField := (CurrentField + I) mod 4; end; }

{procedure TCustomlPEdit.CMWantSpecialKey(var Msg: TCMWantSpecialKey);

begin

inherited;

//Msg.Result := Ord(Char(Msg.CharCode) = #9) ; end;}

procedure TCustomlPEdit.CMDialogChar(var Message: TCMDialogChar);

begin with Message do

if CharCode = VKJTAB then

begin

Message.Result := 0; if GetKeyState(VK_SHIFT)<>0 then

begin

if (CurrentField=0) then Exit; CurrentField := CurrentField — 1;

end

else

begin

if (CurrentField=3) then Exit; CurrentField := CurrentField + 1;

end;

Message.Result := 1; end //VK_TAB

else

inherited; end;

{procedure TCustomlPEdit.CMDialogKey(var Message: TCMDialogKey);

begin

if (Focused or Windows.IsChild(Handle, Windows.GetFocus))

and

(Message.CharCode = VK_TAB) and (GetKeyState(VK_CONTROL) < 0) then

begin

if GetKeyState (VK_SHIFT) 00 then

CurrentField := (CurrentField -1+4) mod 4

else

CurrentField := (CurrentField + 1) ir.oci 4; Message.Result := 1;

end else

inherited; end; }

function TCustomlPEdit.GetIP(Index: Integer): Byte;

begin

SendMessage

(Handle,IPM_GETADDRESS,0,longint(@FipAddress));

case Index of

1 : Result := FIRST_IPADDRESS(FipAddress);

2 : Result := SECOND_IPADDRESS(FipAddress) ;

3 : Result := THIRD_IPADDRESS(FipAddress);

4 : Result := FOURTH_IPADDRESS(FipAddress); else Result := 0;

end;

end;

procedure TCustomlPEdit.SetIP(Index: Integer; Value: Byte);

begin

case Index of

1: FIPAddress := FIPAddress AND $FFFFFF or DWORD(Value) shl 24;

2: FIPAddress := FIPAddress AND $FFOOFFFF or DWORD(Value) shl 16;

3: FIPAddress := FIPAddress AND $FFFFOOFF or DWORD(Value) shl 8;

4: FIPAddress := FIPAddress AND $FFFFFFOO or DWORD(Value);

else Exit;

end;

SendMessage(Handle, IPM_SETADDRESS, 0, FIPAddress);

end;

function TCustomlPEdit.GetMinIP(Index: Integer): Byte; begin if (Index<0) or (Index>3) then

Result := 0

else

Result := LoByte(FIPLimits[Index]);

end;

procedure TCustomlPEdit.SetMinIP(Index: Integer; Value: Byte);

begin

if (Index<0) or (Index>3)

then Exit;

FIPLimits[Index] := MAKEIPRANGE(HiByte(FIPLimits[Index]), Value);

SendMessage(Handle, IPM_SETRANGE, Index, FIPLimits[Index]);

end;

function TCustomlPEdit.GetMaxIP(Index: Integer): Byte; begin if (Index<0) or (Index>3)

then

Result := 0

else

Result := HiByte(FIPLimits[Index]);

end;

procedure TCustomlPEdit.SetMaxIP(Index: Integer; Value: Byte);

begin

if (Index<0) or (Index>3) then Exit;

FIPLimits[Index] := MAKEIPRANGE(Value, LoByte(FIPLimits[Index]));

SendMessage(Handle, IPM_SETRANGE, Index, FIPLimits[Index]);

end;

procedure TCustomlPEdit.Clear,

begin

SendMessage(Handle, IPM_CLEARADDRESS, 0, 0);

end;

function TCustomlPEdit.IsBlank: boolean;

begin

Result:= SendMessage(Handle, IPM_ISBLANK, 0, 0) = 0;

end;

procedure TCustomlPEdit.SetCurrentField(Index: Integer);

begin

if (Index<0) or (Index>3)

then Exit;

FCurrentField := Index;

SendMessage(Handle, IPM_SETFOCUS, wParam(FCurrentField), 0) ;

end;

function TCustomlPEdit.IPDwordToString(dw: DWORD): string;

begin

Result := Format('%d.%d.%d.%d',

[FIRST_IPADDRESS(dw),

SECOND_IPADDRESS(dw),

THIRD_IPADDRESS(dw),

FOURTH_IPADDRESS(dw)]);

end;

function TCustomlPEdit.IPStringToDword(s: string): DWORD;

var i,j : Integer;

NewAddr, Part : DWORD;

begin

NewAddr := 0;

try

i := 0; repeat

j := PosC. ', s); if j<=l then if i<3 then

Abort else

Part := StrToInt(s) else

Part := StrToInt(Copy(s, I, j-1));

if Part>255 then Abort; Delete(s, 1, j);

NewAddr := (NewAddr shl 8) or Part;

Inc(i);

until i>3;

Result := NewAddr;

//Windows.MessageBox(0, pChar(IntToHex(FIPAddress, 8)), '', MB_Ok);

except end;

end;

function TCustomlPEdit.GetlPString: string;

begin

SendMessage(Handle,IPM_GETADDRESS, 0, longint(SFIPAddress));

Result := IpDwordToString(FIPAddress);

end;

procedure TCustomlPEdit.SetlPString(Value: string);

begin

FIPAddress := IPStringToDword(Value);

SendMessage(Handle, IPM_SETADDRESS, 0, FIPAddress);

end;

procedure Register;

begin

RegisterComponents('Samples', [TIPEdit]);

end;

end.

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

Резюме

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

С элементами управления вам так или иначе придется сталкиваться во всех последующих главах.

 

 

ЧАСТНОЕ УЧРЕЖДЕНИЕ ОБРАЗОВАНИЯ


Поделиться:

Дата добавления: 2014-12-03; просмотров: 106; Мы поможем в написании вашей работы!; Нарушение авторских прав





lektsii.com - Лекции.Ком - 2014-2024 год. (0.005 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав
Главная страница Случайная страница Контакты