using System; using System.Runtime.InteropServices; using static Vanara.PInvoke.User32; namespace Vanara.PInvoke { public static partial class ComCtl32 { /// /// Creates IP address controls. These controls are similar to an edit control, but they enable you to enter a numeric address in /// Internet protocol (IP) format. /// public const string WC_IPADDRESS = "SysIPAddress32"; private const int IPN_FIRST = -860; #pragma warning disable 1584, 1711, 1572, 1581, 1580 /// IP Address Messages public enum IPAddressMessage { /// Clears the contents of the IP address control. /// Must be zero. /// Must be zero. /// The return value is not used. IPM_CLEARADDRESS = WindowMessage.WM_USER + 100, /// Sets the address values for all four fields in the IP address control. /// Must be zero. /// /// A DWORD value that contains the new address. The field 3 value is contained in bits 0 through 7. The field 2 value is /// contained in bits 8 through 15. The field 1 value is contained in bits 16 through 23. The field 0 value is contained in bits /// 24 through 31. The MAKEIPADDRESS macro can also be used to create the address information. /// /// The return value is not used. IPM_SETADDRESS = WindowMessage.WM_USER + 101, /// Gets the address values for all four fields in the IP address control. /// Must be zero. /// /// A pointer to a DWORD value that receives the address. The field 3 value will be contained in bits 0 through 7. The field 2 /// value will be contained in bits 8 through 15. The field 1 value will be contained in bits 16 through 23. The field 0 value /// will be contained in bits 24 through 31. The FIRST_IPADDRESS, SECOND_IPADDRESS, THIRD_IPADDRESS, and FOURTH_IPADDRESS macros /// can also be used to extract the address information. Zero will be returned as the address for any blank fields. /// /// Returns the number of nonblank fields. IPM_GETADDRESS = WindowMessage.WM_USER + 102, /// ets the valid range for the specified field in the IP address control. /// /// If the user enters a value in the field that is outside of this range, the control will send the IPN_FIELDCHANGED /// notification with the entered value. If the value is still outside of the range after sending the notification, the control /// will attempt to change the entered value to the closest range limit. /// /// A zero-based field index to which the range will be applied. /// /// A WORD value that contains the lower limit of the range in the low-order byte and the upper limit in the high-order byte. /// Both of these values are inclusive. The MAKEIPRANGE macro can also be used to create the range. /// /// Returns nonzero if successful, or zero otherwise. IPM_SETRANGE = WindowMessage.WM_USER + 103, /// /// Sets the keyboard focus to the specified field in the IP address control. All of the text in that field will be selected. /// /// /// A zero-based field index to which the focus should be set. If this value is greater than the number of fields, focus is set /// to the first blank field. If all fields are nonblank, focus is set to the first field. /// /// Must be zero. /// The return value is not used. IPM_SETFOCUS = WindowMessage.WM_USER + 104, /// Determines if all fields in the IP address control are blank. /// Must be zero. /// Must be zero. /// Returns nonzero if all fields are blank, or zero otherwise. IPM_ISBLANK = WindowMessage.WM_USER + 105, } /// IP Address Notifications public enum IPAddressNotification { /// /// Sent when the user changes a field in the control or moves from one field to another. This notification code is sent in the /// form of a WM_NOTIFY message. /// /// /// A pointer to an NMIPADDRESS structure that contains information about the changed address. The iValue member of this /// structure will contain the entered value, even if it is out of the range of the field. You can modify this member to any /// value that is within the range for the field in response to this notification code. /// /// The return value is ignored. IPN_FIELDCHANGED = IPN_FIRST - 0 } #pragma warning restore 1584, 1711, 1572, 1581, 1580 /// Gets the IP address represented as a byte array from an unsigned pointer. /// The IP address. /// The IP address represented as a byte array. public static byte[] GET_IPADDRESS(uint ipAddress) => new[] { (byte)((ipAddress >> 24) & 0xff), (byte)((ipAddress >> 16) & 0xff), (byte)((ipAddress >> 8) & 0xff), (byte)(ipAddress & 0xff) }; /// Packs four byte-values into a single LPARAM suitable for use with the IPM_SETADDRESS message. /// The field 0 address. /// The field 1 address. /// The field 2 address. /// The field 3 address. /// Returns an LPARAM value that contains the address. [PInvokeData("Commctrl.h", MSDNShortId = "bb761385")] public static uint MAKEIPADDRESS(byte b0, byte b1, byte b2, byte b3) => ((uint)b0 << 24) + ((uint)b1 << 16) + ((uint)b2 << 8) + b3; /// Packs four byte-values into a single LPARAM suitable for use with the IPM_SETADDRESS message. /// The bytes ordered 0-3. /// Returns an LPARAM value that contains the address. [PInvokeData("Commctrl.h", MSDNShortId = "bb761385")] public static uint MAKEIPADDRESS(byte[] bytes) { if (bytes != null && bytes.Length != 4) throw new ArgumentOutOfRangeException(nameof(bytes), "Array must contain exactly four items."); return bytes == null ? 0 : MAKEIPADDRESS(bytes[0], bytes[1], bytes[2], bytes[3]); } /// Packs two byte-values into a single LPARAM suitable for use with the IPM_SETRANGE message. /// The lower limit of the range. /// The upper limit of the range. /// Returns an LPARAM value that contains the range. [PInvokeData("Commctrl.h", MSDNShortId = "bb761386")] public static uint MAKEIPRANGE(byte low, byte high) => (uint)((high << 8) + low); /// Contains information for the IPN_FIELDCHANGED notification code. [PInvokeData("Commctrl.h", MSDNShortId = "bb761375")] [StructLayout(LayoutKind.Sequential)] public struct NMIPADDRESS { /// An NMHDR structure that contains additional information about the notification. public NMHDR hdr; /// The zero-based number of the field that was changed. public int iField; /// /// The new value of the field specified in the iField member. While processing the IPN_FIELDCHANGED notification, this member /// can be set to any value that is within the range of the field and the control will place this new value in the field. /// public int iValue; } } }