source: trunk/src/comctl32/ipaddress.c@ 44

Last change on this file since 44 was 42, checked in by achimha, 26 years ago

New Comctl32 controls - not all are compiling/linking yet!

File size: 12.7 KB
Line 
1/*
2 * IP Address control
3 *
4 * Copyright 1998, 1999 Eric Kohl
5 * Copyright 1998 Alex Priem <alexp@sci.kun.nl>
6 *
7 * NOTES
8
9 *
10 * TODO:
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.
20 * -handle VK_ESCAPE.
21 */
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <stdio.h>
26
27#include "winbase.h"
28#include "commctrl.h"
29#include "ipaddress.h"
30#include "heap.h"
31
32
33#define IPADDRESS_GetInfoPtr(hwnd) ((IPADDRESS_INFO *)GetWindowLongA (hwnd, 0))
34
35
36static BOOL
37IPADDRESS_SendNotify (HWND hwnd, UINT command);
38static BOOL
39IPADDRESS_SendIPAddressNotify (HWND hwnd, UINT field, BYTE newValue);
40
41
42/* property name of tooltip window handle */
43#define IP_SUBCLASS_PROP "CCIP32SubclassInfo"
44
45
46static LRESULT CALLBACK
47IPADDRESS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
48
49
50
51
52static VOID
53IPADDRESS_Refresh (HWND hwnd, HDC hdc)
54{
55 RECT rcClient;
56 HBRUSH hbr;
57 COLORREF clr=GetSysColor (COLOR_3DDKSHADOW);
58 int i,x,fieldsize;
59
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);
64 DeleteObject (hbr);
65
66 x=rcClient.left;
67 fieldsize=(rcClient.right-rcClient.left) /4;
68
69 for (i=0; i<3; i++) { /* Should draw text "." here */
70 x+=fieldsize;
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);
75
76 }
77
78}
79
80
81
82
83
84static LRESULT
85IPADDRESS_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
86{
87 IPADDRESS_INFO *infoPtr;
88 RECT rcClient, edit;
89 int i,fieldsize;
90 LPIP_SUBCLASS_INFO lpipsi;
91
92
93 infoPtr = (IPADDRESS_INFO *)COMCTL32_Alloc (sizeof(IPADDRESS_INFO));
94 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
95
96 GetClientRect (hwnd, &rcClient);
97
98 fieldsize=(rcClient.right-rcClient.left) /4;
99
100 edit.top =rcClient.top+2;
101 edit.bottom=rcClient.bottom-2;
102
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));
107 lpipsi->hwnd = hwnd;
108 lpipsi->uRefCount++;
109 SetPropA ((HWND)hwnd, IP_SUBCLASS_PROP,
110 (HANDLE)lpipsi);
111/* infoPtr->lpipsi= lpipsi; */
112 } else
113// WARN (ipaddress,"IP-create called twice\n");
114
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,
128 (HANDLE)lpipsi);
129 }
130
131 lpipsi->infoPtr= infoPtr;
132
133 return 0;
134}
135
136
137static LRESULT
138IPADDRESS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
139{
140 int i;
141 IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
142 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
143 GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
144
145 for (i=0; i<=3; i++) {
146 SetWindowLongA ((HWND)lpipsi->hwndIP[i], GWL_WNDPROC,
147 (LONG)lpipsi->wpOrigProc[i]);
148 }
149
150 COMCTL32_Free (infoPtr);
151 return 0;
152}
153
154
155static LRESULT
156IPADDRESS_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
157{
158 HDC hdc;
159
160// TRACE (ipaddress,"\n");
161 hdc = GetDC (hwnd);
162 IPADDRESS_Refresh (hwnd, hdc);
163 ReleaseDC (hwnd, hdc);
164
165 IPADDRESS_SendIPAddressNotify (hwnd, 0, 0); /* FIXME: should use -1 */
166 IPADDRESS_SendNotify (hwnd, EN_KILLFOCUS);
167 InvalidateRect (hwnd, NULL, TRUE);
168
169 return 0;
170}
171
172
173static LRESULT
174IPADDRESS_Paint (HWND hwnd, WPARAM wParam)
175{
176 HDC hdc;
177 PAINTSTRUCT ps;
178
179 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
180 IPADDRESS_Refresh (hwnd, hdc);
181 if(!wParam)
182 EndPaint (hwnd, &ps);
183 return 0;
184}
185
186
187static LRESULT
188IPADDRESS_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
189{
190 HDC hdc;
191
192// TRACE (ipaddress,"\n");
193
194 hdc = GetDC (hwnd);
195 IPADDRESS_Refresh (hwnd, hdc);
196 ReleaseDC (hwnd, hdc);
197
198 return 0;
199}
200
201
202static LRESULT
203IPADDRESS_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
204{
205 /* IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd); */
206// TRACE (ipaddress,"\n");
207 return 0;
208}
209
210
211static BOOL
212IPADDRESS_SendNotify (HWND hwnd, UINT command)
213
214{
215// TRACE (ipaddress, "%x\n",command);
216 return (BOOL)SendMessageA (GetParent (hwnd), WM_COMMAND,
217 MAKEWPARAM (GetWindowLongA (hwnd, GWL_ID),command), (LPARAM)hwnd);
218}
219
220
221static BOOL
222IPADDRESS_SendIPAddressNotify (HWND hwnd, UINT field, BYTE newValue)
223{
224 NMIPADDRESS nmip;
225
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;
230
231 nmip.iField=field;
232 nmip.iValue=newValue;
233
234 return (BOOL)SendMessageA (GetParent (hwnd), WM_NOTIFY,
235 (WPARAM)nmip.hdr.idFrom, (LPARAM)&nmip);
236}
237
238
239
240
241static LRESULT
242IPADDRESS_ClearAddress (HWND hwnd, WPARAM wParam, LPARAM lParam)
243{
244 int i;
245 HDC hdc;
246 char buf[1];
247 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
248 GetPropA ((HWND)hwnd,IP_SUBCLASS_PROP);
249
250// TRACE (ipaddress,"\n");
251
252 buf[0]=0;
253 for (i=0; i<=3; i++)
254 SetWindowTextA (lpipsi->hwndIP[i],buf);
255
256 hdc = GetDC (hwnd);
257 IPADDRESS_Refresh (hwnd, hdc);
258 ReleaseDC (hwnd, hdc);
259
260 return 0;
261}
262
263static LRESULT
264IPADDRESS_IsBlank (HWND hwnd, WPARAM wParam, LPARAM lParam)
265{
266 int i;
267 char buf[20];
268 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
269 GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
270
271// TRACE (ipaddress,"\n");
272
273 for (i=0; i<=3; i++) {
274 GetWindowTextA (lpipsi->hwndIP[i],buf,5);
275 if (buf[0])
276 return 0;
277 }
278
279 return 1;
280}
281
282static LRESULT
283IPADDRESS_GetAddress (HWND hwnd, WPARAM wParam, LPARAM lParam)
284{
285 char field[20];
286 int i,valid,fieldvalue;
287 DWORD ip_addr;
288 IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
289 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
290 GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
291
292// TRACE (ipaddress,"\n");
293
294 valid=0;
295 ip_addr=0;
296 for (i=0; i<=3; i++) {
297 GetWindowTextA (lpipsi->hwndIP[i],field,4);
298 ip_addr*=256;
299 if (field[0]) {
300 field[3]=0;
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];
306 ip_addr+=fieldvalue;
307 valid++;
308 }
309 }
310
311 *(LPDWORD) lParam=ip_addr;
312
313 return valid;
314}
315
316
317static LRESULT
318IPADDRESS_SetRange (HWND hwnd, WPARAM wParam, LPARAM lParam)
319{
320 IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
321 INT index;
322
323// TRACE (ipaddress,"\n");
324
325 index=(INT) wParam;
326 if ((index<0) || (index>3)) return 0;
327
328 infoPtr->LowerLimit[index]=lParam & 0xff;
329 infoPtr->UpperLimit[index]=(lParam >>8) & 0xff;
330 return 1;
331}
332
333static LRESULT
334IPADDRESS_SetAddress (HWND hwnd, WPARAM wParam, LPARAM lParam)
335{
336 IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
337 HDC hdc;
338 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
339 GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
340 int i,ip_address,value;
341 char buf[20];
342
343// TRACE (ipaddress,"\n");
344 ip_address=(DWORD) lParam;
345
346 for (i=3; i>=0; i--) {
347 value=ip_address & 0xff;
348 if ((value>=infoPtr->LowerLimit[i]) && (value<=infoPtr->UpperLimit[i]))
349 {
350 sprintf (buf,"%d",value);
351 SetWindowTextA (lpipsi->hwndIP[i],buf);
352 IPADDRESS_SendNotify (hwnd, EN_CHANGE);
353 }
354 ip_address/=256;
355 }
356
357 hdc = GetDC (hwnd); /* & send notifications */
358 IPADDRESS_Refresh (hwnd, hdc);
359 ReleaseDC (hwnd, hdc);
360
361 return TRUE;
362}
363
364
365
366
367static LRESULT
368IPADDRESS_SetFocusToField (HWND hwnd, WPARAM wParam, LPARAM lParam)
369{
370 /* IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd); */
371 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
372 GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
373 INT index;
374
375 index=(INT) wParam;
376// TRACE (ipaddress," %d\n", index);
377 if ((index<0) || (index>3)) return 0;
378
379 SetFocus (lpipsi->hwndIP[index]);
380
381 return 1;
382}
383
384
385static LRESULT
386IPADDRESS_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
387{
388// TRACE (ipaddress, "\n");
389
390 SetFocus (hwnd);
391 IPADDRESS_SendNotify (hwnd, EN_SETFOCUS);
392 IPADDRESS_SetFocusToField (hwnd, 0, 0);
393
394 return TRUE;
395}
396
397
398
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
403*/
404
405
406
407
408static int
409IPADDRESS_GotoNextField (LPIP_SUBCLASS_INFO lpipsi, int currentfield)
410{
411 int newField,fieldvalue;
412 char field[20];
413 IPADDRESS_INFO *infoPtr=lpipsi->infoPtr;
414
415// TRACE (ipaddress,"\n");
416 GetWindowTextA (lpipsi->hwndIP[currentfield],field,4);
417 if (field[0]) {
418 field[3]=0;
419 newField=-1;
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];
425 if (newField>=0) {
426 sprintf (field,"%d",newField);
427 SetWindowTextA (lpipsi->hwndIP[currentfield], field);
428 return 1;
429 }
430 }
431
432 if (currentfield<3)
433 SetFocus (lpipsi->hwndIP[currentfield+1]);
434 return 0;
435}
436
437
438LRESULT CALLBACK
439IPADDRESS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
440{
441 int i,l,index;
442 IPADDRESS_INFO *infoPtr;
443 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
444 GetPropA ((HWND)hwnd,IP_SUBCLASS_PROP);
445
446 infoPtr = lpipsi->infoPtr;
447 index=0; /* FIXME */
448 for (i=0; i<=3; i++)
449 if (lpipsi->hwndIP[i]==hwnd) index=i;
450
451 switch (uMsg) {
452 case WM_CHAR: break;
453 case WM_KEYDOWN: {
454 char c=(char) wParam;
455 if (c==VK_TAB) {
456 HWND pwnd;
457 int shift;
458 shift = GetKeyState(VK_SHIFT) & 0x8000;
459 if (shift)
460 pwnd=GetNextDlgTabItem (GetParent (hwnd), 0, TRUE);
461 else
462 pwnd=GetNextDlgTabItem (GetParent (hwnd), 0, FALSE);
463 if (pwnd) SetFocus (pwnd);
464 break;
465 }
466
467 if ((c==' ') || (c=='.') || (c==VK_RIGHT)) {
468 IPADDRESS_GotoNextField (lpipsi,index);
469 wParam=0;
470 lParam=0;
471 break;
472 }
473 if (c==VK_LEFT) {
474
475 }
476 if (c==VK_RETURN) {
477 }
478 if (((c>='0') && (c<='9')) || (iscntrl(c))) {
479 l=GetWindowTextLengthA (lpipsi->hwndIP[index]);
480 if (l==3)
481 if (IPADDRESS_GotoNextField (lpipsi,index)) {
482 wParam=0;
483 lParam=0;
484 }
485 break;
486 }
487
488 wParam=0;
489 lParam=0;
490 break;
491 }
492 }
493
494 return CallWindowProcA (lpipsi->wpOrigProc[index], hwnd, uMsg, wParam, lParam);
495}
496
497LRESULT WINAPI
498IPADDRESS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
499{
500 switch (uMsg)
501 {
502 case IPM_CLEARADDRESS:
503 return IPADDRESS_ClearAddress (hwnd, wParam, lParam);
504
505 case IPM_SETADDRESS:
506 return IPADDRESS_SetAddress (hwnd, wParam, lParam);
507
508 case IPM_GETADDRESS:
509 return IPADDRESS_GetAddress (hwnd, wParam, lParam);
510
511 case IPM_SETRANGE:
512 return IPADDRESS_SetRange (hwnd, wParam, lParam);
513
514 case IPM_SETFOCUS:
515 return IPADDRESS_SetFocusToField (hwnd, wParam, lParam);
516
517 case IPM_ISBLANK:
518 return IPADDRESS_IsBlank (hwnd, wParam, lParam);
519
520 case WM_CREATE:
521 return IPADDRESS_Create (hwnd, wParam, lParam);
522
523 case WM_DESTROY:
524 return IPADDRESS_Destroy (hwnd, wParam, lParam);
525
526 case WM_GETDLGCODE:
527 return DLGC_WANTARROWS | DLGC_WANTCHARS;
528
529 case WM_KILLFOCUS:
530 return IPADDRESS_KillFocus (hwnd, wParam, lParam);
531
532 case WM_LBUTTONDOWN:
533 return IPADDRESS_LButtonDown (hwnd, wParam, lParam);
534
535 case WM_PAINT:
536 return IPADDRESS_Paint (hwnd, wParam);
537
538 case WM_SETFOCUS:
539 return IPADDRESS_SetFocus (hwnd, wParam, lParam);
540
541 case WM_SIZE:
542 return IPADDRESS_Size (hwnd, wParam, lParam);
543
544 default:
545// if (uMsg >= WM_USER)
546// ERR (ipaddress, "unknown msg %04x wp=%08x lp=%08lx\n",
547// uMsg, wParam, lParam);
548 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
549 }
550 return 0;
551}
552
553
554void
555IPADDRESS_Register (void)
556{
557 WNDCLASSA wndClass;
558
559 if (GlobalFindAtomA (WC_IPADDRESSA)) return;
560
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;
569
570 RegisterClassA (&wndClass);
571}
572
573VOID
574IPADDRESS_Unregister (VOID)
575{
576 if (GlobalFindAtomA (WC_IPADDRESSA))
577 UnregisterClassA (WC_IPADDRESSA, (HINSTANCE)NULL);
578}
579
Note: See TracBrowser for help on using the repository browser.