📄 ipaddr.cpp
字号:
// Adjust child controls appropriately
for (int ii = 0; ii < 4; ii++)
m_Addr[ii].EnableWindow(bEnable);
}
Invalidate();
}
LONG CIPAddrCtl::OnSetFont(UINT wParam, LONG lParam)
{
// Note: font passed on to children, but we don't
// use it, the system font is much nicer for printing
// the dots, since they show up much better
for (int ii = 0; ii < 4; ii++)
m_Addr[ii].SendMessage(WM_SETFONT, wParam, lParam);
return 0;
}
LONG CIPAddrCtl::OnGetAddress(UINT wParam, LONG lParam)
{
BOOL bStatus;
int i, nAddr[4], nInError = 0;
BOOL bPrintErrors = (BOOL) wParam; // Cast wParam as a flag
IPA_ADDR* lpIPAddr = (IPA_ADDR*) lParam; // Cast lParam as an IPA_ADDR structure
if (NULL == lpIPAddr) // If it's a bad pointer, return an error
return FALSE;
memset(lpIPAddr, 0, sizeof(IPA_ADDR)); // Zero out the returned data
// Parse the fields and return an error indication if something bad was detected
for (i = 0; i < 4; i++)
{
bStatus = ParseAddressPart(m_Addr[i], nAddr[i]);
if (!bStatus) // If it failed to parse, quit now
{
nInError = i + 1; // Remember which address part was in error
break; // Break out of for loop
}
}
if (!bStatus) // Error detected during parse?
{
lpIPAddr->nInError = nInError; // Show where it occurred
if (bPrintErrors) // If they want us to print error messages
{
CString szText;
if (nAddr[i] < 0)
szText = _T("Missing value in IP address");
else
szText.Format(_T("%d is not a valid entry. Please specify a value between 0 and 255 for this field."), nAddr[i]);
MessageBox(szText, _T("Error"), MB_OK | MB_ICONEXCLAMATION);
}
m_Addr[i].SetFocus(); // Set focus to offending byte
m_Addr[i].SetSel(0, -1); // Select entire contents
return FALSE; // Return an error
}
lpIPAddr->nAddr1 = nAddr[0]; // Return the pieces to the caller
lpIPAddr->nAddr2 = nAddr[1];
lpIPAddr->nAddr3 = nAddr[2];
lpIPAddr->nAddr4 = nAddr[3];
lpIPAddr->nInError = 0; // No error to report
return TRUE; // Return success
}
LONG CIPAddrCtl::OnSetAddress(UINT wParam, LONG lParam)
{
CString szText;
IPA_ADDR* lpIPAddr = (IPA_ADDR*) lParam; // Cast lParam as an IPA_ADDR structure
// Format their data and load the edit controls
szText.Format(_T("%u"), lpIPAddr->nAddr1);
m_Addr[0].SetWindowText(szText);
szText.Format(_T("%u"), lpIPAddr->nAddr2);
m_Addr[1].SetWindowText(szText);
szText.Format(_T("%u"), lpIPAddr->nAddr3);
m_Addr[2].SetWindowText(szText);
szText.Format(_T("%u"), lpIPAddr->nAddr4);
m_Addr[3].SetWindowText(szText);
return TRUE;
}
LONG CIPAddrCtl::OnSetReadOnly(UINT wParam, LONG lParam)
{
m_bReadOnly = (BOOL) wParam;
for (int ii = 0; ii < 4; ii++)
m_Addr[ii].SetReadOnly(m_bReadOnly);
Invalidate();
return TRUE;
}
BOOL CIPAddrCtl::ParseAddressPart(CEdit& edit, int& n)
{
CString szText;
edit.GetWindowText(szText); // Get text from edit control
if (szText.IsEmpty()) // Empty text is an error
{
n = -1; // Return bogus value
return FALSE; // Return parse failure to caller
}
n = _ttoi(szText); // Grab a decimal value from edit text
if (n < 0 || n > 255) // If it is out of range, return an error
return FALSE;
return TRUE; // Looks acceptable, return success
}
CIPAddrEdit* CIPAddrCtl::GetEditControl(int nIndex)
{
if (nIndex < 1 || nIndex > 4)
return NULL;
return &m_Addr[nIndex - 1];
}
/////////////////////////////////////////////////////////////////////////////
// CIPAddrEdit
CIPAddrEdit::CIPAddrEdit()
{
}
CIPAddrEdit::~CIPAddrEdit()
{
}
void CIPAddrEdit::SetParent(CIPAddrCtl* pParent)
{
m_pParent = pParent; // Save pointer to parent control
}
BEGIN_MESSAGE_MAP(CIPAddrEdit, CEdit)
//{{AFX_MSG_MAP(CIPAddrEdit)
ON_WM_CHAR()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CIPAddrEdit message handlers
void CIPAddrEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// Logic for this function:
// Tab and dot are forwarded to the parent. Tab (or shift-tab) operate
// just like expected (focus moves to next control after the parent).
// Dot or space causes the parent to set focus to the next child edit (if
// focus is currently set to one of the first three edit controls).
// Numerics (0..9) and control characters are forwarded to the standard
// CEdit OnChar method; all other characters are dropped.
if (VK_TAB == nChar ||
'.' == nChar ||
' ' == nChar ||
VK_RETURN == nChar)
m_pParent->OnChildChar(nChar, nRepCnt, nFlags, *this);
else if (('0' <= nChar && '9'>= nChar) || iscntrl(nChar))
{
CEdit::OnChar(nChar, nRepCnt, nFlags);
// Automatically advance to next child control if 3 characters were entered;
// use "-" to indicate field was full to OnChildChar
if (3 == GetWindowTextLength())
m_pParent->OnChildChar('-', 0, nFlags, *this);
}
else
::MessageBeep(0xFFFFFFFF);
}
void CIPAddrEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// Handle the left and right arrow keys. If the left arrow key is pressed
// with the caret at the left of the input text, shift focus to the previous
// control (if in edit controls 2-4). Likewise for the right arrow key.
// This is done by calling the parent's OnChildChar method.
// If not left or right arrow, or not at beginning or end, call default
// OnKeyDown processor so key down gets passed to edit control.
if (VK_LEFT == nChar || VK_RIGHT == nChar)
{
CPoint ptCaret = GetCaretPos();
int nCharPos = LOWORD(CharFromPos(ptCaret));
if ((VK_LEFT == nChar && nCharPos == 0) ||
(VK_RIGHT == nChar && nCharPos == GetWindowTextLength()))
m_pParent->OnChildChar(nChar, nRepCnt, nFlags, *this);
}
else if (VK_ESCAPE == nChar)
{
// Must handle VK_ESCAPE specially.
// In a normal dialog, VK_ESCAPE gets handled by the dialog box window process,
// and the edit control never sees the character. When the edit control lives
// on a property page, this doesn't happen. If VK_ESCAPE is not handled here
// then when the escape key is pressed the entire control disappears from the
// dialog! If the parent of the control is a dialog, and the dialog's parent
// is also a dialog, that's a sign that the control is on a property page.
TCHAR cClass1[12];
TCHAR cClass2[12];
// Clear out window class name arrays
memset(cClass1, 0, sizeof(cClass1));
memset(cClass2, 0, sizeof(cClass2));
// Get parent and parent's parent window pointers
CWnd* pDialog = m_pParent->GetParent(); // Get parent of the IP address edit control
CWnd* pDialogParent = pDialog->GetParent(); // Get its parent
// Get class names of the windows that own the IP address edit control and its parent
if (NULL != pDialog)
::GetClassName(pDialog->m_hWnd, cClass1, sizeof(cClass1)/sizeof(TCHAR));
if (NULL != pDialogParent)
::GetClassName(pDialogParent->m_hWnd, cClass2, sizeof(cClass2)/sizeof(TCHAR));
// If parent is a dialog, and parent's parent is a dialog, simulate Cancel button press
if (0 == _tcscmp(cClass1, szDialogClass) && 0 == _tcscmp(cClass2, szDialogClass))
{
CWnd* pCancel = pDialogParent->GetDlgItem(IDCANCEL); // Get the Cancel button
pDialogParent->SendMessage(WM_COMMAND,
MAKEWPARAM(IDCANCEL, BN_CLICKED),
(LPARAM) (NULL != pCancel->m_hWnd ? pCancel->m_hWnd : NULL));
return;
}
}
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
/////////////////////////////////////////////////////////////////////////////
// DDX routines
void DDX_IPAddr(CDataExchange* pDX, int nIDC, unsigned char* nAddr)
{
IPA_ADDR x;
HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
ASSERT(hWndCtrl);
CIPAddrCtl* pIPAddrCtl = (CIPAddrCtl*) CWnd::FromHandle(hWndCtrl);
ASSERT(pIPAddrCtl);
if (!pDX->m_bSaveAndValidate)
{
// Load IP address control with current data
x.nAddr1 = nAddr[0]; // Copy address bytes over
x.nAddr2 = nAddr[1];
x.nAddr3 = nAddr[2];
x.nAddr4 = nAddr[3];
pIPAddrCtl->SetAddress(&x);
}
else
{
// Save contents of IP address control
BOOL bStatus = pIPAddrCtl->GetAddress(TRUE, &x);
if (!bStatus)
{
// x.nInError contains the 1-based index of the address field that was in error
pDX->m_hWndLastControl = pIPAddrCtl->GetEditControl(x.nInError)->m_hWnd; // Set HWND of control to set focus on
pDX->m_bEditLastControl = TRUE; // It's an edit control (so Fail selects the text)
pDX->Fail(); // Fail DDX
}
nAddr[0] = x.nAddr1;
nAddr[1] = x.nAddr2;
nAddr[2] = x.nAddr3;
nAddr[3] = x.nAddr4;
}
}
void DDX_IPAddr(CDataExchange* pDX, int nIDC, CString& szAddr)
{
IPA_ADDR x;
HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
ASSERT(hWndCtrl);
CIPAddrCtl* pIPAddrCtl = (CIPAddrCtl*) CWnd::FromHandle(hWndCtrl);
ASSERT(pIPAddrCtl);
if (!pDX->m_bSaveAndValidate)
{
// Convert string to numbers
unsigned char nAddr[4];
memset(nAddr, 0, 4);
// Get numbers
for (int ii = 0; ii < 4; ii++)
{
if (ii < 3)
{
int nIndex = szAddr.Find(_T('.'));
if (-1 != nIndex)
{
nAddr[ii] = (unsigned char) _ttoi(szAddr.Left(nIndex));
szAddr = szAddr.Mid(nIndex + 1);
}
}
else
nAddr[ii] = (unsigned char) _ttoi(szAddr);
}
// Load IP address control with current data
x.nAddr1 = nAddr[0]; // Copy address bytes over
x.nAddr2 = nAddr[1];
x.nAddr3 = nAddr[2];
x.nAddr4 = nAddr[3];
pIPAddrCtl->SetAddress(&x);
}
else
{
// Save contents of IP address control
BOOL bStatus = pIPAddrCtl->GetAddress(TRUE, &x);
if (!bStatus)
{
// x.nInError contains the 1-based index of the address field that was in error
pDX->m_hWndLastControl = pIPAddrCtl->GetEditControl(x.nInError)->m_hWnd; // Set HWND of control to set focus on
pDX->m_bEditLastControl = TRUE; // It's an edit control (so Fail selects the text)
pDX->Fail(); // Fail DDX
}
szAddr.Format(_T("%d.%d.%d.%d"),
(unsigned char) x.nAddr1, (unsigned char) x.nAddr2,
(unsigned char) x.nAddr3, (unsigned char) x.nAddr4);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -