Программирование на Delphi 7
f65d50f6

Сообщения обрабатываемые



Таблица 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 отношения не имеющая.

 



Содержание раздела