|
|
/* Copyright (c) 1991, Microsoft Corporation, all rights reserved
ipaddr.c - TCP/IP Address custom control
November 9, 1992 Greg Strange */
#include "ctlspriv.h"
// The character that is displayed between address fields.
#define FILLER TEXT('.')
#define SZFILLER TEXT(".")
#define SPACE TEXT(' ')
#define BACK_SPACE 8
/* Min, max values */ #define NUM_FIELDS 4
#define CHARS_PER_FIELD 3
#define HEAD_ROOM 1 // space at top of control
#define LEAD_ROOM 3 // space at front of control
#define MIN_FIELD_VALUE 0 // default minimum allowable field value
#define MAX_FIELD_VALUE 255 // default maximum allowable field value
// All the information unique to one control is stuffed in one of these
// structures in global memory and the handle to the memory is stored in the
// Windows extra space.
typedef struct tagFIELD { HANDLE hWnd; WNDPROC lpfnWndProc; BYTE byLow; // lowest allowed value for this field.
BYTE byHigh; // Highest allowed value for this field.
} FIELD;
typedef struct tagIPADDR { HWND hwndParent; HWND hwnd; UINT uiFieldWidth; UINT uiFillerWidth; BOOL fEnabled : 1; BOOL fPainted : 1; BOOL bControlInFocus : 1; // TRUE if the control is already in focus, dont't send another focus command
BOOL bCancelParentNotify : 1; // Don't allow the edit controls to notify parent if TRUE
BOOL fInMessageBox : 1; // Set when a message box is displayed so that
BOOL fFontCreated :1; HFONT hfont; // we don't send a EN_KILLFOCUS message when
// we receive the EN_KILLFOCUS message for the
// current field.
FIELD Children[NUM_FIELDS];
HTHEME hTheme; } IPADDR;
// The following macros extract and store the CONTROL structure for a control.
#define IPADDRESS_EXTRA sizeof(DWORD)
#define GET_IPADDR_HANDLE(hWnd) ((HGLOBAL)(GetWindowLongPtr((hWnd), GWLP_USERDATA)))
#define SAVE_IPADDR_HANDLE(hWnd,x) (SetWindowLongPtr((hWnd), GWLP_USERDATA, (LONG_PTR)(x)))
/* internal IPAddress function prototypes */ LRESULT IPAddressWndFn( HWND, UINT, WPARAM, LPARAM ); LRESULT IPAddressFieldProc(HWND, UINT, WPARAM, LPARAM); BOOL SwitchFields(IPADDR *, int, int, WORD, WORD); void EnterField(FIELD *, WORD, WORD); BOOL ExitField(IPADDR *, int iField); int GetFieldValue(FIELD *); void SetFieldValue(IPADDR *pipa, int iField, int iValue);
/*
IPAddrInit() - IPAddress custom control initialization call hInstance = library or application instance return TRUE on success, FALSE on failure.
This function does all the one time initialization of IPAddress custom controls. Specifically it creates the IPAddress window class. */ int InitIPAddr(HANDLE hInstance) { WNDCLASS wc;
wc.lpszClassName = WC_IPADDRESS; wc.hCursor = LoadCursor(NULL,IDC_IBEAM); wc.hIcon = NULL; wc.lpszMenuName = (LPCTSTR)NULL; wc.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS|CS_GLOBALCLASS; wc.lpfnWndProc = IPAddressWndFn; wc.hInstance = hInstance; wc.hIcon = NULL; wc.cbWndExtra = IPADDRESS_EXTRA; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1 ); wc.cbClsExtra = 0;
return (RegisterClass(&wc) || (GetLastError() == ERROR_CLASS_ALREADY_EXISTS)); }
/*
IPAddressWndFn() - Main window function for an IPAddress control.
call hWnd handle to IPAddress window wMsg message number wParam word parameter lParam long parameter */
void FormatIPAddress(LPTSTR pszString, DWORD* dwValue) { int nField, nPos; BOOL fFinish = FALSE;
dwValue[0] = 0; dwValue[1] = 0; dwValue[2] = 0; dwValue[3] = 0;
if (pszString[0] == 0) return;
for( nField = 0, nPos = 0; !fFinish; nPos++) { if (( pszString[nPos]<TEXT('0')) || (pszString[nPos]>TEXT('9'))) { // not a number
nField++; fFinish = (nField == 4); } else { dwValue[nField] *= 10; dwValue[nField] += (pszString[nPos]-TEXT('0')); } } }
void IP_OnSetFont(IPADDR* pipa, HFONT hfont, BOOL fRedraw) { int i; RECT rect; HFONT OldFont; BOOL fNewFont = FALSE; UINT uiFieldStart; HDC hdc; if (hfont) { fNewFont = TRUE; } else { hfont = (HFONT)SendMessage(pipa->hwnd, WM_GETFONT, 0, 0); } hdc = GetDC(pipa->hwnd); OldFont = SelectObject(hdc, hfont); GetCharWidth(hdc, FILLER, FILLER, (int *)(&pipa->uiFillerWidth)); SelectObject(hdc, OldFont); ReleaseDC(pipa->hwnd, hdc); GetClientRect(pipa->hwnd, &rect); pipa->hfont = hfont; pipa->uiFieldWidth = (RECTWIDTH(rect) - LEAD_ROOM - pipa->uiFillerWidth *(NUM_FIELDS-1)) / NUM_FIELDS;
uiFieldStart = LEAD_ROOM;
for (i = 0; i < NUM_FIELDS; i++) {
HWND hwnd = pipa->Children[i].hWnd; if (fNewFont) SendMessage(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)fRedraw); SetWindowPos(hwnd, NULL, uiFieldStart, HEAD_ROOM, pipa->uiFieldWidth, (rect.bottom-rect.top), SWP_NOACTIVATE);
uiFieldStart += pipa->uiFieldWidth + pipa->uiFillerWidth;
} }
LRESULT IPAddressWndFn( hWnd, wMsg, wParam, lParam ) HWND hWnd; UINT wMsg; WPARAM wParam; LPARAM lParam; { LRESULT lResult; IPADDR *pipa; int i;
pipa = (IPADDR *)GET_IPADDR_HANDLE(hWnd); lResult = TRUE;
switch( wMsg ) {
// use empty string (not NULL) to set to blank
case WM_SETTEXT: { TCHAR szBuf[CHARS_PER_FIELD+1]; DWORD dwValue[4]; LPTSTR pszString = (LPTSTR)lParam;
FormatIPAddress(pszString, &dwValue[0]); pipa->bCancelParentNotify = TRUE;
for (i = 0; i < NUM_FIELDS; ++i) { if (pszString[0] == 0) { szBuf[0] = 0; } else { StringCchPrintf(szBuf, ARRAYSIZE(szBuf), TEXT("%d"), dwValue[i]); } SendMessage(pipa->Children[i].hWnd, WM_SETTEXT, 0, (LPARAM) (LPSTR) szBuf); }
pipa->bCancelParentNotify = FALSE;
SendMessage(pipa->hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hWnd), EN_CHANGE), (LPARAM)hWnd); } break;
case WM_GETTEXTLENGTH: case WM_GETTEXT: { int iFieldValue; DWORD dwValue[4]; TCHAR szResult[30]; TCHAR *pszDest = (TCHAR *)lParam;
lResult = 0; dwValue[0] = 0; dwValue[1] = 0; dwValue[2] = 0; dwValue[3] = 0;
for (i = 0; i < NUM_FIELDS; ++i) { iFieldValue = GetFieldValue(&(pipa->Children[i])); if (iFieldValue == -1) { iFieldValue = 0; } else { ++lResult; }
dwValue[i] = iFieldValue; }
StringCchPrintf(szResult, ARRAYSIZE(szResult), TEXT("%d.%d.%d.%d"), dwValue[0], dwValue[1], dwValue[2], dwValue[3] );
if (wMsg == WM_GETTEXT) { StringCchPrintf(pszDest, (int)wParam, szResult); lResult = lstrlen( pszDest ); } else { lResult = lstrlen(szResult); }
break; } case WM_GETDLGCODE : lResult = DLGC_WANTCHARS; break;
case WM_NCCREATE: SetWindowBits(hWnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE, WS_EX_CLIENTEDGE); SetWindowBits(hWnd, GWL_EXSTYLE, RTL_MIRRORED_WINDOW, 0);
lResult = TRUE; break;
case WM_THEMECHANGED: { if (pipa->hTheme) CloseThemeData(pipa->hTheme); pipa->hTheme = OpenThemeData(hWnd, L"Combobox");
InvalidateRect(hWnd, NULL, TRUE); } break;
case WM_CREATE : /* create pallette window */ { LONG id;
pipa = (IPADDR*)LocalAlloc(LPTR, sizeof(IPADDR));
if (pipa) { CREATESTRUCT* pcs = ((CREATESTRUCT *)lParam); SAVE_IPADDR_HANDLE(hWnd, pipa);
pipa->fEnabled = TRUE; pipa->hwndParent = pcs->hwndParent; pipa->hwnd = hWnd; pipa->hTheme = OpenThemeData(hWnd, L"Combobox");
id = GetDlgCtrlID(hWnd); for (i = 0; i < NUM_FIELDS; ++i) { pipa->Children[i].byLow = MIN_FIELD_VALUE; pipa->Children[i].byHigh = MAX_FIELD_VALUE;
pipa->Children[i].hWnd = CreateWindowEx(0, TEXT("Edit"), NULL, WS_CHILD | ES_CENTER, 0, 10, 100, 100, hWnd, (HMENU)(LONG_PTR)id, pcs->hInstance, (LPVOID)NULL);
SAVE_IPADDR_HANDLE(pipa->Children[i].hWnd, i); SendMessage(pipa->Children[i].hWnd, EM_LIMITTEXT, CHARS_PER_FIELD, 0L);
pipa->Children[i].lpfnWndProc = (WNDPROC) GetWindowLongPtr(pipa->Children[i].hWnd, GWLP_WNDPROC);
SetWindowLongPtr(pipa->Children[i].hWnd, GWLP_WNDPROC, (LONG_PTR)IPAddressFieldProc);
}
IP_OnSetFont(pipa, NULL, FALSE); for (i = 0; i < NUM_FIELDS; ++i) ShowWindow(pipa->Children[i].hWnd, SW_SHOW);
#undef pcs
} else DestroyWindow(hWnd); } lResult = 0; break;
case WM_PAINT: /* paint IPADDR window */ { PAINTSTRUCT Ps; RECT rect; COLORREF TextColor; COLORREF cRef; HFONT OldFont;
BeginPaint(hWnd, (LPPAINTSTRUCT)&Ps); OldFont = SelectObject( Ps.hdc, pipa->hfont); GetClientRect(hWnd, &rect); if (pipa->fEnabled) { TextColor = GetSysColor(COLOR_WINDOWTEXT); cRef = GetSysColor(COLOR_WINDOW); } else { TextColor = GetSysColor(COLOR_GRAYTEXT); cRef = GetSysColor(COLOR_3DFACE); }
FillRectClr(Ps.hdc, &rect, cRef); SetRect(&rect, 0, HEAD_ROOM, pipa->uiFillerWidth, (rect.bottom-rect.top));
SetBkColor(Ps.hdc, cRef); SetTextColor(Ps.hdc, TextColor);
for (i = 0; i < NUM_FIELDS-1; ++i) { rect.left += pipa->uiFieldWidth + pipa->uiFillerWidth; rect.right += rect.left + pipa->uiFillerWidth; ExtTextOut(Ps.hdc, rect.left, HEAD_ROOM, ETO_OPAQUE, &rect, SZFILLER, 1, NULL); }
pipa->fPainted = TRUE;
SelectObject(Ps.hdc, OldFont); EndPaint(hWnd, &Ps); } break;
case WM_SETFOCUS : /* get focus - display caret */ EnterField(&(pipa->Children[0]), 0, CHARS_PER_FIELD); break; HANDLE_MSG(pipa, WM_SETFONT, IP_OnSetFont);
case WM_LBUTTONDOWN : /* left button depressed - fall through */ SetFocus(hWnd); break;
case WM_ENABLE: { pipa->fEnabled = (BOOL)wParam; for (i = 0; i < NUM_FIELDS; ++i) { EnableWindow(pipa->Children[i].hWnd, (BOOL)wParam); } if (pipa->fPainted) InvalidateRect(hWnd, NULL, FALSE); } break;
case WM_NCPAINT: { if (pipa->hTheme) { HRGN hrgn = (wParam != 1) ? (HRGN)wParam : NULL; HBRUSH hbr = (HBRUSH)GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND);
if (CCDrawNonClientTheme(pipa->hTheme, hWnd, hrgn, hbr, 0, CBXS_NORMAL)) { return TRUE; } } } goto DoDefault;
case WM_DESTROY : // Restore all the child window procedures before we delete our memory block.
for (i = 0; i < NUM_FIELDS; ++i) { SendMessage(pipa->Children[i].hWnd, WM_DESTROY, 0, 0); SetWindowLongPtr(pipa->Children[i].hWnd, GWLP_WNDPROC, (LONG_PTR)pipa->Children[i].lpfnWndProc); }
if (pipa->hTheme) CloseThemeData(pipa->hTheme);
LocalFree(pipa); break;
case WM_COMMAND: switch (HIWORD(wParam)) { // One of the fields lost the focus, see if it lost the focus to another field
// of if we've lost the focus altogether. If its lost altogether, we must send
// an EN_KILLFOCUS notification on up the ladder.
case EN_KILLFOCUS: { HWND hFocus;
if (!pipa->fInMessageBox) { hFocus = GetFocus(); for (i = 0; i < NUM_FIELDS; ++i) if (pipa->Children[i].hWnd == hFocus) break;
if (i >= NUM_FIELDS) { SendMessage(pipa->hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hWnd), EN_KILLFOCUS), (LPARAM)hWnd); pipa->bControlInFocus = FALSE; } } } break;
case EN_SETFOCUS: { HWND hFocus;
if (!pipa->fInMessageBox) { hFocus = (HWND)lParam;
for (i = 0; i < NUM_FIELDS; ++i) if (pipa->Children[i].hWnd == hFocus) break;
// send a focus message when the
if (i < NUM_FIELDS && pipa->bControlInFocus == FALSE) { SendMessage(pipa->hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hWnd), EN_SETFOCUS), (LPARAM)hWnd);
pipa->bControlInFocus = TRUE; // only set the focus once
} } } break;
case EN_CHANGE: if (pipa->bCancelParentNotify == FALSE) { SendMessage(pipa->hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hWnd), EN_CHANGE), (LPARAM)hWnd);
} break; } break;
// Get the value of the IP Address. The address is placed in the DWORD pointed
// to by lParam and the number of non-blank fields is returned.
case IPM_GETADDRESS: { int iFieldValue; DWORD dwValue;
lResult = 0; dwValue = 0; for (i = 0; i < NUM_FIELDS; ++i) { iFieldValue = GetFieldValue(&(pipa->Children[i])); if (iFieldValue == -1) iFieldValue = 0; else ++lResult; dwValue = (dwValue << 8) + iFieldValue; } *((DWORD *)lParam) = dwValue; } break;
// Clear all fields to blanks.
case IPM_CLEARADDRESS: { pipa->bCancelParentNotify = TRUE; for (i = 0; i < NUM_FIELDS; ++i) { SendMessage(pipa->Children[i].hWnd, WM_SETTEXT, 0, (LPARAM) (LPSTR) TEXT("")); } pipa->bCancelParentNotify = FALSE; SendMessage(pipa->hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hWnd), EN_CHANGE), (LPARAM)hWnd); } break;
// Set the value of the IP Address. The address is in the lParam with the
// first address byte being the high byte, the second being the second byte,
// and so on. A lParam value of -1 removes the address.
case IPM_SETADDRESS: { pipa->bCancelParentNotify = TRUE;
for (i = 0; i < NUM_FIELDS; ++i) { BYTE bVal = HIBYTE(HIWORD(lParam)); if (pipa->Children[i].byLow <= bVal && bVal <= pipa->Children[i].byHigh) { SetFieldValue(pipa, i, bVal);
} else { lResult = FALSE; }
lParam <<= 8; }
pipa->bCancelParentNotify = FALSE;
SendMessage(pipa->hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hWnd), EN_CHANGE), (LPARAM)hWnd); } break;
case IPM_SETRANGE: if (wParam < NUM_FIELDS && LOBYTE(LOWORD(lParam)) <= HIBYTE(LOWORD(lParam))) { lResult = MAKEIPRANGE(pipa->Children[wParam].byLow, pipa->Children[wParam].byHigh); pipa->Children[wParam].byLow = LOBYTE(LOWORD(lParam)); pipa->Children[wParam].byHigh = HIBYTE(LOWORD(lParam)); break; } lResult = 0; break;
// Set the focus to this IPADDR.
// wParam = the field number to set focus to, or -1 to set the focus to the
// first non-blank field.
case IPM_SETFOCUS:
if (wParam >= NUM_FIELDS) { for (wParam = 0; wParam < NUM_FIELDS; ++wParam) if (GetFieldValue(&(pipa->Children[wParam])) == -1) break; if (wParam >= NUM_FIELDS) wParam = 0; } EnterField(&(pipa->Children[wParam]), 0, CHARS_PER_FIELD); break;
// Determine whether all four subfields are blank
case IPM_ISBLANK:
lResult = TRUE; for (i = 0; i < NUM_FIELDS; ++i) { if (GetFieldValue(&(pipa->Children[i])) != -1) { lResult = FALSE; break; } } break;
default: DoDefault: lResult = DefWindowProc( hWnd, wMsg, wParam, lParam ); break; } return( lResult ); }
/*
IPAddressFieldProc() - Edit field window procedure
This function sub-classes each edit field. */ LRESULT IPAddressFieldProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { IPADDR *pipa; FIELD *pField; HWND hIPADDRWindow; WORD wChildID; LRESULT lresult;
if (!(hIPADDRWindow = GetParent(hWnd))) return 0;
pipa = (IPADDR *)GET_IPADDR_HANDLE(hIPADDRWindow); if (!pipa) return 0; wChildID = (WORD)GET_IPADDR_HANDLE(hWnd); pField = &(pipa->Children[wChildID]);
if (pField->hWnd != hWnd) return 0;
switch (wMsg) { case WM_DESTROY: DeleteObject((HGDIOBJ)SendMessage(hWnd, WM_GETFONT, 0, 0)); return 0;
case WM_CHAR:
// Typing in the last digit in a field, skips to the next field.
if (wParam >= TEXT('0') && wParam <= TEXT('9')) { LRESULT lResult;
lResult = CallWindowProc(pipa->Children[wChildID].lpfnWndProc, hWnd, wMsg, wParam, lParam); lResult = SendMessage(hWnd, EM_GETSEL, 0, 0L);
if (lResult == MAKELPARAM(CHARS_PER_FIELD, CHARS_PER_FIELD) && ExitField(pipa, wChildID) && wChildID < NUM_FIELDS-1) { EnterField(&(pipa->Children[wChildID+1]), 0, CHARS_PER_FIELD); } return lResult; }
// spaces and periods fills out the current field and then if possible,
// goes to the next field.
else if (wParam == FILLER || wParam == SPACE ) { LRESULT lResult; lResult = SendMessage(hWnd, EM_GETSEL, 0, 0L); if (lResult != 0L && HIWORD(lResult) == LOWORD(lResult) && ExitField(pipa, wChildID)) { if (wChildID >= NUM_FIELDS-1) MessageBeep((UINT)-1); else { EnterField(&(pipa->Children[wChildID+1]), 0, CHARS_PER_FIELD); } } return 0; }
// Backspaces go to the previous field if at the beginning of the current field.
// Also, if the focus shifts to the previous field, the backspace must be
// processed by that field.
else if (wParam == BACK_SPACE) { if (wChildID > 0 && SendMessage(hWnd, EM_GETSEL, 0, 0L) == 0L) { if (SwitchFields(pipa, wChildID, wChildID-1, CHARS_PER_FIELD, CHARS_PER_FIELD) && SendMessage(pipa->Children[wChildID-1].hWnd, EM_LINELENGTH, 0, 0L) != 0L) { SendMessage(pipa->Children[wChildID-1].hWnd, wMsg, wParam, lParam); } return 0; } }
// Any other printable characters are not allowed.
else if (wParam > SPACE) { MessageBeep((UINT)-1); return 0; } break;
case WM_KEYDOWN: switch (wParam) {
// Arrow keys move between fields when the end of a field is reached.
case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN: if (GetKeyState(VK_CONTROL) < 0) { if ((wParam == VK_LEFT || wParam == VK_UP) && wChildID > 0) { SwitchFields(pipa, wChildID, wChildID-1, 0, CHARS_PER_FIELD); return 0; } else if ((wParam == VK_RIGHT || wParam == VK_DOWN) && wChildID < NUM_FIELDS-1) { SwitchFields(pipa, wChildID, wChildID+1, 0, CHARS_PER_FIELD); return 0; } } else { DWORD dwResult; WORD wStart, wEnd;
dwResult = (DWORD)SendMessage(hWnd, EM_GETSEL, 0, 0L); wStart = LOWORD(dwResult); wEnd = HIWORD(dwResult); if (wStart == wEnd) { if ((wParam == VK_LEFT || wParam == VK_UP) && wStart == 0 && wChildID > 0) { SwitchFields(pipa, wChildID, wChildID-1, CHARS_PER_FIELD, CHARS_PER_FIELD); return 0; } else if ((wParam == VK_RIGHT || wParam == VK_DOWN) && wChildID < NUM_FIELDS-1) { dwResult = (DWORD)SendMessage(hWnd, EM_LINELENGTH, 0, 0L); if (wStart >= dwResult) { SwitchFields(pipa, wChildID, wChildID+1, 0, 0); return 0; } } } } break;
// Home jumps back to the beginning of the first field.
case VK_HOME: if (wChildID > 0) { SwitchFields(pipa, wChildID, 0, 0, 0); return 0; } break;
// End scoots to the end of the last field.
case VK_END: if (wChildID < NUM_FIELDS-1) { SwitchFields(pipa, wChildID, NUM_FIELDS-1, CHARS_PER_FIELD, CHARS_PER_FIELD); return 0; } break;
} // switch (wParam)
break;
case WM_KILLFOCUS: if ( !ExitField( pipa, wChildID )) { return 0; }
} // switch (wMsg)
lresult = CallWindowProc( pipa->Children[wChildID].lpfnWndProc, hWnd, wMsg, wParam, lParam); return lresult; }
/*
Switch the focus from one field to another. call pipa = Pointer to the IPADDR structure. iOld = Field we're leaving. iNew = Field we're entering. hNew = Window of field to goto wStart = First character selected wEnd = Last character selected + 1 returns TRUE on success, FALSE on failure.
Only switches fields if the current field can be validated. */ BOOL SwitchFields(IPADDR *pipa, int iOld, int iNew, WORD wStart, WORD wEnd) { if (!ExitField(pipa, iOld)) return FALSE; EnterField(&(pipa->Children[iNew]), wStart, wEnd); return TRUE; }
/*
Set the focus to a specific field's window. call pField = pointer to field structure for the field. wStart = First character selected wEnd = Last character selected + 1 */ void EnterField(FIELD *pField, WORD wStart, WORD wEnd) { SetFocus(pField->hWnd); SendMessage(pField->hWnd, EM_SETSEL, wStart, wEnd); }
void SetFieldValue(IPADDR *pipa, int iField, int iValue) { TCHAR szBuf[CHARS_PER_FIELD+1]; FIELD* pField = &(pipa->Children[iField]);
StringCchPrintf(szBuf, ARRAYSIZE(szBuf), TEXT("%d"), iValue); SendMessage(pField->hWnd, WM_SETTEXT, 0, (LPARAM) (LPSTR) szBuf); }
/*
Exit a field. call pipa = pointer to IPADDR structure. iField = field number being exited. returns TRUE if the user may exit the field. FALSE if he may not. */ BOOL ExitField(IPADDR *pipa, int iField) { FIELD *pField; int i; NMIPADDRESS nm; int iOldValue;
pField = &(pipa->Children[iField]); i = GetFieldValue(pField); iOldValue = i; nm.iField = iField; nm.iValue = i; SendNotifyEx(pipa->hwndParent, pipa->hwnd, IPN_FIELDCHANGED, &nm.hdr, FALSE); i = nm.iValue; if (i != -1) {
if (i < (int)(UINT)pField->byLow || i > (int)(UINT)pField->byHigh) { if ( i < (int)(UINT) pField->byLow ) { /* too small */ i = (int)(UINT)pField->byLow; } else { /* must be bigger */ i = (int)(UINT)pField->byHigh; } SetFieldValue(pipa, iField, i); // FEATURE: send notify up
return FALSE; } }
if (iOldValue != i) { SetFieldValue(pipa, iField, i); } return TRUE; }
/*
Get the value stored in a field. call pField = pointer to the FIELD structure for the field. returns The value (0..255) or -1 if the field has not value. */ int GetFieldValue(FIELD *pField) { WORD wLength; TCHAR szBuf[CHARS_PER_FIELD+1]; INT i;
*(WORD *)szBuf = (sizeof(szBuf)/sizeof(TCHAR)) - 1; wLength = (WORD)SendMessage(pField->hWnd,EM_GETLINE,0,(LPARAM)(LPSTR)szBuf); if (wLength != 0) { szBuf[wLength] = TEXT('\0'); i = StrToInt(szBuf); return i; } else return -1; }
|