CIPAddressCtrl 雖非編輯控制項,但內部包含 4 個子編輯控制項 (每個八位組一個)。當任一欄位內容變更,會發送 EN_CHANGE 通知。透過 Spy++ 可得知子編輯控制項 ID 為 1135 (各欄位共用同一 ID)。
afx_msg void OnChangeIpField();ON_EN_CHANGE(1135, OnChangeIpField)
void CMyDlg::OnChangeIpField() {
DWORD dwIp = 0;
m_ipCtrl.GetAddress(dwIp); // 取得 4 八位組打包值
BYTE b1 = FIRST_IPADDRESS(dwIp);
BYTE b2 = SECOND_IPADDRESS(dwIp);
BYTE b3 = THIRD_IPADDRESS(dwIp);
BYTE b4 = FOURTH_IPADDRESS(dwIp);
// 即時驗證、顯示、聯動其他控制項...
}
SetAddress 需提供 4 個八位組,無法直接表示「100.6.x.x」這類網段。利用子視窗枚舉,逐欄設定文字:
void SetIpAddressCtrlNetwork(CIPAddressCtrl* pCtrl,
BYTE nField0, BYTE nField1, BYTE nField2, BYTE nField3, BYTE nFieldCount) {
if (!pCtrl) return;
pCtrl->ClearAddress();
if (nFieldCount == 0) return;
if (nFieldCount >= 4) {
pCtrl->SetAddress(nField0, nField1, nField2, nField3);
return;
}
BYTE fields[4] = { nField0, nField1, nField2, nField3 };
HWND hChild = ::GetWindow(pCtrl->m_hWnd, GW_CHILD);
int idx = 3; // 子視窗順序為高位到低位? 實測為反序,需注意
while (hChild && idx >= 0) {
if (idx < nFieldCount) {
TCHAR sz[4]; _stprintf_s(sz, _T("%d"), fields[idx]);
::SetWindowText(hChild, sz);
}
hChild = ::GetWindow(hChild, GW_HWNDNEXT);
idx--;
}
}
注意:子視窗遍歷順序可能因版本不同而異,建議搭配 Spy++ 確認實際順序再調整 idx 邏輯。
善用 EN_CHANGE 實現即時回饋,結合子視窗文字設定突破 SetAddress 限制,讓 IP 位址控制項更靈活好用。