4 * Copyright 1998, 1999 Eric Kohl
5 * Copyright 1998 Alex Priem <alexp@sci.kun.nl>
11 * -Check ranges when changing field-focus.
12 * -Check all notifications/behavior.
13 * -Optimization: include lpipsi in IPADDRESS_INFO.
14 * -CurrentFocus: field that has focus at moment of processing.
15 * -connect Rect32 rcClient.
16 * -handle right and left arrows correctly. Boring.
17 * -split GotoNextField in CheckField and GotoNextField.
18 * -check ipaddress.cpp for missing features.
19 * -refresh: draw '.' instead of setpixel.
28 #include "ipaddress.h"
33 #define IPADDRESS_GetInfoPtr(hwnd) ((IPADDRESS_INFO *)GetWindowLongA (hwnd, 0))
37 IPADDRESS_SendNotify (HWND hwnd
, UINT command
);
39 IPADDRESS_SendIPAddressNotify (HWND hwnd
, UINT field
, BYTE newValue
);
42 /* property name of tooltip window handle */
43 #define IP_SUBCLASS_PROP "CCIP32SubclassInfo"
46 static LRESULT CALLBACK
47 IPADDRESS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
53 IPADDRESS_Refresh (HWND hwnd
, HDC hdc
)
57 COLORREF clr
=GetSysColor (COLOR_3DDKSHADOW
);
60 GetClientRect (hwnd
, &rcClient
);
61 hbr
= CreateSolidBrush (RGB(255,255,255));
62 DrawEdge (hdc
, &rcClient
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
63 FillRect (hdc
, &rcClient
, hbr
);
67 fieldsize
=(rcClient
.right
-rcClient
.left
) /4;
69 for (i
=0; i
<3; i
++) { /* Should draw text "." here */
71 SetPixel (hdc
, x
, 13, clr
);
72 SetPixel (hdc
, x
, 14, clr
);
73 SetPixel (hdc
, x
+1, 13, clr
);
74 SetPixel (hdc
, x
+1, 14, clr
);
85 IPADDRESS_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
87 IPADDRESS_INFO
*infoPtr
;
90 LPIP_SUBCLASS_INFO lpipsi
;
93 infoPtr
= (IPADDRESS_INFO
*)COMCTL32_Alloc (sizeof(IPADDRESS_INFO
));
94 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
96 GetClientRect (hwnd
, &rcClient
);
98 fieldsize
=(rcClient
.right
-rcClient
.left
) /4;
100 edit
.top
=rcClient
.top
+2;
101 edit
.bottom
=rcClient
.bottom
-2;
103 lpipsi
=(LPIP_SUBCLASS_INFO
)
104 GetPropA ((HWND
)hwnd
, IP_SUBCLASS_PROP
);
105 if (lpipsi
== NULL
) {
106 lpipsi
= (LPIP_SUBCLASS_INFO
) COMCTL32_Alloc (sizeof(IP_SUBCLASS_INFO
));
109 SetPropA ((HWND
)hwnd
, IP_SUBCLASS_PROP
,
111 /* infoPtr->lpipsi= lpipsi; */
113 WARN (ipaddress
,"IP-create called twice\n");
115 for (i
=0; i
<=3; i
++) {
116 infoPtr
->LowerLimit
[i
]=0;
117 infoPtr
->UpperLimit
[i
]=255;
118 edit
.left
=rcClient
.left
+i
*fieldsize
+3;
119 edit
.right
=rcClient
.left
+(i
+1)*fieldsize
-2;
120 lpipsi
->hwndIP
[i
]= CreateWindowA ("edit", NULL
,
121 WS_CHILD
| WS_VISIBLE
| ES_LEFT
,
122 edit
.left
, edit
.top
, edit
.right
-edit
.left
, edit
.bottom
-edit
.top
,
123 hwnd
, (HMENU
) 1, GetWindowLongA (hwnd
, GWL_HINSTANCE
), NULL
);
124 lpipsi
->wpOrigProc
[i
]= (WNDPROC
)
125 SetWindowLongA (lpipsi
->hwndIP
[i
],GWL_WNDPROC
, (LONG
)
126 IPADDRESS_SubclassProc
);
127 SetPropA ((HWND
)lpipsi
->hwndIP
[i
], IP_SUBCLASS_PROP
,
131 lpipsi
->infoPtr
= infoPtr
;
138 IPADDRESS_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
141 IPADDRESS_INFO
*infoPtr
= IPADDRESS_GetInfoPtr (hwnd
);
142 LPIP_SUBCLASS_INFO lpipsi
=(LPIP_SUBCLASS_INFO
)
143 GetPropA ((HWND
)hwnd
, IP_SUBCLASS_PROP
);
145 for (i
=0; i
<=3; i
++) {
146 SetWindowLongA ((HWND
)lpipsi
->hwndIP
[i
], GWL_WNDPROC
,
147 (LONG
)lpipsi
->wpOrigProc
[i
]);
150 COMCTL32_Free (infoPtr
);
156 IPADDRESS_KillFocus (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
160 TRACE (ipaddress
,"\n");
162 IPADDRESS_Refresh (hwnd
, hdc
);
163 ReleaseDC (hwnd
, hdc
);
165 IPADDRESS_SendIPAddressNotify (hwnd
, 0, 0); /* FIXME: should use -1 */
166 IPADDRESS_SendNotify (hwnd
, EN_KILLFOCUS
);
167 InvalidateRect (hwnd
, NULL
, TRUE
);
174 IPADDRESS_Paint (HWND hwnd
, WPARAM wParam
)
179 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
180 IPADDRESS_Refresh (hwnd
, hdc
);
182 EndPaint (hwnd
, &ps
);
188 IPADDRESS_SetFocus (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
192 TRACE (ipaddress
,"\n");
195 IPADDRESS_Refresh (hwnd
, hdc
);
196 ReleaseDC (hwnd
, hdc
);
203 IPADDRESS_Size (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
205 /* IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd); */
206 TRACE (ipaddress
,"\n");
212 IPADDRESS_SendNotify (HWND hwnd
, UINT command
)
215 TRACE (ipaddress
, "%x\n",command
);
216 return (BOOL
)SendMessageA (GetParent (hwnd
), WM_COMMAND
,
217 MAKEWPARAM (GetWindowLongA (hwnd
, GWL_ID
),command
), (LPARAM
)hwnd
);
222 IPADDRESS_SendIPAddressNotify (HWND hwnd
, UINT field
, BYTE newValue
)
226 TRACE (ipaddress
, "%x %x\n",field
,newValue
);
227 nmip
.hdr
.hwndFrom
= hwnd
;
228 nmip
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
229 nmip
.hdr
.code
= IPN_FIELDCHANGED
;
232 nmip
.iValue
=newValue
;
234 return (BOOL
)SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
235 (WPARAM
)nmip
.hdr
.idFrom
, (LPARAM
)&nmip
);
242 IPADDRESS_ClearAddress (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
247 LPIP_SUBCLASS_INFO lpipsi
=(LPIP_SUBCLASS_INFO
)
248 GetPropA ((HWND
)hwnd
,IP_SUBCLASS_PROP
);
250 TRACE (ipaddress
,"\n");
254 SetWindowTextA (lpipsi
->hwndIP
[i
],buf
);
257 IPADDRESS_Refresh (hwnd
, hdc
);
258 ReleaseDC (hwnd
, hdc
);
264 IPADDRESS_IsBlank (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
268 LPIP_SUBCLASS_INFO lpipsi
=(LPIP_SUBCLASS_INFO
)
269 GetPropA ((HWND
)hwnd
, IP_SUBCLASS_PROP
);
271 TRACE (ipaddress
,"\n");
273 for (i
=0; i
<=3; i
++) {
274 GetWindowTextA (lpipsi
->hwndIP
[i
],buf
,5);
283 IPADDRESS_GetAddress (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
286 int i
,valid
,fieldvalue
;
288 IPADDRESS_INFO
*infoPtr
= IPADDRESS_GetInfoPtr (hwnd
);
289 LPIP_SUBCLASS_INFO lpipsi
=(LPIP_SUBCLASS_INFO
)
290 GetPropA ((HWND
)hwnd
, IP_SUBCLASS_PROP
);
292 TRACE (ipaddress
,"\n");
296 for (i
=0; i
<=3; i
++) {
297 GetWindowTextA (lpipsi
->hwndIP
[i
],field
,4);
301 fieldvalue
=atoi(field
);
302 if (fieldvalue
<infoPtr
->LowerLimit
[i
])
303 fieldvalue
=infoPtr
->LowerLimit
[i
];
304 if (fieldvalue
>infoPtr
->UpperLimit
[i
])
305 fieldvalue
=infoPtr
->UpperLimit
[i
];
311 *(LPDWORD
) lParam
=ip_addr
;
318 IPADDRESS_SetRange (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
320 IPADDRESS_INFO
*infoPtr
= IPADDRESS_GetInfoPtr (hwnd
);
323 TRACE (ipaddress
,"\n");
326 if ((index
<0) || (index
>3)) return 0;
328 infoPtr
->LowerLimit
[index
]=lParam
& 0xff;
329 infoPtr
->UpperLimit
[index
]=(lParam
>>8) & 0xff;
334 IPADDRESS_SetAddress (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
336 IPADDRESS_INFO
*infoPtr
= IPADDRESS_GetInfoPtr (hwnd
);
338 LPIP_SUBCLASS_INFO lpipsi
=(LPIP_SUBCLASS_INFO
)
339 GetPropA ((HWND
)hwnd
, IP_SUBCLASS_PROP
);
340 int i
,ip_address
,value
;
343 TRACE (ipaddress
,"\n");
344 ip_address
=(DWORD
) lParam
;
346 for (i
=3; i
>=0; i
--) {
347 value
=ip_address
& 0xff;
348 if ((value
>=infoPtr
->LowerLimit
[i
]) && (value
<=infoPtr
->UpperLimit
[i
]))
350 sprintf (buf
,"%d",value
);
351 SetWindowTextA (lpipsi
->hwndIP
[i
],buf
);
352 IPADDRESS_SendNotify (hwnd
, EN_CHANGE
);
357 hdc
= GetDC (hwnd
); /* & send notifications */
358 IPADDRESS_Refresh (hwnd
, hdc
);
359 ReleaseDC (hwnd
, hdc
);
368 IPADDRESS_SetFocusToField (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
370 /* IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd); */
371 LPIP_SUBCLASS_INFO lpipsi
=(LPIP_SUBCLASS_INFO
)
372 GetPropA ((HWND
)hwnd
, IP_SUBCLASS_PROP
);
376 TRACE (ipaddress
," %d\n", index
);
377 if ((index
<0) || (index
>3)) return 0;
379 SetFocus (lpipsi
->hwndIP
[index
]);
386 IPADDRESS_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
388 TRACE (ipaddress
, "\n");
391 IPADDRESS_SendNotify (hwnd
, EN_SETFOCUS
);
392 IPADDRESS_SetFocusToField (hwnd
, 0, 0);
399 /* tab/shift-tab: IPN_FIELDCHANGED, lose focus.
400 dot, space,right arrow: set focus to next child edit.
401 numerics (0..9), control characters: forward to default edit control
402 other characters: dropped
409 IPADDRESS_GotoNextField (LPIP_SUBCLASS_INFO lpipsi
, int currentfield
)
411 int newField
,fieldvalue
;
413 IPADDRESS_INFO
*infoPtr
=lpipsi
->infoPtr
;
415 TRACE (ipaddress
,"\n");
416 GetWindowTextA (lpipsi
->hwndIP
[currentfield
],field
,4);
420 fieldvalue
=atoi(field
);
421 if (fieldvalue
<infoPtr
->LowerLimit
[currentfield
])
422 newField
=infoPtr
->LowerLimit
[currentfield
];
423 if (fieldvalue
>infoPtr
->UpperLimit
[currentfield
])
424 newField
=infoPtr
->UpperLimit
[currentfield
];
426 sprintf (field
,"%d",newField
);
427 SetWindowTextA (lpipsi
->hwndIP
[currentfield
], field
);
433 SetFocus (lpipsi
->hwndIP
[currentfield
+1]);
439 IPADDRESS_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
442 IPADDRESS_INFO
*infoPtr
;
443 LPIP_SUBCLASS_INFO lpipsi
=(LPIP_SUBCLASS_INFO
)
444 GetPropA ((HWND
)hwnd
,IP_SUBCLASS_PROP
);
446 infoPtr
= lpipsi
->infoPtr
;
449 if (lpipsi
->hwndIP
[i
]==hwnd
) index
=i
;
454 char c
=(char) wParam
;
458 shift
= GetKeyState(VK_SHIFT
) & 0x8000;
460 pwnd
=GetNextDlgTabItem (GetParent (hwnd
), 0, TRUE
);
462 pwnd
=GetNextDlgTabItem (GetParent (hwnd
), 0, FALSE
);
463 if (pwnd
) SetFocus (pwnd
);
467 if ((c
==' ') || (c
=='.') || (c
==VK_RIGHT
)) {
468 IPADDRESS_GotoNextField (lpipsi
,index
);
478 if (((c
>='0') && (c
<='9')) || (iscntrl(c
))) {
479 l
=GetWindowTextLengthA (lpipsi
->hwndIP
[index
]);
481 if (IPADDRESS_GotoNextField (lpipsi
,index
)) {
494 return CallWindowProcA (lpipsi
->wpOrigProc
[index
], hwnd
, uMsg
, wParam
, lParam
);
498 IPADDRESS_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
502 case IPM_CLEARADDRESS
:
503 return IPADDRESS_ClearAddress (hwnd
, wParam
, lParam
);
506 return IPADDRESS_SetAddress (hwnd
, wParam
, lParam
);
509 return IPADDRESS_GetAddress (hwnd
, wParam
, lParam
);
512 return IPADDRESS_SetRange (hwnd
, wParam
, lParam
);
515 return IPADDRESS_SetFocusToField (hwnd
, wParam
, lParam
);
518 return IPADDRESS_IsBlank (hwnd
, wParam
, lParam
);
521 return IPADDRESS_Create (hwnd
, wParam
, lParam
);
524 return IPADDRESS_Destroy (hwnd
, wParam
, lParam
);
527 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
530 return IPADDRESS_KillFocus (hwnd
, wParam
, lParam
);
533 return IPADDRESS_LButtonDown (hwnd
, wParam
, lParam
);
536 return IPADDRESS_Paint (hwnd
, wParam
);
539 return IPADDRESS_SetFocus (hwnd
, wParam
, lParam
);
542 return IPADDRESS_Size (hwnd
, wParam
, lParam
);
546 ERR (ipaddress
, "unknown msg %04x wp=%08x lp=%08lx\n",
547 uMsg
, wParam
, lParam
);
548 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
555 IPADDRESS_Register (void)
559 if (GlobalFindAtomA (WC_IPADDRESSA
)) return;
561 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
562 wndClass
.style
= CS_GLOBALCLASS
;
563 wndClass
.lpfnWndProc
= (WNDPROC
)IPADDRESS_WindowProc
;
564 wndClass
.cbClsExtra
= 0;
565 wndClass
.cbWndExtra
= sizeof(IPADDRESS_INFO
*);
566 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
567 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_3DFACE
+ 1);
568 wndClass
.lpszClassName
= WC_IPADDRESSA
;
570 RegisterClassA (&wndClass
);
574 IPADDRESS_Unregister (VOID
)
576 if (GlobalFindAtomA (WC_IPADDRESSA
))
577 UnregisterClassA (WC_IPADDRESSA
, (HINSTANCE
)NULL
);