home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / inole / gizmobar.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  20KB  |  729 lines

  1. /*
  2.  * GIZMOBAR.C
  3.  *
  4.  * Contains the main window procedure of the GizmoBar control
  5.  * that handles mouse logic and Windows messages.
  6.  *
  7.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  8.  *
  9.  * Kraig Brockschmidt, Microsoft
  10.  * Internet  :  kraigb@microsoft.com
  11.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  12.  */
  13.  
  14.  
  15. #include "inoledll.h"
  16.  
  17.  
  18. //In GIZMO.C
  19. extern TOOLDISPLAYDATA g_tdd;
  20.  
  21.  
  22. /*
  23.  * GizmoBarPAllocate
  24.  *
  25.  * Purpose:
  26.  *  Allocates and initializes the control's primary data structure
  27.  *  for each window that gets created.
  28.  *
  29.  * Parameters:
  30.  *  pfSuccess       int * indicating success of the function.
  31.  *  hWnd            HWND that is tied to this structure.
  32.  *  hInst           HINSTANCE of the DLL.
  33.  *  hWndAssociate   HWND to which we send messages.
  34.  *  dwStyle         DWORD initial style.
  35.  *  uState          UINT initial state.
  36.  *  uID             UINT identifier for this window.
  37.  *
  38.  * Return Value:
  39.  *  PGIZMOBAR       If NULL returned then GizmoBarPAllocate could not
  40.  *                  allocate memory.  If a non-NULL pointer is
  41.  *                  returned with *pfSuccess, then call GizmoBarPFree
  42.  *                  immediately.  If you get a non-NULL pointer and
  43.  *                  *pfSuccess==TRUE then the function succeeded.
  44.  */
  45.  
  46. PGIZMOBAR GizmoBarPAllocate(int *pfSuccess, HWND hWnd
  47.     , HINSTANCE hInst, HWND hWndAssociate, DWORD dwStyle
  48.     , UINT uState , UINT uID)
  49.     {
  50.     PGIZMOBAR     pGB;
  51.  
  52.     if (NULL==pfSuccess)
  53.         return NULL;
  54.  
  55.     *pfSuccess=FALSE;
  56.  
  57.     //Allocate the structure
  58.     pGB=(PGIZMOBAR)(void *)LocalAlloc(LPTR, CBGIZMOBAR);
  59.  
  60.     if (NULL==pGB)
  61.         return NULL;
  62.  
  63.     //Initialize LibMain parameter holders.
  64.     pGB->hWnd         =hWnd;
  65.     pGB->hInst        =hInst;
  66.     pGB->hWndAssociate=hWndAssociate;
  67.     pGB->dwStyle      =dwStyle;
  68.     pGB->uState       =uState;
  69.     pGB->uID          =uID;
  70.     pGB->fEnabled     =TRUE;
  71.  
  72.     pGB->crFace=GetSysColor(COLOR_BTNFACE);
  73.     pGB->hBrFace=CreateSolidBrush(pGB->crFace);
  74.  
  75.     if (NULL==pGB->hBrFace)
  76.         return pGB;
  77.  
  78.     pGB->hFont=GetStockObject(SYSTEM_FONT);
  79.  
  80.     *pfSuccess=TRUE;
  81.     return pGB;
  82.     }
  83.  
  84.  
  85.  
  86.  
  87. /*
  88.  * GizmoBarPFree
  89.  *
  90.  * Purpose:
  91.  *  Reverses all initialization done by GizmoBarPAllocate, cleaning
  92.  *  up any allocations including the application structure itself.
  93.  *
  94.  * Parameters:
  95.  *  pGB             PGIZMOBAR to the control's structure
  96.  *
  97.  * Return Value:
  98.  *  PGIZMOBAR       NULL if successful, pGB if not, meaning we
  99.  *                  couldn't free some allocation.
  100.  */
  101.  
  102. PGIZMOBAR GizmoBarPFree(PGIZMOBAR pGB)
  103.     {
  104.     if (NULL==pGB)
  105.         return NULL;
  106.  
  107.     /*
  108.      * Free all the gizmos we own.  When we call GizmoPFree we always
  109.      * free the first one in the list which updates pGB->pGizmos for
  110.      * us, so we just have to keep going until pGizmos is NULL,
  111.      * meaning we're at the end of the list.
  112.      */
  113.     while (NULL!=pGB->pGizmos)
  114.         GizmoPFree(&pGB->pGizmos, pGB->pGizmos);
  115.  
  116.     if (NULL!=pGB->hBrFace)
  117.         DeleteObject(pGB->hBrFace);
  118.  
  119.     /*
  120.      * Notice that since we never create a font, we aren't
  121.      * responsible for our hFont member.
  122.      */
  123.  
  124.     return (PGIZMOBAR)(void *)LocalFree((HLOCAL)(UINT)(LONG)pGB);
  125.     }
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134. /*
  135.  * GizmoBarWndProc
  136.  *
  137.  * Purpose:
  138.  *  Window Procedure for the GizmoBar custom control.  Handles all
  139.  *  messages like WM_PAINT just as a normal application window would.
  140.  *  Any message not processed here should go to DefWindowProc.
  141.  *
  142.  * Parameters:
  143.  *  Standard
  144.  *
  145.  * Return Value:
  146.  *  Standard
  147.  */
  148.  
  149. LRESULT WINAPI GizmoBarWndProc(HWND hWnd, UINT iMsg
  150.     , WPARAM wParam, LPARAM lParam)
  151.     {
  152.     BOOL            fSuccess;
  153.     BOOL            fTemp;
  154.     LPCREATESTRUCT  pCreate;
  155.     PGIZMOBAR       pGB;
  156.     PGIZMO          pGizmo;
  157.     RECT            rc;
  158.     POINT           pt;
  159.     short           x, y;
  160.     COLORREF        cr;
  161.  
  162.     COMMANDPARAMS(wID, wCode, hWndMsg);
  163.  
  164.     pGB=(PGIZMOBAR)GetWindowLong(hWnd, GBWL_STRUCTURE);
  165.  
  166.     //Pass control messages onto another function for processing.
  167.     if (iMsg >= WM_USER)
  168.         return GBMessageHandler(hWnd, iMsg, wParam, lParam, pGB);
  169.  
  170.     switch (iMsg)
  171.         {
  172.         case WM_NCCREATE:
  173.             pCreate=(LPCREATESTRUCT)lParam;
  174.  
  175.             pGB=GizmoBarPAllocate(&fSuccess, hWnd
  176.                 , pCreate->hInstance, pCreate->hwndParent
  177.                 , pCreate->style, 0, (UINT)pCreate->hMenu);
  178.  
  179.             if (!fSuccess)
  180.                 {
  181.                 GizmoBarPFree(pGB);
  182.                 return -1L;
  183.                 }
  184.             else
  185.                 SetWindowLong(hWnd, GBWL_STRUCTURE, (LONG)pGB);
  186.  
  187.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  188.  
  189.  
  190.         case WM_DESTROY:
  191.             /*
  192.              * We want to clean up before DestroyWindow nukes all the
  193.              * children, so WM_DESTROY is a better to do it than
  194.              * WM_NCDESTROY.
  195.              */
  196.             GizmoBarPFree(pGB);
  197.             break;
  198.  
  199.  
  200.         case WM_ERASEBKGND:
  201.             /*
  202.              * Eat this message to avoid erasing portions that
  203.              * we are going to repaint in WM_PAINT.  Part of a
  204.              * change-state-and-repaint strategy is to rely on
  205.              * WM_PAINT to do anything visual, which includes
  206.              * erasing invalid portions.  Letting WM_ERASEBKGND
  207.              * erase the background is redundant.
  208.              */
  209.             return TRUE;
  210.  
  211.        #ifdef WIN32
  212.         case WM_CTLCOLORBTN:
  213.         case WM_CTLCOLORSTATIC:
  214.             fTemp=TRUE;
  215.        #else
  216.         case WM_CTLCOLOR:
  217.             //Change the color of static text on the GizmoBar.
  218.             fTemp=(HIWORD(lParam)==CTLCOLOR_STATIC
  219.                 || HIWORD(lParam)==CTLCOLOR_BTN);
  220.        #endif
  221.  
  222.             if (fTemp)
  223.                 {
  224.                 cr=GetSysColor(COLOR_BTNFACE);
  225.                 SetTextColor((HDC)wParam
  226.                     , GetSysColor(COLOR_BTNTEXT));
  227.                 SetBkColor((HDC)wParam, cr);
  228.  
  229.                 /*
  230.                  * If the system colors have changed, then crFace
  231.                  * will not be equal to COLOR_BTNFACE, so we
  232.                  * reinitialize the background brush.  This scheme
  233.                  * handles system color changes appropriately
  234.                  * without processing WM_WININICHANGE and without
  235.                  * blindly creating a new brush on every WM_CTLCOLOR
  236.                  * message.
  237.                  */
  238.                 if (cr!=pGB->crFace)
  239.                     {
  240.                     pGB->crFace=cr;
  241.  
  242.                     if (NULL!=pGB->hBrFace)
  243.                         DeleteObject(pGB->hBrFace);
  244.  
  245.                     pGB->hBrFace=CreateSolidBrush(pGB->crFace);
  246.                     }
  247.  
  248.                 return (LONG)(UINT)pGB->hBrFace;
  249.                 }
  250.  
  251.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  252.  
  253.  
  254.         case WM_PAINT:
  255.             GizmoBarPaint(hWnd, pGB);
  256.             break;
  257.  
  258.  
  259.         case WM_SETFONT:
  260.             /*
  261.              * wParam has the new font that we now send to all other
  262.              * windows controls in us.  We control repaints here to
  263.              * prevent a lot of repainting for each control.
  264.              */
  265.             DefWindowProc(hWnd, WM_SETREDRAW, FALSE, 0L);
  266.  
  267.             if ((WPARAM)NULL!=wParam)
  268.                 {
  269.                 pGB->hFont=(HFONT)wParam;
  270.                 GizmoPEnum(&pGB->pGizmos, FEnumChangeFont
  271.                     , (DWORD)(LPTSTR)pGB);
  272.  
  273.                 DefWindowProc(hWnd, WM_SETREDRAW, TRUE, 0L);
  274.                 InvalidateRect(hWnd, NULL, FALSE);
  275.                 UpdateWindow(hWnd);
  276.                 }
  277.  
  278.             break;
  279.  
  280.  
  281.         case WM_GETFONT:
  282.             return (LRESULT)(UINT)pGB->hFont;
  283.  
  284.  
  285.         case WM_ENABLE:
  286.             /*
  287.              * wParam has the new enable flag that we use to enable
  288.              * or disable ALL controls in us at one time.  We also
  289.              * turn the redraw off to prevent a lot of flicker.
  290.              */
  291.             DefWindowProc(hWnd, WM_SETREDRAW, FALSE, 0L);
  292.  
  293.             pGB->fEnabled=(BOOL)wParam;
  294.             GizmoPEnum(&pGB->pGizmos, FEnumEnable
  295.                 , (DWORD)(LPTSTR)pGB);
  296.  
  297.             DefWindowProc(hWnd, WM_SETREDRAW, TRUE, 0L);
  298.             InvalidateRect(hWnd, NULL, FALSE);
  299.             UpdateWindow(hWnd);
  300.             break;
  301.  
  302.  
  303.         case WM_CANCELMODE:
  304.             pGizmo=pGB->pGizmoTrack;
  305.  
  306.             pGB->fTracking=FALSE;
  307.             pGB->fMouseOut=FALSE;
  308.  
  309.             if (NULL!=pGizmo)
  310.                 GizmoPStateSet(hWnd, pGizmo, COMMANDBUTTON_UP);
  311.  
  312.             ReleaseCapture();
  313.             break;
  314.  
  315.  
  316.         case WM_LBUTTONDBLCLK:
  317.         case WM_LBUTTONDOWN:
  318.             //Get the mouse coordinates.
  319.             x=LOWORD(lParam);
  320.             y=HIWORD(lParam);
  321.  
  322.  
  323.             /*
  324.              * See if we hit a command or attribute gizmo or not.
  325.              * Anything else that is a control will get the message
  326.              * instead of us anyway, so we don't have to check.
  327.              * FEnumHitTest also validates drawn gizmos, enabled, and
  328.              * visible, so we don't.
  329.              */
  330.             pGizmo=GizmoPEnum(&pGB->pGizmos, FEnumHitTest, lParam);
  331.  
  332.             if (NULL==pGizmo)
  333.                 break;          //Didn't hit one matching our needs.
  334.  
  335.             /*
  336.              * Inform the associate that a command was hit like a
  337.              * menu item.
  338.              */
  339.             if (NULL!=pGB->hWndAssociate)
  340.                 {
  341.                 if (pGizmo->fNotify)
  342.                     {
  343.                     SendMenuSelect(pGB->hWndAssociate, pGizmo->uID
  344.                         , 0, 0);
  345.                     }
  346.                 }
  347.  
  348.             /*
  349.              * We hit a button.  If it's a command or attribute,
  350.              * then change the state and start tracking.
  351.              */
  352.             pGB->fTracking=TRUE;
  353.             pGB->pGizmoTrack=pGizmo;
  354.             pGB->fMouseOut=FALSE;
  355.             SetCapture(hWnd);
  356.  
  357.             pGizmo->uStateOrg=pGizmo->uState;
  358.             GizmoPStateSet(hWnd, pGizmo, ATTRIBUTEBUTTON_MOUSEDOWN);
  359.  
  360.             break;
  361.  
  362.  
  363.         case WM_MOUSEMOVE:
  364.             POINTFROMLPARAM(pt, lParam);
  365.  
  366.             if (!pGB->fTracking)
  367.                 break;
  368.  
  369.             pGizmo=pGB->pGizmoTrack;
  370.             SetRect(&rc, pGizmo->x, pGizmo->y, pGizmo->x+pGizmo->dx
  371.                 , pGizmo->y+pGizmo->dy);
  372.  
  373.             fTemp=pGB->fMouseOut;
  374.             pGB->fMouseOut=!PtInRect(&rc, pt);
  375.  
  376.             //If the mouse went out, change state to the original.
  377.             if (!fTemp && pGB->fMouseOut)
  378.                 {
  379.                 GizmoPStateSet(hWnd, pGizmo, pGizmo->uStateOrg);
  380.  
  381.                 if (NULL!=pGB->hWndAssociate)
  382.                     {
  383.                     //Notify that we left the button
  384.                     if (pGizmo->fNotify)
  385.                         SendMenuSelect(pGB->hWndAssociate, 0, ~0, 0);
  386.                     }
  387.                 }
  388.  
  389.             if (fTemp && !pGB->fMouseOut)
  390.                 {
  391.                 GizmoPStateSet(hWnd, pGizmo
  392.                     , ATTRIBUTEBUTTON_MOUSEDOWN);
  393.  
  394.                 if (NULL!=pGB->hWndAssociate)
  395.                     {
  396.                     //Notify that we pressed down again
  397.                     if (pGizmo->fNotify)
  398.                         {
  399.                         SendMenuSelect(pGB->hWndAssociate
  400.                             , pGizmo->uID , 0, 0);
  401.                         }
  402.                     }
  403.                 }
  404.  
  405.             break;
  406.  
  407.  
  408.         case WM_LBUTTONUP:
  409.             if (!pGB->fTracking)
  410.                 break;
  411.  
  412.             pGB->fTracking=FALSE;
  413.             pGizmo=pGB->pGizmoTrack;
  414.             ReleaseCapture();
  415.  
  416.  
  417.             /*
  418.              * Repaint if we were actually below the mouse when this
  419.              * occurred.  For command buttons, pop the button up.
  420.              * For attributes, either toggle the state (inclusive
  421.              * buttons) or check the selected one (exclusive buttons)
  422.              */
  423.  
  424.             if (!pGB->fMouseOut)
  425.                 {
  426.                 //Command buttons always come up.
  427.                 if (GIZMOTYPE_BUTTONCOMMAND==pGizmo->iType)
  428.                     GizmoPStateSet(hWnd, pGizmo, COMMANDBUTTON_UP);
  429.  
  430.                 //Attribute inclusive buttons toggle
  431.                 if (GIZMOTYPE_BUTTONATTRIBUTEIN==pGizmo->iType)
  432.                     {
  433.                     GizmoPCheck(hWnd, pGizmo, !(BUTTONGROUP_DOWN
  434.                         & pGizmo->uStateOrg));
  435.                     }
  436.  
  437.                 //Attribure exclusive buttons are always checked.
  438.                 if (GIZMOTYPE_BUTTONATTRIBUTEEX==pGizmo->iType)
  439.                     GizmoPCheck(hWnd, pGizmo, TRUE);
  440.  
  441.                 //Only send messages if notify is ON.
  442.                 if (NULL!=pGB->hWndAssociate && pGizmo->fNotify)
  443.                     {
  444.                     SendMenuSelect(pGB->hWndAssociate, 0, ~0, 0);
  445.                     SendCommand(pGB->hWndAssociate, pGizmo->uID
  446.                         , BN_CLICKED, hWnd);
  447.                     }
  448.                 }
  449.  
  450.             break;
  451.  
  452.  
  453.         case WM_COMMAND:
  454.             //Pass control messages on if the gizmo's notify is ON.
  455.             if (NULL!=pGB->hWndAssociate)
  456.                 {
  457.                 pGizmo=PGizmoFromHwndID(hWnd, wID);
  458.  
  459.                 if (NULL!=pGizmo)
  460.                     {
  461.                     if (pGizmo->fNotify)
  462.                         {
  463.                         SendMessage(pGB->hWndAssociate, iMsg, wParam
  464.                             , lParam);
  465.                         }
  466.                     }
  467.                 }
  468.             break;
  469.  
  470.         default:
  471.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  472.         }
  473.  
  474.     return 0L;
  475.     }
  476.  
  477.  
  478.  
  479.  
  480. /*
  481.  * GizmoBarPaint
  482.  *
  483.  * Purpose:
  484.  *  Handles all WM_PAINT messages for the control and paints either
  485.  *  the entire thing or just one GizmoBar button if pGB->pGizmoPaint
  486.  *  is non-NULL.
  487.  *
  488.  * Parameters:
  489.  *  hWnd            HWND Handle to the control.
  490.  *  pGB             PGIZMOBAR control data pointer.
  491.  *
  492.  * Return Value:
  493.  *  None
  494.  */
  495.  
  496. void GizmoBarPaint(HWND hWnd, PGIZMOBAR pGB)
  497.     {
  498.     RECT            rc;
  499.     HDC             hDC;
  500.     HBRUSH          hBr=NULL;
  501.     HPEN            hPen=NULL;
  502.     PAINTGIZMO      pg;
  503.  
  504.     hDC=BeginPaint(hWnd, &pg.ps);
  505.     GetClientRect(hWnd, &rc);
  506.  
  507.     /*
  508.      * The only part of the frame we need to draw is the bottom line,
  509.      * so we inflate the rectangle such that all other parts are
  510.      * outside the visible region.
  511.      */
  512.     hBr=CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  513.  
  514.     if (NULL!=hBr)
  515.         SelectObject(hDC, hBr);
  516.  
  517.     hPen=CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME));
  518.  
  519.     if (NULL!=hPen)
  520.         SelectObject(hDC, hPen);
  521.  
  522.     Rectangle(hDC, rc.left-1, rc.top-1, rc.right+1, rc.bottom);
  523.  
  524.  
  525.     /*
  526.      * All that we have to do to draw the controls is start through
  527.      * the list, ignoring anything but buttons, and calling BTTNCUR's
  528.      * UIToolButtonDraw for buttons.  Since we don't even have to
  529.      * track positions of things, we can just use an enum.
  530.      */
  531.  
  532.     UIToolConfigureForDisplay(&pg.tdd);
  533.     GizmoPEnum(&pGB->pGizmos, FEnumPaintGizmos, (DWORD)(LPTSTR)&pg);
  534.  
  535.     //Clean up
  536.     EndPaint(hWnd, &pg.ps);
  537.  
  538.     if (NULL!=hBr)
  539.         DeleteObject(hBr);
  540.  
  541.     if (NULL!=hPen)
  542.         DeleteObject(hPen);
  543.  
  544.     return;
  545.     }
  546.  
  547.  
  548.  
  549.  
  550.  
  551. /*
  552.  * FEnumPaintGizmos
  553.  *
  554.  * Purpose:
  555.  *  Enumeration callback for all the gizmos we know about in order to
  556.  *  draw them.
  557.  *
  558.  * Parameters:
  559.  *  pGizmo          PGIZMO to draw.
  560.  *  iGizmo          UINT index on the GizmoBar of this gizmo.
  561.  *  dw              DWORD extra data passed to GizmoPEnum, in our
  562.  *                  case a pointer to a PAINTGIZMO structure.
  563.  *
  564.  * Return Value:
  565.  *  BOOL            TRUE to continue the enumeration, FALSE
  566.  *                  otherwise.
  567.  */
  568.  
  569. BOOL WINAPI FEnumPaintGizmos(PGIZMO pGizmo, UINT iGizmo, DWORD dw)
  570.     {
  571.     PPAINTGIZMO     ppg=(PPAINTGIZMO)dw;
  572.     RECT            rc, rcI;
  573.  
  574.     //Only draw those marked for repaint.
  575.     if ((GIZMOTYPE_DRAWN & pGizmo->iType))
  576.         {
  577.         SetRect(&rc, pGizmo->x, pGizmo->y
  578.             , pGizmo->x+pGizmo->dx, pGizmo->y+pGizmo->dy);
  579.  
  580.         //Only draw gizmos in the repaint area
  581.         if (IntersectRect(&rcI, &rc, &ppg->ps.rcPaint))
  582.             {
  583.             UIToolButtonDraw(ppg->ps.hdc, pGizmo->x, pGizmo->y
  584.                 , pGizmo->dx, pGizmo->dy, pGizmo->hBmp
  585.                 , pGizmo->cxImage, pGizmo->cyImage, pGizmo->iBmp
  586.                 , (UINT)pGizmo->uState, &ppg->tdd);
  587.             }
  588.         }
  589.  
  590.     return TRUE;
  591.     }
  592.  
  593.  
  594.  
  595.  
  596.  
  597. /*
  598.  * FEnumChangeFont
  599.  *
  600.  * Purpose:
  601.  *  Enumeration callback for all the gizmos we know about in order to
  602.  *  send a new font to them that's stored in PGIZMOBAR in dw.
  603.  *
  604.  * Parameters:
  605.  *  pGizmo          PGIZMO to draw.
  606.  *  iGizmo          UINT index on the GizmoBar of this gizmo.
  607.  *  dw              DWORD extra data passed to GizmoPEnum, in our
  608.  *                  case the GizmoBar's pGB.
  609.  *
  610.  * Return Value:
  611.  *  BOOL            TRUE to continue the enumeration, FALSE otherwise.
  612.  */
  613.  
  614. BOOL WINAPI FEnumChangeFont(PGIZMO pGizmo, UINT iGizmo, DWORD dw)
  615.     {
  616.     PGIZMOBAR   pGB=(PGIZMOBAR)dw;
  617.  
  618.     //Only need to change fonts in windowed controls using WM_SETFONT
  619.     if (NULL!=pGizmo->hWnd)
  620.         {
  621.         SendMessage(pGizmo->hWnd, WM_SETFONT
  622.             , (WPARAM)pGB->hFont, 1L);
  623.         }
  624.  
  625.     return TRUE;
  626.     }
  627.  
  628.  
  629.  
  630.  
  631.  
  632.  
  633. /*
  634.  * FEnumEnable
  635.  *
  636.  * Purpose:
  637.  *  Enumeration callback for all the gizmos we know about in order to
  638.  *  enable or disable them from the WM_ENABLE message.
  639.  *
  640.  * Parameters:
  641.  *  pGizmo          PGIZMO to draw.
  642.  *  iGizmo          UINT index on the GizmoBar of this gizmo.
  643.  *  dw              DWORD extra data passed to GizmoPEnum, in our
  644.  *                  case the GizmoBar's pGB.
  645.  *
  646.  * Return Value:
  647.  *  BOOL            TRUE to continue the enumeration, FALSE
  648.  *                  otherwise.
  649.  */
  650.  
  651. BOOL WINAPI FEnumEnable(PGIZMO pGizmo, UINT iGizmo, DWORD dw)
  652.     {
  653.     PGIZMOBAR   pGB=(PGIZMOBAR)dw;
  654.     BOOL        fEnable=pGB->fEnabled;
  655.  
  656.     //NOTE:  This code is duplicated in GBGizmoEnable in API.C
  657.     if (NULL!=pGizmo->hWnd)
  658.         EnableWindow(pGizmo->hWnd, fEnable);
  659.     else
  660.         {
  661.         //If we're not down, command and attribute buttons act same.
  662.         if (!(BUTTONGROUP_DOWN & pGizmo->uState))
  663.             {
  664.             GizmoPStateSet(pGB->hWnd, pGizmo, fEnable
  665.                 ? COMMANDBUTTON_UP : COMMANDBUTTON_DISABLED);
  666.             }
  667.         else
  668.             {
  669.             /*
  670.              * Attribute buttons are a little more sensitive
  671.              * with DOWNDISABLED
  672.              */
  673.             GizmoPStateSet(pGB->hWnd, pGizmo, fEnable
  674.                 ? ATTRIBUTEBUTTON_DOWN
  675.                 : ATTRIBUTEBUTTON_DOWNDISABLED);
  676.             }
  677.         }
  678.  
  679.     return TRUE;
  680.     }
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688. /*
  689.  * FEnumHitTest
  690.  *
  691.  * Purpose:
  692.  *  Enumeration callback for all the gizmos we know about in order to
  693.  *  hit-test them.
  694.  *
  695.  * Parameters:
  696.  *  pGizmo          PGIZMO to draw.
  697.  *  iGizmo          UINT index on the GizmoBar of this gizmo.
  698.  *  dw              DWORD extra data passed to GizmoPEnum, in our
  699.  *                  case the hDC on which to draw.
  700.  *
  701.  * Return Value:
  702.  *  BOOL            TRUE to continue the enumeration, FALSE
  703.  *                  otherwise.
  704.  */
  705.  
  706. BOOL WINAPI FEnumHitTest(PGIZMO pGizmo, UINT iGizmo, DWORD dw)
  707.     {
  708.     RECT  rc;
  709.     POINT pt;
  710.  
  711.     POINTFROMLPARAM(pt, dw);
  712.     
  713.     /*
  714.      * Hit tests have to happen on visible, enabled, and drawn
  715.      * controls only.
  716.      */
  717.     if (GIZMOTYPE_DRAWN & pGizmo->iType && !pGizmo->fHidden
  718.         && !(BUTTONGROUP_DISABLED & pGizmo->uState))
  719.         {
  720.         SetRect(&rc, pGizmo->x, pGizmo->y
  721.             , pGizmo->x+pGizmo->dx, pGizmo->y+pGizmo->dy);
  722.  
  723.         //Stop enumeration if we have a hit.
  724.         return !PtInRect(&rc, pt);
  725.         }
  726.  
  727.     return TRUE;
  728.     }
  729.