Home

VCL Controls: The Labeled Edit Box

 

The IP Address Control

 

Introduction

The IP Address control is an object that allows the user to enter an IP address or you to retrieve one. The control appears like an edit box or a masked edit box divided in four (semi-independent) sections:

The IP Address control is aware of the basic rules of IP address formatting. To proceed with the control, the user can click the first field and start typing. Each section allows only digits. By default, the control is configured to allow only numbers that range from 0 to 255 but you the programmer can change this allowed range. It does not allow a negative character. If the user enters a value higher than the allowed, the number is reset. Each field can allow only three digits. Once a valid value has been entered in a field, the focus shifts to the next section to the right.

Operations on an IP Address Control

To create an IP Address control, you can either use the traditional Win32 approach or create your own component that would implement the behavior set by the Win32 API. Because in this book we will not create custom components, we will use the Win32 technique. Therefore, to create an IP Address control, call the CreateWindow() or the CreateWindowEx() function and specify the class name as WC_IPADDRESS. Here is an example:

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
	void __fastcall FormCreate(TObject *Sender);
private:
	HWND hWndIPAddress; // User declarations
public: // User declarations
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	hWndIPAddress = CreateWindowEx( 0,
					WC_IPADDRESS,
					NULL,
					WS_CHILD | WS_VISIBLE | WS_TABSTOP,
					90, 14, 120, 20,
					Handle,
					NULL,
					HInstance,
					NULL );
}
//---------------------------------------------------------------------------

Some of the jobs you will perform on an IP Address control consist of checking whether the control contains an address, setting an IP address in its fields, retrieving the current address from its fields, or deleting an address from its fields.

Before doing anything on an IP Address control, you may want to check whether its fields are filled with some entries. To do this, you can send an IPM_ISBLANK message using the SendMessage() function. Because you are only checking the contents of the control, the wParam and the lParam parameters are not used and must be passed with 0 values. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
	BOOL IsThereAnAddress = SendMessage(hWndIPAddress, IPM_ISBLANK, 0, 0);

	if( IsThereAnAddress == True )
		ShowMessage("There is no IP address");
}
//---------------------------------------------------------------------------

On the other hand, if the control already contains an IP address, whether it is complete or not, before performing such operations as changing its values or else, you may want to completely delete the current IP address. This is done by sending an IPM_CLEARADDRESS message to the control using the SendMessage() function. The wParam and the lParam parameters are not used and will be passed as 0. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	SendMessage(hWndIPAddress, IPM_CLEARADDRESS, 0, 0);
}
//---------------------------------------------------------------------------

By default, when the IP Address control is created, it is blank: its field do not contain values. Whether the control is empty or not, if you want to fill it up, you must first create an address. This is done by calling the MAKEIPADDRESS macro. Its syntax is:

LPARAM MAKEIPADDRESS(BYTE b0, BYTE b1, BYTE b2, BYTE b3);

This macro simply requires 4 byte values as arguments. Each value should range from 0 to 255. Here is an example:

MAKEIPADDRESS(212, 56, 198, 92);

The MAKEIPADDRESS macro is only used to create an address. If you want to pass that address to an IP Address control, you can send it an IPM_SETADDRESS message using the SendMessage() function. The wParam argument is not used and must be passed as 0. The address to be set is passed as the lParam argument, which results from a call to the MAKEIPADDRESS macro. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	LPARAM lpAdr = MAKEIPADDRESS(212, 56, 198, 92);

	hWndIPAddress = CreateWindowEx( 0,
					WC_IPADDRESS,
					NULL,
					WS_CHILD | WS_VISIBLE | WS_TABSTOP,
					90, 14, 120, 20,
					Handle,
					NULL,
					HInstance,
					NULL );

	SendMessage(hWndIPAddress, IPM_SETADDRESS, 0, lpAdr);
}
//---------------------------------------------------------------------------

If the control already contains an address and you want to retrieve it, send it an IPM_GETADDRESS message using the SendMessage() function. The syntax you would use is:

lResult = SendMessage((HWND) hWndControl,
		      (UINT) IPM_GETADDRESS,
		      0,
		      (LPARAM) lParam);

