網絡程序頻繁需要用戶輸入 IPv4 地址。用普通 TEdit 不僅需自行驗證格式(四段 0-255),還要手動處理字符串與 32 位整數的轉換。Windows 內置的 IP Address Edit Control (SysIPAddress32) 完美解決這些問題:自動校驗、直接獲取/設置 32 位值、支持分段範圍限制。
IP 控件屬於 ICC_INTERNET_CLASSES 類,必須調用 InitCommonControlsEx 初始化:
#include <commctrl.h>
// 在 WinMain 或 FormCreate 最早處調用
INITCOMMONCONTROLSEX icc = {0};
icc.dwSize = sizeof(icc);
icc.dwICC = ICC_INTERNET_CLASSES;
if (!InitCommonControlsEx(&icc)) {
// 初始化失敗處理
return;
}
注意: 僅調用 InitCommonControls 不會載入 IE3+ 新增的網絡類控件。
使用 CreateWindowEx,窗口類名為 WC_IPADDRESS (定義在 commctrl.h,值為 "SysIPAddress32"):
HWND hIpEdit = CreateWindowEx(
0, WC_IPADDRESS, NULL,
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
10, 10, 135, 25, // 位置、大小
hwndParent, // 父窗口
(HMENU)IDC_IPADDRESS, // 控件 ID
hInstance, NULL
);
在 C++ Builder 中,可在 FormCreate 動態創建,或放置一個 TPanel 後用 SetParent 移入。
| 消息常量 | 值 | 用途 | 參數/返回 |
|---|---|---|---|
| IPM_CLEARADDRESS | WM_USER+100 | 清空所有字段 | wParam/lParam=0 |
| IPM_SETADDRESS | WM_USER+101 | 設置 IP 值 | lParam = 32位 IP (網絡序) |
| IPM_GETADDRESS | WM_USER+102 | 獲取 IP 值 | lParam = 指向 DWORD 的指針;返回非空字段數 |
| IPM_SETRANGE | WM_USER+103 | 限制某字段範圍 | wParam=字段索引(0-3);lParam低16位: 高字節=上限,低字節=下限 |
| IPM_SETFOCUS | WM_USER+104 | 設置輸入焦點到指定字段 | wParam=字段索引(0-3) |
| IPM_ISBLANK | WM_USER+105 | 判斷是否全空 | 返回非0=全空,0=有內容 |
// 宏:構造 32 位 IP 值 (網絡字節序)
#define MAKEIPADDRESS(b1,b2,b3,b4) \
((DWORD)(((DWORD)(b1)<<24) | ((DWORD)(b2)<<16) | ((DWORD)(b3)<<8) | (DWORD)(b4)))
// 設置 IP: 192.168.1.100
DWORD ip = MAKEIPADDRESS(192, 168, 1, 100);
SendMessage(hIpEdit, IPM_SETADDRESS, 0, (LPARAM)ip);
// 獲取 IP
DWORD ipOut = 0;
int fieldCount = SendMessage(hIpEdit, IPM_GETADDRESS, 0, (LPARAM)&ipOut);
if (fieldCount == 4) {
// 解析四段
int b1 = (ipOut >> 24) & 0xFF;
int b2 = (ipOut >> 16) & 0xFF;
int b3 = (ipOut >> 8) & 0xFF;
int b4 = ipOut & 0xFF;
}
// 限制第一段為 100~200
SendMessage(hIpEdit, IPM_SETRANGE, 0, (LPARAM)MAKELONG(100, 200)); // 低字節=下限,高字節=上限
// 清空
SendMessage(hIpEdit, IPM_CLEARADDRESS, 0, 0);
// 判斷是否為空
if (SendMessage(hIpEdit, IPM_ISBLANK, 0, 0)) {
ShowMessage("IP 不能為空");
}
用戶修改字段或焦點移動時,控件向父窗口發送 WM_NOTIFY,NMHDR::code == IPN_FIELDCHANGED:
// 在表單的 WndProc 或消息映射中處理
void __fastcall TForm1::WndProc(TMessage &Message) {
if (Message.Msg == WM_NOTIFY) {
LPNMHDR pNMHDR = (LPNMHDR)Message.LParam;
if (pNMHDR->code == IPN_FIELDCHANGED && pNMHDR->hwndFrom == hIpEdit) {
// 實時驗證、聯動更新等
DWORD ip; SendMessage(hIpEdit, IPM_GETADDRESS, 0, (LPARAM)&ip);
// ...
}
}
TForm::WndProc(Message);
}
若不想直接用 API,可將上述邏輯封裝為繼承自 TCustomControl 的 TIPAddressEdit 組件,發布 IPAddress (DWORD)、Range[4] 等屬性,並在 CreateParams 中指定 WC_IPADDRESS,實現設計時拖放使用。
Windows IP 控件是處理 IPv4 輸入的「瑞士軍刀」:原生、無依賴、功能完備。掌握 InitCommonControlsEx 初始化與六條核心消息,即可在任何 Win32 框架(C++ Builder、MFC、WTL、純 SDK)中高效集成。