Main Page | File List

ipaddr.cpp

00001 #pragma title("IP Address Custom Control Implementation")
00002 
00003 // Created by Joseph A. Dziedzic, September 1997
00004 // Revised April 1998
00005 // Thanks to Dan Anderson, Kenny Goers, Kevin Lussier, and Doug Miller for their suggestions
00006 // and code enhancements.
00007 // Mail comments to dziedzic@ma.ultranet.com
00008 
00009 
00010 #include "stdafx.h"
00011 #include "IPAddr.h"
00012 
00013 #ifdef _DEBUG
00014 #define new DEBUG_NEW
00015 #undef THIS_FILE
00016 static char THIS_FILE[] = __FILE__;
00017 #endif
00018 
00019 // Style bits for the individual edit controls
00020 const int WS_EDIT = WS_CHILD | WS_VISIBLE | ES_CENTER | ES_MULTILINE;
00021 const TCHAR szDialogClass[] = _T("#32770");                     // Special window class for dialogs
00022 
00023 BOOL CIPAddrCtl::m_bRegistered = Register();            // Register the control during class initialization
00024 
00026 // CIPAddrCtl
00027 
00028 IMPLEMENT_DYNCREATE(CIPAddrCtl, CWnd)
00029 
00030 CIPAddrCtl::CIPAddrCtl()
00031 {
00032         m_bEnabled = TRUE;                                                              // Window enabled flag (TRUE by default)
00033         m_bReadOnly = FALSE;                                                    // Read only flag (FALSE by default)
00034         m_bNoValidate = FALSE;                                                  // Don't do immediate field validation on input
00035 }
00036 
00037 CIPAddrCtl::~CIPAddrCtl()
00038 {
00039 }
00040 
00041 
00042 BEGIN_MESSAGE_MAP(CIPAddrCtl, CWnd)
00043         //{{AFX_MSG_MAP(CIPAddrCtl)
00044         ON_WM_CREATE()
00045         ON_WM_NCDESTROY()
00046         ON_WM_SIZE()
00047         ON_WM_SETFOCUS()
00048         ON_WM_PAINT()
00049         ON_WM_ENABLE()
00050         ON_WM_ERASEBKGND()
00051         ON_MESSAGE(WM_SETFONT, OnSetFont)
00052         ON_MESSAGE(IPAM_GETADDRESS, OnGetAddress)
00053         ON_MESSAGE(IPAM_SETADDRESS, OnSetAddress)
00054         ON_MESSAGE(IPAM_SETREADONLY, OnSetReadOnly)
00055         //}}AFX_MSG_MAP
00056 END_MESSAGE_MAP()
00057 
00058 
00060 // CIPAddrCtl message handlers
00061 
00062 BOOL CIPAddrCtl::Register()
00063 {
00064         // Register the window class of the control
00065         WNDCLASS        wc;
00066         wc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;    // Usual style bits
00067         wc.lpfnWndProc = IPAddrWndProc;                                 // Message processing code
00068         wc.cbClsExtra = 0;                                                              // No extra bytes needed
00069         wc.cbWndExtra = 0;
00070         wc.hInstance = NULL;                                                    // No instance handle
00071         wc.hIcon = NULL;                                                                // No icon
00072         wc.hCursor = ::LoadCursor(NULL, IDC_IBEAM);             // Use I-beam cursor (like edit control)
00073         wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);   // Use default window color (overriden in OnEraseBkgnd)
00074         wc.lpszMenuName = NULL;                                                 // No menus
00075         wc.lpszClassName = _T("IPAddr");                                // Class name
00076         if (!::RegisterClass(&wc))                                              // If registration failed, subsequent dialogs will fail
00077         {
00078                 ASSERT(FALSE);
00079                 return FALSE;
00080         }
00081         else
00082                 return TRUE;
00083 }
00084 
00085 BOOL CIPAddrCtl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, DWORD dwExStyle/*=0*/)
00086 {
00087         // Create a window class that has the properties we want
00088         CString szWndClass = AfxRegisterWndClass(CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW,
00089                 ::LoadCursor(NULL, IDC_IBEAM), (HBRUSH) COLOR_WINDOW+1);
00090 
00091         // Create using the extended window style
00092 #if _MSC_VER >= 1100
00093         // Original VC 5.0 stuff
00094         return CWnd::CreateEx(dwExStyle, szWndClass, NULL, dwStyle, rect, pParentWnd, nID);
00095 #else
00096         // Back ported to VC 4.2
00097         return CWnd::CreateEx(dwExStyle, szWndClass, NULL, dwStyle,
00098                 rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
00099                 pParentWnd->GetSafeHwnd(), (HMENU) nID);
00100 #endif
00101 }
00102 
00103 LRESULT CALLBACK IPAddrWndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
00104 {
00105         switch (uiMsg)                                                                  // Dispatch on message type
00106         {
00107         case WM_NCCREATE:                                                               // On WM_NCCREATE we create a C++ object and attach it to the control
00108                 {
00109                         CIPAddrCtl* pCtl = new CIPAddrCtl;              // Create an instance of the class
00110                         ASSERT(pCtl);                                                   // Better not fail!
00111                         BOOL b = pCtl->SubclassWindow(hWnd);    // Attach the window handle to the new object
00112                         ASSERT(b);                                                              // Better not fail!
00113                         return b;                                                               // Return result to continue/abort window creation
00114                         break;
00115                 }
00116         default:                                                                                // All other messages go through default window processor
00117                 return ::DefWindowProc(hWnd, uiMsg, wParam, lParam);
00118         }
00119 }
00120 
00121 int CIPAddrCtl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
00122 {
00123         if (CWnd::OnCreate(lpCreateStruct) == -1)       
00124                 return -1;
00125 
00126         // Save the "no immediate validation on input" style setting
00127         m_bNoValidate = (lpCreateStruct->style & IPAS_NOVALIDATE);
00128 
00129         // Set the styles for the parent control
00130         ModifyStyleEx(0, WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY);
00131 
00132         // Create the four edit controls used to obtain the four parts of the IP address (size
00133         // of controls gets set during OnSize)
00134         for (int ii = 0; ii < 4; ii++)
00135         {
00136                 m_Addr[ii].Create(WS_EDIT, CRect(0,0,0,0), this, IDC_ADDR1 + ii);
00137                 m_Addr[ii].LimitText(3);
00138                 m_Addr[ii].SetParent(this);
00139         }
00140         
00141         return 0;
00142 }
00143 
00144 void CIPAddrCtl::OnNcDestroy() 
00145 {
00146         CWnd::OnNcDestroy();
00147         
00148         // Make sure the window was destroyed
00149         ASSERT(NULL == m_hWnd);
00150 
00151         // Destroy this object since it won't be destroyed otherwise
00152         delete this;
00153 }
00154 
00155 void CIPAddrCtl::OnSize(UINT nType, int cx, int cy) 
00156 {
00157         CWnd::OnSize(nType, cx, cy);
00158 
00159         // Get the width of a "." drawn in the control
00160         CDC*    pDC = GetDC();
00161         CSize   szDot = pDC->GetTextExtent(_T("."), 1);
00162         int nDotWidth = szDot.cx;
00163         ReleaseDC(pDC); 
00164 
00165         // Based on the size of the parent window, compute the width & height of the edit
00166         // controls.  Leave room for the three "." which will be drawn on the parent window
00167         // to separate the four parts of the IP address.
00168         CRect   rcClient;
00169         GetClientRect(&rcClient);
00170         int nEditWidth = (rcClient.Width() - (3 * nDotWidth)) / 4;
00171         int nEditHeight = rcClient.Height();
00172         int cyEdge = ::GetSystemMetrics(SM_CYEDGE);
00173 
00174         // Compute rectangles for the edit controls, then move the controls into place
00175         CRect rect = CRect(0, cyEdge, nEditWidth, nEditHeight);
00176         for (int ii = 0; ii < 4; ii++)
00177         {
00178                 m_rcAddr[ii] = rect;
00179                 m_Addr[ii].MoveWindow(rect);
00180                 rect.OffsetRect(nEditWidth + nDotWidth, 0);
00181         }
00182 
00183         rect = CRect(nEditWidth, 0, nEditWidth + nDotWidth, nEditHeight);
00184         for (ii = 0; ii < 3; ii++)
00185         {
00186                 m_rcDot[ii] = rect;
00187                 rect.OffsetRect(nEditWidth + nDotWidth, 0);
00188         }
00189 }
00190 
00191 void CIPAddrCtl::OnSetFocus(CWnd* pOldWnd) 
00192 {
00193         CWnd::OnSetFocus(pOldWnd);
00194         
00195         m_Addr[0].SetFocus();                                                   // Set focus to first edit control
00196         m_Addr[0].SetSel(0, -1);                                                // Select entire contents
00197 }
00198 
00199 // Protected function called by the edit control (friend class) when it receives a
00200 // character which should be processed by the parent
00201 void CIPAddrCtl::OnChildChar(UINT nChar, UINT nRepCnt, UINT nFlags, CIPAddrEdit& child)
00202 {
00203         switch (nChar)
00204         {
00205         case '.':                                                                               // Dot means advance to next edit control (if in first 3)
00206         case VK_RIGHT:                                                                  // Ditto for right arrow at end of text
00207         case ' ':                                                                               // Ditto for space
00208                 {
00209                 UINT nIDC = child.GetDlgCtrlID();                       // Get control ID of the edit control
00210                 if (nIDC < IDC_ADDR4)                                           // Move focus to appropriate edit control and select entire contents
00211                 {
00212                         m_Addr[nIDC - IDC_ADDR1 + 1].SetFocus();
00213                         if (VK_RIGHT != nChar)                                  // Re-select text unless arrow key entered
00214                                 m_Addr[nIDC - IDC_ADDR1 + 1].SetSel(0, -1);
00215                 }               
00216                 break;
00217                 }
00218 
00219         case VK_LEFT:                                                                   // Left arrow means move to previous edit control (if in last 3)
00220                 {
00221                 UINT nIDC = child.GetDlgCtrlID();                       // Get control ID of the edit control
00222                 if (nIDC > IDC_ADDR1)                                           // Move focus to appropriate edit control
00223                         m_Addr[nIDC - IDC_ADDR1 - 1].SetFocus();
00224                 break;
00225                 }
00226 
00227         case VK_TAB:                                                                    // Tab moves between controls in the dialog
00228                 {
00229                 CWnd*   pWnd;
00230                 SHORT nShift = ::GetKeyState(VK_SHIFT);         // Get state of shift key
00231                 if (nShift < 0)
00232                         pWnd = GetParent()->GetNextDlgTabItem(this, TRUE);
00233                 else
00234                         pWnd = GetParent()->GetNextDlgTabItem(this, FALSE);
00235                 if (NULL != pWnd)                                                       // If there's a control, set focus to it
00236                         pWnd->SetFocus();
00237                 break;
00238                 }
00239 
00240         case VK_RETURN:                                                                 // Return implies default pushbutton press
00241                 {
00242                 DWORD dw = ((CDialog*) GetParent())->GetDefID();        // Get ID of default pushbutton
00243                 if (DC_HASDEFID == HIWORD(dw))                          // If there is a default pushbutton, simulate pressing it
00244                 {
00245                         CWnd* pWnd = GetParent()->GetDlgItem(LOWORD(dw));       // Get the control
00246                         WPARAM wp = MAKEWPARAM(LOWORD(dw), BN_CLICKED);         // Build wParam for WM_COMMAND
00247                         GetParent()->SendMessage(WM_COMMAND, wp, (LPARAM) pWnd->m_hWnd);        // Fake like button was pressed
00248                 }
00249                 }
00250                 break;
00251 
00252         case '-':                                                                               // "Field full" indication
00253                 // Validate the contents for proper values (unless suppressed)
00254                 if (!m_bNoValidate)                                                     // If not suppressing immediate validation
00255                 {
00256                         CString         szText;
00257 
00258                         child.GetWindowText(szText);                    // Get text from edit control
00259                         int n = _ttoi(szText);                                  // Get numeric value from edit control
00260                         if (n < 0 || n > 255)                                   // If out of range, notify parent
00261                         {
00262                                 szText.Format(_T("%d is not a valid entry.  Please specify a value between 0 and 255 for this field."), n);
00263                                 MessageBox(szText, _T("Error"), MB_OK | MB_ICONEXCLAMATION);
00264                                 child.SetFocus();                                       // Set focus to offending field
00265                                 child.SetSel(0, -1);                            // Select all text
00266                                 return;
00267                         }
00268                 }
00269 
00270                 // Advance to next field
00271                 OnChildChar('.', 0, nFlags, child);
00272                 break;
00273 
00274         default:
00275                 TRACE(_T("Unexpected call to CIPAddrCtl::OnChildChar!\n"));
00276         }
00277 }
00278 
00279 void CIPAddrCtl::OnPaint() 
00280 {
00281         CPaintDC dc(this); // device context for painting
00282 
00283         // Save mode and set to transparent (so background remains)
00284         int nOldMode = dc.SetBkMode(TRANSPARENT);
00285 
00286         // If disabled, set text color to COLOR_GRAYTEXT, else use COLOR_WINDOWTEXT
00287         COLORREF crText;
00288         if (m_bEnabled)
00289                 crText = ::GetSysColor(COLOR_WINDOWTEXT);
00290         else
00291                 crText = ::GetSysColor(COLOR_GRAYTEXT);
00292         COLORREF crOldText = dc.SetTextColor(crText);
00293 
00294         // Draw the three "." which separate the four edit controls
00295         for (int ii = 0; ii < 3; ii++)
00296                 dc.DrawText(_T("."), 1, m_rcDot[ii], DT_CENTER | DT_SINGLELINE | DT_BOTTOM);
00297 
00298         // Restore old mode and color
00299         dc.SetBkMode(nOldMode);
00300         dc.SetTextColor(crOldText);
00301 
00302         // Do not call CWnd::OnPaint() for painting messages
00303 }
00304 
00305 BOOL CIPAddrCtl::OnEraseBkgnd(CDC* pDC) 
00306 {
00307         CRect   rcClient;
00308         GetClientRect(&rcClient);
00309 
00310         if (m_bEnabled && !m_bReadOnly)
00311                 ::FillRect(pDC->m_hDC, rcClient, (HBRUSH) (COLOR_WINDOW+1));
00312         else
00313                 ::FillRect(pDC->m_hDC, rcClient, (HBRUSH) (COLOR_BTNFACE+1));
00314 
00315         return TRUE;
00316 }
00317 
00318 void CIPAddrCtl::OnEnable(BOOL bEnable) 
00319 {
00320         CWnd::OnEnable(bEnable);
00321         
00322         // Nothing to do unless the window state has changed
00323         if (bEnable != m_bEnabled)
00324         {
00325                 // Save new state
00326                 m_bEnabled = bEnable;
00327 
00328                 // Adjust child controls appropriately
00329                 for (int ii = 0; ii < 4; ii++)
00330                         m_Addr[ii].EnableWindow(bEnable);
00331         }
00332 
00333         Invalidate();
00334 }
00335 
00336 LONG CIPAddrCtl::OnSetFont(UINT wParam, LONG lParam)
00337 {
00338         // Note: font passed on to children, but we don't
00339         // use it, the system font is much nicer for printing
00340         // the dots, since they show up much better
00341 
00342         for (int ii = 0; ii < 4; ii++)
00343                 m_Addr[ii].SendMessage(WM_SETFONT, wParam, lParam);
00344 
00345         return 0;
00346 }
00347 
00348 LONG CIPAddrCtl::OnGetAddress(UINT wParam, LONG lParam)
00349 {
00350         BOOL bStatus;
00351         int     i, nAddr[4], nInError = 0;
00352 
00353         BOOL bPrintErrors = (BOOL) wParam;                              // Cast wParam as a flag
00354         IPA_ADDR* lpIPAddr = (IPA_ADDR*) lParam;                // Cast lParam as an IPA_ADDR structure
00355         if (NULL == lpIPAddr)                                                   // If it's a bad pointer, return an error
00356                 return FALSE;
00357         memset(lpIPAddr, 0, sizeof(IPA_ADDR));                  // Zero out the returned data
00358 
00359         // Parse the fields and return an error indication if something bad was detected
00360         for (i = 0; i < 4; i++)
00361         {
00362                 bStatus = ParseAddressPart(m_Addr[i], nAddr[i]);
00363                 if (!bStatus)                                                           // If it failed to parse, quit now
00364                 {
00365                         nInError = i + 1;                                               // Remember which address part was in error
00366                         break;                                                                  // Break out of for loop
00367                 }
00368         }
00369         if (!bStatus)                                                                   // Error detected during parse?
00370         {
00371                 lpIPAddr->nInError = nInError;                          // Show where it occurred
00372                 if (bPrintErrors)                                                       // If they want us to print error messages
00373                 {
00374                         CString szText;
00375                         if (nAddr[i] < 0)
00376                                 szText = _T("Missing value in IP address");
00377                         else
00378                                 szText.Format(_T("%d is not a valid entry.  Please specify a value between 0 and 255 for this field."), nAddr[i]);
00379                         MessageBox(szText, _T("Error"), MB_OK | MB_ICONEXCLAMATION);
00380                 }
00381                 m_Addr[i].SetFocus();                                           // Set focus to offending byte
00382                 m_Addr[i].SetSel(0, -1);                                        // Select entire contents
00383                 return FALSE;                                                           // Return an error
00384         }
00385 
00386         lpIPAddr->nAddr1 = nAddr[0];                                    // Return the pieces to the caller
00387         lpIPAddr->nAddr2 = nAddr[1];
00388         lpIPAddr->nAddr3 = nAddr[2];
00389         lpIPAddr->nAddr4 = nAddr[3];
00390         lpIPAddr->nInError = 0;                                                 // No error to report
00391         return TRUE;                                                                    // Return success
00392 }
00393 
00394 LONG CIPAddrCtl::OnSetAddress(UINT wParam, LONG lParam)
00395 {
00396         CString         szText;
00397 
00398         IPA_ADDR* lpIPAddr = (IPA_ADDR*) lParam;                // Cast lParam as an IPA_ADDR structure
00399 
00400         // Format their data and load the edit controls
00401         szText.Format(_T("%u"), lpIPAddr->nAddr1);
00402         m_Addr[0].SetWindowText(szText);
00403         szText.Format(_T("%u"), lpIPAddr->nAddr2);
00404         m_Addr[1].SetWindowText(szText);
00405         szText.Format(_T("%u"), lpIPAddr->nAddr3);
00406         m_Addr[2].SetWindowText(szText);
00407         szText.Format(_T("%u"), lpIPAddr->nAddr4);
00408         m_Addr[3].SetWindowText(szText);
00409         return TRUE;
00410 }
00411 
00412 LONG CIPAddrCtl::OnSetReadOnly(UINT wParam, LONG lParam)
00413 {
00414         m_bReadOnly = (BOOL) wParam;
00415 
00416         for (int ii = 0; ii < 4; ii++)
00417                 m_Addr[ii].SetReadOnly(m_bReadOnly);
00418 
00419         Invalidate();
00420         return TRUE;
00421 }
00422 
00423 BOOL CIPAddrCtl::ParseAddressPart(CEdit& edit, int& n)
00424 {
00425         CString         szText;
00426 
00427         edit.GetWindowText(szText);                                             // Get text from edit control
00428         if (szText.IsEmpty())                                                   // Empty text is an error
00429         {
00430                 n = -1;                                                                         // Return bogus value
00431                 return FALSE;                                                           // Return parse failure to caller
00432         }
00433 
00434         n = _ttoi(szText);                                                              // Grab a decimal value from edit text
00435         if (n < 0 || n > 255)                                                   // If it is out of range, return an error
00436                 return FALSE;
00437 
00438         return TRUE;                                                                    // Looks acceptable, return success
00439 }
00440 
00441 CIPAddrEdit* CIPAddrCtl::GetEditControl(int nIndex)
00442 {
00443         if (nIndex < 1 || nIndex > 4)
00444                 return NULL;
00445         return &m_Addr[nIndex - 1];
00446 }
00447 
00448 
00450 // CIPAddrEdit
00451 
00452 CIPAddrEdit::CIPAddrEdit()
00453 {
00454 }
00455 
00456 CIPAddrEdit::~CIPAddrEdit()
00457 {
00458 }
00459 
00460 void CIPAddrEdit::SetParent(CIPAddrCtl* pParent)
00461 {
00462         m_pParent = pParent;                                                    // Save pointer to parent control
00463 }
00464 
00465 
00466 BEGIN_MESSAGE_MAP(CIPAddrEdit, CEdit)
00467         //{{AFX_MSG_MAP(CIPAddrEdit)
00468         ON_WM_CHAR()
00469         ON_WM_KEYDOWN()
00470         //}}AFX_MSG_MAP
00471 END_MESSAGE_MAP()
00472 
00474 // CIPAddrEdit message handlers
00475 
00476 void CIPAddrEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
00477 {
00478         // Logic for this function:
00479         // Tab and dot are forwarded to the parent.  Tab (or shift-tab) operate
00480         // just like expected (focus moves to next control after the parent).
00481         // Dot or space causes the parent to set focus to the next child edit (if
00482         // focus is currently set to one of the first three edit controls).
00483         // Numerics (0..9) and control characters are forwarded to the standard
00484         // CEdit OnChar method; all other characters are dropped.
00485         if (VK_TAB == nChar ||
00486                 '.' == nChar ||
00487                 ' ' == nChar ||
00488                 VK_RETURN == nChar)
00489                 m_pParent->OnChildChar(nChar, nRepCnt, nFlags, *this);
00490         else if (('0' <= nChar && '9'>= nChar) || iscntrl(nChar))
00491         {
00492                 CEdit::OnChar(nChar, nRepCnt, nFlags);
00493 
00494                 // Automatically advance to next child control if 3 characters were entered;
00495                 // use "-" to indicate field was full to OnChildChar
00496                 if (3 == GetWindowTextLength())
00497                         m_pParent->OnChildChar('-', 0, nFlags, *this);
00498         }
00499         else
00500                 ::MessageBeep(0xFFFFFFFF);
00501 }
00502 
00503 void CIPAddrEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
00504 {
00505         // Handle the left and right arrow keys.  If the left arrow key is pressed
00506         // with the caret at the left of the input text, shift focus to the previous
00507         // control (if in edit controls 2-4).  Likewise for the right arrow key.
00508         // This is done by calling the parent's OnChildChar method.
00509         // If not left or right arrow, or not at beginning or end, call default
00510         // OnKeyDown processor so key down gets passed to edit control.
00511         if (VK_LEFT == nChar || VK_RIGHT == nChar)
00512         {
00513                 CPoint ptCaret = GetCaretPos();
00514                 int nCharPos = LOWORD(CharFromPos(ptCaret));
00515                 if ((VK_LEFT == nChar && nCharPos == 0) ||
00516                         (VK_RIGHT == nChar && nCharPos == GetWindowTextLength()))
00517                         m_pParent->OnChildChar(nChar, nRepCnt, nFlags, *this);
00518         }
00519         else if (VK_ESCAPE == nChar)
00520         {
00521                 // Must handle VK_ESCAPE specially.
00522                 // In a normal dialog, VK_ESCAPE gets handled by the dialog box window process,
00523                 // and the edit control never sees the character.  When the edit control lives
00524                 // on a property page, this doesn't happen.  If VK_ESCAPE is not handled here
00525                 // then when the escape key is pressed the entire control disappears from the
00526                 // dialog!  If the parent of the control is a dialog, and the dialog's parent
00527                 // is also a dialog, that's a sign that the control is on a property page.
00528                 TCHAR   cClass1[12];
00529                 TCHAR   cClass2[12];
00530 
00531                 // Clear out window class name arrays
00532                 memset(cClass1, 0, sizeof(cClass1));
00533                 memset(cClass2, 0, sizeof(cClass2));
00534 
00535                 // Get parent and parent's parent window pointers
00536                 CWnd* pDialog = m_pParent->GetParent();         // Get parent of the IP address edit control
00537                 CWnd* pDialogParent = pDialog->GetParent();     // Get its parent
00538 
00539                 // Get class names of the windows that own the IP address edit control and its parent
00540                 if (NULL != pDialog)
00541                         ::GetClassName(pDialog->m_hWnd, cClass1, sizeof(cClass1)/sizeof(TCHAR));
00542                 if (NULL != pDialogParent)
00543                         ::GetClassName(pDialogParent->m_hWnd, cClass2, sizeof(cClass2)/sizeof(TCHAR));
00544 
00545                 // If parent is a dialog, and parent's parent is a dialog, simulate Cancel button press
00546                 if (0 == _tcscmp(cClass1, szDialogClass) && 0 == _tcscmp(cClass2, szDialogClass))
00547                 {
00548                         CWnd* pCancel = pDialogParent->GetDlgItem(IDCANCEL);    // Get the Cancel button
00549                         pDialogParent->SendMessage(WM_COMMAND,
00550                                 MAKEWPARAM(IDCANCEL, BN_CLICKED),
00551                                 (LPARAM) (NULL != pCancel->m_hWnd ? pCancel->m_hWnd : NULL));
00552                         return;
00553                 }
00554         }
00555         CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
00556 }
00557 
00559 // DDX routines
00560 
00561 void DDX_IPAddr(CDataExchange* pDX, int nIDC, unsigned char* nAddr)
00562 {
00563         IPA_ADDR x;
00564 
00565         HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
00566         ASSERT(hWndCtrl);
00567         CIPAddrCtl* pIPAddrCtl = (CIPAddrCtl*) CWnd::FromHandle(hWndCtrl);
00568         ASSERT(pIPAddrCtl);
00569 
00570         if (!pDX->m_bSaveAndValidate)
00571         {
00572                 // Load IP address control with current data
00573                 x.nAddr1 = nAddr[0];                                            // Copy address bytes over
00574                 x.nAddr2 = nAddr[1];
00575                 x.nAddr3 = nAddr[2];
00576                 x.nAddr4 = nAddr[3];
00577                 pIPAddrCtl->SetAddress(&x);
00578         }
00579         else
00580         {
00581                 // Save contents of IP address control
00582                 BOOL bStatus = pIPAddrCtl->GetAddress(TRUE, &x);
00583                 if (!bStatus)
00584                 {
00585                         // x.nInError contains the 1-based index of the address field that was in error
00586                         pDX->m_hWndLastControl = pIPAddrCtl->GetEditControl(x.nInError)->m_hWnd;        // Set HWND of control to set focus on
00587                         pDX->m_bEditLastControl = TRUE;                 // It's an edit control (so Fail selects the text)
00588                         pDX->Fail();                                                    // Fail DDX
00589                 }
00590                 nAddr[0] = x.nAddr1;
00591                 nAddr[1] = x.nAddr2;
00592                 nAddr[2] = x.nAddr3;
00593                 nAddr[3] = x.nAddr4;
00594         }
00595 }
00596 
00597 void DDX_IPAddr(CDataExchange* pDX, int nIDC, CString& szAddr)
00598 {
00599         IPA_ADDR x;
00600 
00601         HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
00602         ASSERT(hWndCtrl);
00603         CIPAddrCtl* pIPAddrCtl = (CIPAddrCtl*) CWnd::FromHandle(hWndCtrl);
00604         ASSERT(pIPAddrCtl);
00605 
00606         if (!pDX->m_bSaveAndValidate)
00607         {
00608         // Convert string to numbers
00609         unsigned char nAddr[4];
00610         memset(nAddr, 0, 4);
00611 
00612         // Get numbers
00613         for (int ii = 0; ii < 4; ii++)
00614         {
00615             if (ii < 3)
00616             {
00617                 int nIndex = szAddr.Find(_T('.'));
00618                 if (-1 != nIndex)
00619                 {
00620                     nAddr[ii] = (unsigned char) _ttoi(szAddr.Left(nIndex));
00621                     szAddr = szAddr.Mid(nIndex + 1);
00622                 }
00623             }
00624             else
00625                 nAddr[ii] = (unsigned char) _ttoi(szAddr);
00626         }
00627 
00628                 // Load IP address control with current data
00629                 x.nAddr1 = nAddr[0];                                            // Copy address bytes over
00630                 x.nAddr2 = nAddr[1];
00631                 x.nAddr3 = nAddr[2];
00632                 x.nAddr4 = nAddr[3];
00633                 pIPAddrCtl->SetAddress(&x);
00634         }
00635         else
00636         {
00637                 // Save contents of IP address control
00638                 BOOL bStatus = pIPAddrCtl->GetAddress(TRUE, &x);
00639                 if (!bStatus)
00640                 {
00641                         // x.nInError contains the 1-based index of the address field that was in error
00642                         pDX->m_hWndLastControl = pIPAddrCtl->GetEditControl(x.nInError)->m_hWnd;        // Set HWND of control to set focus on
00643                         pDX->m_bEditLastControl = TRUE;                 // It's an edit control (so Fail selects the text)
00644                         pDX->Fail();                                                    // Fail DDX
00645                 }
00646         szAddr.Format(_T("%d.%d.%d.%d"),
00647                 (unsigned char) x.nAddr1, (unsigned char) x.nAddr2,
00648                 (unsigned char) x.nAddr3, (unsigned char) x.nAddr4);
00649         }
00650 }

Generated on Mon May 8 22:27:08 2006 by  doxygen 1.3.9.1