|
|
1.1 root 1: /*
2: * GIZMO.C
3: * GizmoBar Version 1.00, March 1993
4: *
5: * Allocate, free, find, and enumerate functions for the GIZMO structure
6: * and a generic subclass procedure to handle tabbing between gizmos.
7: *
8: * Copyright (c)1992 Microsoft Corporation, All Rights Reserved.
9: *
10: * Kraig Brockschmidt, Software Design Engineer
11: * Microsoft Systems Developer Relations
12: *
13: * Internet : [email protected]
14: * Compuserve: >INTERNET:[email protected]
15: */
16:
17: #ifdef WIN32
18: #define _INC_OLE
19: #define __RPC_H__
20: #endif
21:
22:
23: #define STRICT
24: #include <windows.h>
25: #include "gizmoint.h"
26:
27:
28: /*
29: * In order to control tabbing in the gizmos, we need to subclass
30: * real pushbuttons, edit controls, listboxes, and comboboxes. So
31: * we keep an array of the four original procs for such controls.
32: */
33: WNDPROC pfnOrg[CSUBGIZMOS]={NULL, NULL, NULL, NULL};
34:
35:
36: char szStatic[]="static";
37: char szEdit[]="edit";
38: char szCombobox[]="combobox";
39: char szListbox[]="listbox";
40: char szButton[]="button";
41:
42:
43: //Here so PAINT.C can get at it.
44: TOOLDISPLAYDATA tdd;
45:
46:
47:
48: /*
49: * GizmoPAllocate
50: *
51: * Purpose:
52: * Allocates and initializes a GIZMO data structure.
53: *
54: * Parameters:
55: * pfSuccess LPINT flag indicating success of failure.
56: * ppFirst PPGIZMO providing the first gizmo in this list.
57: * hWndParent HWND of the parent of this gizmo. Can be NULL for
58: * iType==GIZMOTYPE_BUTTON* or GIZMOTYPE_SEPARATOR.
59: * iType UINT gizmo control type.
60: * iGizmo UINT index of this gizmo in the GizmoBar.
61: * uID UINT identifier to send with WM_COMMAND for this control.
62: * dx, dy UINT width and height of the gizmo.
63: * pszText LPSTR to the text for edits, listboxes, combobox, and text.
64: * dwStyle DWORD style for edits, lists, and combos, and texts.
65: * hBmp HBITMAP for button gizmos, is applicable.
66: * iImage UINT index into hBmp for the button image, if applicable.
67: * uState UINT initial state of the control.
68: *
69: * Return Value:
70: * PGIZMO If NULL returned then GizmoPAllocate could not allocate
71: * memory. If a non-NULL pointer is returned with
72: * *pfSuccess, then call GizmoPFree immediately. If you
73: * get a non-NULL pointer and *pfSuccess==TRUE then the
74: * function succeeded.
75: */
76:
77: PGIZMO GizmoPAllocate(LPINT pfSuccess, PPGIZMO ppFirst, HWND hWndParent
78: , UINT iType, UINT iGizmo, UINT uID, UINT dx, UINT dy, LPSTR pszText
79: , HBITMAP hBmp, UINT iImage, UINT uState)
80: {
81: PGIZMO pGizmo;
82: PGIZMO pCur, pPrev;
83: LPSTR pszClass;
84: HINSTANCE hInst;
85: UINT i;
86: DWORD dwStyle;
87: HWND hWndE;
88:
89: if (NULL==pfSuccess)
90: return NULL;
91:
92: //Make sure we know of this gizmo type.
93: if (GIZMOTYPE_MIN > iType || GIZMOTYPE_MAX < iType)
94: return NULL;
95:
96: *pfSuccess=FALSE;
97:
98: //Allocate the structure
99: pGizmo=(PGIZMO)(char *)LocalAlloc(LPTR, CBGIZMO);
100:
101: if (NULL==pGizmo)
102: return NULL;
103:
104:
105: //Store the necessary information for this gizmo.
106: pGizmo->iType =iType;
107: pGizmo->uID =uID;
108: pGizmo->hBmp =hBmp;
109: pGizmo->iBmp =iImage;
110: pGizmo->uState =uState;
111: pGizmo->fNotify =TRUE;
112:
113:
114: /*
115: * Insert this structure into our gizmo list. Each time we scan
116: * we increment the index counter (starting at zero) comparing it
117: * to the desired index of insertion. We then know exactly where
118: * to insert this new gizmo. Note that we insert the new gizmo in
119: * the list appropriately for the given owner, so enumerations will
120: * come out ordered in the same way for that owner.
121: */
122:
123: i=0;
124: pCur=*ppFirst;
125: pPrev=NULL;
126:
127: while (NULL!=pCur && i++ < iGizmo)
128: {
129: pPrev=pCur;
130: pCur =pCur->pNext;
131: }
132:
133: //Point to our neighbors
134: pGizmo->pPrev=pPrev;
135: pGizmo->pNext=pCur;
136:
137:
138: //Point out neighbors to us.
139: if (NULL==pPrev)
140: *ppFirst=pGizmo;
141: else
142: pPrev->pNext=pGizmo;
143:
144: if (NULL!=pCur)
145: pCur->pPrev=pGizmo;
146:
147:
148: //Our x-coordinate is the x of the previous gizmo plus its width.
149: if (NULL!=pPrev)
150: pGizmo->x=pGizmo->pPrev->x+pGizmo->pPrev->dx;
151: else
152: pGizmo->x=4; //First gizmo is at x=4
153:
154:
155: //If we're a separator or image button, force standards on dx.
156: UIToolConfigureForDisplay(&tdd);
157: pGizmo->cxImage=tdd.cxImage;
158: pGizmo->cyImage=tdd.cyImage;
159:
160:
161: if ((GIZMOTYPE_DRAWN & iType) && NULL==hBmp)
162: dx=tdd.cxButton;
163:
164: if (GIZMOTYPE_SEPARATOR==iType)
165: dx=6;
166:
167: /*
168: * Now create windows for edits, texts, lists, and comboboxes.
169: * First calculate the most often defaults used in the switch.
170: */
171: pGizmo->dx=dx+6;
172: pGizmo->dy=min(dy, tdd.cyButton);
173: pGizmo->y=2;
174: pszClass=NULL;
175:
176: /*
177: * If this is new gizmo is a window, create it. There's proabably
178: * a better way to write this code. Gen, got any ideas?
179: */
180: switch (iType)
181: {
182: case GIZMOTYPE_TEXT:
183: pGizmo->dx=dx;
184: pGizmo->y=(tdd.cyBar-1-pGizmo->dy) >> 1; //Center vertically.
185: pszClass=szStatic;
186: dwStyle=SS_LEFT;
187: break;
188:
189: case GIZMOTYPE_EDIT:
190: pGizmo->y=(tdd.cyBar-1-pGizmo->dy) >> 1; //Center vertically.
191: pszClass=szEdit;
192: dwStyle=ES_LEFT | WS_BORDER | WS_TABSTOP;
193: break;
194:
195: case GIZMOTYPE_LISTBOX:
196: pGizmo->dy=dy;
197: pszClass=szCombobox;
198: dwStyle=CBS_DROPDOWNLIST | WS_TABSTOP;
199: break;
200:
201: case GIZMOTYPE_COMBOBOX:
202: pGizmo->dy=dy;
203: pszClass=szCombobox;
204: dwStyle=CBS_DROPDOWN | WS_TABSTOP;
205: break;
206:
207: case GIZMOTYPE_BUTTONNORMAL:
208: pGizmo->dy=dy;
209: pszClass=szButton;
210: dwStyle=BS_PUSHBUTTON | WS_TABSTOP;
211: break;
212:
213: case GIZMOTYPE_SEPARATOR:
214: pGizmo->dx=dx;
215: pGizmo->y=3;
216: break;
217:
218: case GIZMOTYPE_BUTTONATTRIBUTEIN:
219: case GIZMOTYPE_BUTTONATTRIBUTEEX:
220: case GIZMOTYPE_BUTTONCOMMAND:
221: pGizmo->dx=dx;
222: pGizmo->y=3;
223: break;
224: }
225:
226:
227: //If we matched a classname, create a window.
228: if (GIZMOTYPE_WINDOWS & iType)
229: {
230: if (!IsWindow(hWndParent))
231: return pGizmo;
232: #ifdef WIN32
233: hInst=(HINSTANCE)GetWindowLong(hWndParent, GWL_HINSTANCE);
234: #else
235: hInst=(HINSTANCE)GetWindowWord(hWndParent, GWW_HINSTANCE);
236: #endif
237:
238: pGizmo->hWnd=CreateWindow(pszClass, pszText, dwStyle | WS_CHILD | WS_VISIBLE
239: , pGizmo->x, pGizmo->y, dx, pGizmo->dy, hWndParent
240: , (HMENU)uID, hInst, NULL);
241:
242: if (NULL==pGizmo->hWnd)
243: return pGizmo;
244:
245: /*
246: * Subclass comboboxes, listboxes, edits, and windowed buttons.
247: * We use iType to index the original proc array so we can use
248: * a single subclass procedure for all controls. If you mess
249: * with the gizmo type definitions, this is going to break.
250: */
251:
252: if (GIZMOTYPE_WINDOWS & iType && GIZMOTYPE_TEXT!=iType)
253: {
254: //Give the window its type.
255: BITPOSITION(iType, i);
256: SetProp(pGizmo->hWnd, SZTYPEPROP, (HANDLE)i);
257:
258: if (NULL==pfnOrg[i])
259: pfnOrg[i]=(WNDPROC)GetWindowLong(pGizmo->hWnd, GWL_WNDPROC);
260:
261: SetWindowLong(pGizmo->hWnd, GWL_WNDPROC, (LONG)GenericSubProc);
262:
263: //If we're a combobox, get the edit control and subclass it.
264: if (GIZMOTYPE_COMBOBOX==iType)
265: {
266: hWndE=GetDlgItem(pGizmo->hWnd, ID_COMBOEDIT);
267: SetProp(hWndE, SZTYPEPROP, (HANDLE)-1); //Special flag.
268:
269: if (NULL==pfnOrg[0])
270: pfnOrg[0]=(WNDPROC)GetWindowLong(pGizmo->hWnd, GWL_WNDPROC);
271:
272: SetWindowLong(hWndE, GWL_WNDPROC, (LONG)GenericSubProc);
273: }
274: }
275: }
276:
277:
278: //Finally, move all our neighbors to the right over to accomodate us.
279: GizmosExpand(pGizmo);
280:
281: *pfSuccess=TRUE;
282: return pGizmo;
283: }
284:
285:
286:
287:
288:
289:
290: /*
291: * GizmoPFree
292: *
293: * Purpose:
294: * Reverses all initialization done by GizmoPAllocate, cleaning up
295: * any allocations including the application structure itself.
296: *
297: * Parameters:
298: * ppFirst PPGIZMO providing the first gizmo in this list.
299: * pGizmo PGIZMO to the structure
300: *
301: * Return Value:
302: * PGIZMO NULL if successful, pGizmo if not, meaning we couldn't
303: * free something.
304: */
305:
306: PGIZMO GizmoPFree(PPGIZMO ppFirst, PGIZMO pGizmo)
307: {
308: int i;
309:
310: if (NULL==pGizmo)
311: return NULL;
312:
313: //Move other gizmos to fill in this gap.
314: GizmosCompact(pGizmo);
315:
316: //Unsubclass
317: if (GIZMOTYPE_WINDOWS & pGizmo->iType && GIZMOTYPE_TEXT!=pGizmo->iType)
318: {
319: i=(int)GetProp(pGizmo->hWnd, SZTYPEPROP);
320: RemoveProp(pGizmo->hWnd, SZTYPEPROP);
321:
322: SetWindowLong(pGizmo->hWnd, GWL_WNDPROC, (LONG)pfnOrg[i]);
323: }
324:
325: //If this was a window gizmo, destroy the window.
326: if (NULL!=pGizmo->hWnd && IsWindow(pGizmo->hWnd))
327: DestroyWindow(pGizmo->hWnd);
328:
329: //Unlink ourselves.
330: if (NULL!=pGizmo->pNext)
331: pGizmo->pNext->pPrev=pGizmo->pPrev;
332:
333: if (NULL!=pGizmo->pPrev)
334: pGizmo->pPrev->pNext=pGizmo->pNext;
335: else
336: *ppFirst=pGizmo->pNext;
337:
338: return (PGIZMO)LocalFree((HLOCAL)(UINT)(LONG)pGizmo);
339: }
340:
341:
342:
343:
344:
345:
346: /*
347: * GizmosExpand
348: *
349: * Purpose:
350: * Given a starting gizmo and a width, moves it and all gizmos to its
351: * right to the right by the width to make space for showing or creating
352: * a new gizmo.
353: *
354: * Parameters:
355: * pGizmo PGIZMO specifying the gizmo that was inserted.
356: *
357: * Return Value:
358: * None
359: */
360:
361: void GizmosExpand(PGIZMO pGizmo)
362: {
363: int cx;
364:
365: cx=(int)pGizmo->dx;
366:
367: /*
368: * If we and the next control are buttons, use our width-1 to
369: * expand so we overlap borders with our neighboring button.
370: */
371:
372: if (NULL!=pGizmo->pNext)
373: {
374: if ((GIZMOTYPE_BUTTONS & pGizmo->pNext->iType)
375: && (GIZMOTYPE_BUTTONS & pGizmo->iType))
376: cx-=1;
377: }
378:
379: //Walk the gizmo list moving them right by our width.
380: pGizmo=pGizmo->pNext;
381:
382: while (NULL!=pGizmo)
383: {
384: pGizmo->x+=cx;
385:
386: //hWnd is NULL for buttons and separators.
387: if (NULL!=pGizmo->hWnd)
388: SetWindowPos(pGizmo->hWnd, NULL, pGizmo->x, pGizmo->y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
389:
390: pGizmo=pGizmo->pNext;
391: }
392:
393: return;
394: }
395:
396:
397:
398:
399:
400:
401:
402: /*
403: * GizmosCompact
404: *
405: * Purpose:
406: * Given a gizmo, moves all other gizmos to the right of it to the
407: * left by its width on the GizmoBar. Used when removing or hiding
408: * the gizmo.
409: *
410: * Parameters:
411: * pGizmo PGIZMO that is going away, visibly or physically.
412: *
413: * Return Value:
414: * None
415: */
416:
417: void GizmosCompact(PGIZMO pGizmo)
418: {
419: UINT cx;
420: PGIZMO pCur;
421:
422: //Move all the gizmos beyond us on the GizmoBar back by our width.
423: if (NULL!=pGizmo->pNext)
424: {
425: cx=pGizmo->pNext->x - pGizmo->x;
426: pCur=pGizmo->pNext;
427:
428: while (NULL!=pCur)
429: {
430: pCur->x-=cx;
431:
432: if (NULL!=pCur->hWnd)
433: {
434: SetWindowPos(pCur->hWnd, NULL, pCur->x, pCur->y
435: , 0, 0, SWP_NOZORDER | SWP_NOSIZE);
436: }
437:
438: pCur=pCur->pNext;
439: }
440: }
441:
442: return;
443: }
444:
445:
446:
447:
448:
449:
450: /*
451: * GizmoPFind
452: *
453: * Purpose:
454: * Given a GIZMO identifier, locates and returns a pointer to the structure
455: * for that position.
456: *
457: * Parameters:
458: * ppFirst PPGIZMO providing the first gizmo in this list.
459: * uID UINT identifier to find.
460: *
461: * Return Value:
462: * PGIZMO A pointer to a GIZMO structure allocated through
463: * GizmoPAllocate, NULL if iGizmo is out of range.
464: */
465:
466: PGIZMO GizmoPFind(PPGIZMO ppFirst, UINT uID)
467: {
468: PGIZMO pGizmo;
469:
470: pGizmo=*ppFirst;
471:
472: /*
473: * Yep, linear search, but a better search algorithm won't improve
474: * things appreciably. The better thing to optimize is what the
475: * caller passes as ppFirst.
476: */
477: while (NULL!=pGizmo && uID!=pGizmo->uID)
478: pGizmo=pGizmo->pNext;
479:
480: return pGizmo;
481: }
482:
483:
484:
485:
486:
487:
488: /*
489: * GizmoFEnum
490: *
491: * Purpose:
492: * Enumerates the list of GIZMO structures, passing each one to
493: * an application-defined callback.
494: *
495: * Parameters:
496: * ppFirst PPGIZMO providing the first gizmo in this list.
497: * pfnEnum PFNGIZMOENUM to call for each enumerated structure.
498: * dw DWORD extra data to pass to the enumeration function.
499: *
500: * Return Value:
501: * PGIZMO NULL if the enumeration completed. Otherwise a pointer
502: * to the gizmo that enumeration stopped on.
503: */
504:
505: PGIZMO GizmoPEnum(PPGIZMO ppFirst, PFNGIZMOENUM pfnEnum, DWORD dw)
506: {
507: PGIZMO pGizmo;
508: UINT i=0;
509:
510: pGizmo=*ppFirst;
511:
512: while (NULL!=pGizmo)
513: {
514: if (!(*pfnEnum)(pGizmo, i++, dw))
515: break;
516:
517: pGizmo=pGizmo->pNext;
518: }
519:
520: return pGizmo;
521: }
522:
523:
524:
525:
526: /*
527: * GizmoPStateSet
528: *
529: * Purpose:
530: * State maniuplation functions. Set and Clear also invalidate
531: * this gizmo's rectangle on the given window and forces a repaint.
532: *
533: * Parameters:
534: * hWnd HWND of the window to repaint.
535: * pGizmo PGIZMO affected.
536: * dwNew DWORD new state flags.
537: *
538: * Return Value:
539: * UINT Previous state.
540: */
541:
542: UINT GizmoPStateSet(HWND hWnd, PGIZMO pGizmo, UINT uNew)
543: {
544: UINT uRet;
545: RECT rc;
546:
547: if (GIZMOTYPE_SEPARATOR==pGizmo->iType)
548: return pGizmo->uState;
549:
550: //Preserve the color conversion flags across this state change.
551: uRet=pGizmo->uState;
552: pGizmo->uState=(uNew & 0x00FF) | (uRet & 0xFF00);
553:
554: //Adjust the rectangle by one to avoid repainting borders.
555: SetRect(&rc, pGizmo->x+1, pGizmo->y+1, pGizmo->x+pGizmo->dx-1, pGizmo->y+pGizmo->dy-1);
556: InvalidateRect(hWnd, &rc, FALSE);
557: UpdateWindow(hWnd);
558:
559: return uRet;
560: }
561:
562:
563:
564:
565:
566:
567:
568:
569: /*
570: * GizmoPCheck
571: *
572: * Purpose:
573: * Handles checking a single button in a group of attribute buttons.
574: * If the gizmo belongs to a group of mutually exclusive buttons then
575: * the others surrounding it are unchecked appropriately.
576: *
577: * Parameters:
578: * hWnd HWND of the GizmoBar.
579: * pGizmo PGIZMO of the gizmo affected.
580: * fCheck BOOL TRUE to check the button, FALSE to uncheck.
581: *
582: * Return Value:
583: * BOOL TRUE if the gizmo was previously checked, FALSE
584: * otherwise.
585: */
586:
587: BOOL GizmoPCheck(HWND hWnd, PGIZMO pGizmo, BOOL fCheck)
588: {
589: BOOL fPrevCheck;
590: PGIZMO pCur;
591:
592:
593: //Ignore command buttons.
594: if (GIZMOTYPE_BUTTONCOMMAND==pGizmo->iType)
595: return FALSE;
596:
597: //Get the previous state
598: fPrevCheck=(BOOL)(BUTTONGROUP_DOWN & pGizmo->uState);
599:
600:
601: //Simply set the state for inclusive attribute buttons.
602: if (GIZMOTYPE_BUTTONATTRIBUTEIN==pGizmo->iType)
603: {
604: if (pGizmo->fDisabled)
605: {
606: GizmoPStateSet(hWnd, pGizmo
607: , fCheck ? ATTRIBUTEBUTTON_DOWNDISABLED : ATTRIBUTEBUTTON_DISABLED);
608: }
609: else
610: {
611: GizmoPStateSet(hWnd, pGizmo
612: , fCheck ? ATTRIBUTEBUTTON_DOWN : ATTRIBUTEBUTTON_UP);
613: }
614: }
615:
616:
617: if (GIZMOTYPE_BUTTONATTRIBUTEEX==pGizmo->iType)
618: {
619: //We cannot uncheck an exclusive attribute
620: if (!fCheck)
621: return fPrevCheck;
622:
623: /*
624: * For exclusive buttons we have to do more work. First, if we're
625: * already checked (incliding DOWN and MOUSEDOWN) then we set DOWN
626: * and exit. If we're not already checked, then we look for the
627: * gizmo around us, backwards and forwards, that is checked and
628: * uncheck him.
629: */
630:
631: //Search backwards.
632: pCur=pGizmo->pPrev;
633:
634: while (NULL!=pCur)
635: {
636: //Stop at any non-exclusive attribute.
637: if (GIZMOTYPE_BUTTONATTRIBUTEEX!=pCur->iType)
638: {
639: pCur=NULL;
640: break;
641: }
642:
643: //If it's down, set it up and we've finished.
644: if (BUTTONGROUP_DOWN & pCur->uState)
645: break;
646:
647: pCur=pCur->pPrev;
648: }
649:
650:
651: //If we didn't find a previous one, pCur is NULL, so look ahead.
652: if (NULL==pCur)
653: {
654: pCur=pGizmo->pNext;
655:
656: while (NULL!=pCur)
657: {
658: //Stop at any non-exclusive attribute.
659: if (GIZMOTYPE_BUTTONATTRIBUTEEX!=pCur->iType)
660: {
661: pCur=NULL;
662: break;
663: }
664:
665: //If it's down, set it up and we've finished.
666: if (BUTTONGROUP_DOWN & pCur->uState)
667: break;
668:
669: pCur=pCur->pNext;
670: }
671: }
672:
673: //If pCur is non-NULL, the we found a neighbor, so uncheck him
674: if (NULL!=pCur)
675: {
676: GizmoPStateSet(hWnd, pCur
677: , (pGizmo->fDisabled) ? ATTRIBUTEBUTTON_DISABLED : ATTRIBUTEBUTTON_UP);
678: }
679:
680: //Always set ourselves down
681: GizmoPStateSet(hWnd, pGizmo
682: , (pGizmo->fDisabled) ? ATTRIBUTEBUTTON_DOWNDISABLED : ATTRIBUTEBUTTON_DOWN);
683: }
684:
685: return fPrevCheck;
686: }
687:
688:
689:
690:
691:
692:
693:
694: /*
695: * GenericSubProc
696: *
697: * Purpose:
698: * Subclasses window controls in Gizmos so we can trap the tab key and
699: * tab to the next control. We can have one shared generic subclass
700: * procedure because we save the type index for this control in the
701: * property "iType." This allows us to look up the original procedure
702: * in the pfnOrg array.
703: *
704: * Parameters:
705: * Standard
706: *
707: * Return Value:
708: * Standard
709: */
710:
711: LRESULT FAR PASCAL EXPORT GenericSubProc(HWND hWnd, UINT iMsg
712: , WPARAM wParam, LPARAM lParam)
713: {
714: LONG lRet;
715: RECT rc;
716: RECT rcE;
717: HWND hWndE;
718: HBRUSH hBr;
719: HDC hDC;
720: UINT dx;
721: UINT iType, i;
722:
723: i=(int)GetProp(hWnd, SZTYPEPROP);
724: iType=POSITIONBIT(i);
725:
726: //Special: paint the gap in drop-down comboboxes.
727: if (GIZMOTYPE_COMBOBOX==iType && WM_PAINT==iMsg)
728: {
729: //Do default painting.
730: lRet=(*pfnOrg[i])(hWnd, iMsg, wParam, lParam);
731:
732: hWndE=GetDlgItem(hWnd, ID_COMBOEDIT);
733:
734: GetClientRect(hWnd, &rc);
735: GetClientRect(hWndE, &rcE);
736:
737: //The width of the button is the scroll bar width.
738: dx=GetSystemMetrics(SM_CXVSCROLL);
739:
740: //Calculate the rectangle
741: rc.right -=dx;
742: rc.left =rcE.right;
743: rc.bottom+=1;
744:
745: //Paint the gap
746: hDC=GetDC(hWnd); //Already did BeginPaint and EndPaint
747:
748: hBr=CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
749: FillRect(hDC, &rc, hBr);
750: DeleteObject(hBr);
751:
752: ReleaseDC(hWnd, hDC);
753: return lRet;
754: }
755:
756: //Control tabbing to the next or previous control in the GizmoBar.
757: if (WM_KEYDOWN==iMsg && VK_TAB==wParam)
758: {
759: hWndE=hWnd;
760:
761: if (-1==i)
762: hWndE=GetParent(hWnd);
763:
764: hWndE=GetNextDlgTabItem(GetParent(hWndE), hWnd, (BOOL)(GetKeyState(VK_SHIFT)));
765: SetFocus(hWndE);
766: return 0L;
767: }
768:
769: if (-1==i) i=0;
770:
771: //Eat tab chars in edit controls to prevent beeping.
772: if (0==i && WM_CHAR==iMsg && VK_TAB==wParam)
773: return 0L;
774:
775:
776: //Do this or edit controls bomb big-time.
777: return CallWindowProc(pfnOrg[i], hWnd, iMsg, wParam, lParam);
778: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.