Annotation of mstools/ole20/samples/gizmobar/gizmo.c, revision 1.1.1.1

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:     }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.