|
|
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.