This version of the SendMessage() function returns the number of non-empty fields of the address. Each one of the four fields of an IP address has a particular value. The values of these fields can be identified using the following macros:

BYTE FIRST_IPADDRESS(LPARAM lParam);
BYTE SECOND_IPADDRESS(LPARAM lParam);
BYTE THIRD_IPADDRESS(LPARAM lParam);
BYTE FOURTH_IPADDRESS(LPARAM lParam);

Each one of these macros retrieves the value stored in their respective fields. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	DWORD CurAddress;

	LRESULT SM = SendMessage(hWndIPAddress, IPM_GETADDRESS, 0,
				(LPARAM)(LPDWORD)&CurAddress);

	BYTE IPPart1 = FIRST_IPADDRESS((LPARAM)CurAddress);
	BYTE IPPart2 = SECOND_IPADDRESS((LPARAM)CurAddress);
	BYTE IPPart3 = THIRD_IPADDRESS((LPARAM)CurAddress);
	BYTE IPPart4 = FOURTH_IPADDRESS((LPARAM)CurAddress);

	ShowMessage("First:\t\t" + AnsiString(IPPart1) + "\n" +
		    "Second:\t\t" + AnsiString(IPPart2) + "\n" +
		    "Third:\t\t" + AnsiString(IPPart3) + "\n" +
		    "Fourth:\t\t" + AnsiString(IPPart4) + "\n" +
		    "Non-Blank Fields: " + AnsiString(SM));
}
//---------------------------------------------------------------------------

When the fields of an IP Address control are empty, the user can fill them up with some vales. To use it, the user must give it focus and start typing. Once he has provided the three digits of a field, the caret moves to the next field. This is automatically done. If you want to programmatically set the focus to a particular field in response to some user’s action, you can send an IPM_SETFOCUS message to the control. The fields of the control are in a zero-based array where the most left field has an index of 0 and the most right field has an index of 3. To set focus to a field, pass its index as the wParam parameter. The lParam parameter is not used.

By default, each field of an IP address has a range of values from a minimum whose default value is 0 and a maximum whose default value is 255. The control is so much aware of these values that, if the user tries entering a value that is lower than the set range, the control would not respond. For example if the user tries typing – for a negative value, it would not be accepted. On the other hand, if the user tries to enter a value that is higher than the range, the control would reset the field to the set maximum. If you want to control the range of values allowed in a particular field, create it using the MAKEIPRANGE macro. Its syntax is:

LPARAM MAKEIPRANGE(BYTE low, BYTE high);

The MAKEIPRANGE macro is only used to create a range of values. In order to actually assign this range to an IP Address control, send an IPM_SETRANGE message to the control using the SendMessage() function. The wParam parameter is used to specify the index of the field whose range you want to set. The lParam parameter contains the new range set by the return value of the MAKEIPRANGE macro. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	LPARAM wRangeForField3 = MAKEIPRANGE(52, 212);

	hWndIPAddress = CreateWindowEx( 0,
					WC_IPADDRESS,
					NULL,
					WS_CHILD | WS_VISIBLE | WS_TABSTOP,
					90, 14, 120, 20,
					Handle,
					NULL,
					HInstance,
					NULL );

	SendMessage(hWndIPAddress, IPM_SETRANGE, 2, wRangeForField3);
}
//---------------------------------------------------------------------------

Normally, you will usually need to control the range of values for a field in response to the user’s entry in the previous field. This assignment is not handled by the control because it lets the programmer take this role and responsibility.

IP Address Control Events

Although the IP Address control is not an edit box, both share a few characteristics such as their appearance. Like every visual and non-static control, in order to use an IP Address control, the user must give it focus. This can be done by clicking a field in the control. When the IP Address control receives focus, it sends an EN_SETFOCUS message, which produces an event similar to the Edit control’s OnEnter() event.

Like the edit control, when the user starts typing a new value in the IP Address control, it sends an EN_CHANGE message which produces an OnChange() event (similar to that of the Edit control). If the user starts changing the value of a field, the control sends the IPN_FIELDCHANGED notification message.

If the user clicks away, which causes the control to lose focus, it sends an EN_KILLFOCUS message. This produces an event similar to the OnExit() event of the VCL’s Edit control.

 

 
Home Copyright © 2005-2012, FunctionX, Inc.