home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / ole / oleview / shadow.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  15.0 KB  |  559 lines

  1.  
  2. // This is a part of the Microsoft Foundation Classes C++ library.
  3. // Copyright (C) 1992-1998 Microsoft Corporation
  4. // All rights reserved.
  5. //
  6. // This source code is only intended as a supplement to the
  7. // Microsoft Foundation Classes Reference and related
  8. // electronic documentation provided with the library.
  9. // See these sources for detailed information regarding the
  10. // Microsoft Foundation Classes product.
  11.  
  12. /************************************************************************
  13.  *      Module:  shadow.c
  14.  *
  15.  ***********************************************************************/
  16.  
  17. #include "stdafx.h"
  18. #include "shadow.h"
  19. VOID NEAR PASCAL Draw3DLine1( HDC hDC, UINT x, UINT y, UINT nLen, UINT wFlags ) ;
  20. VOID NEAR PASCAL DrawFrame( HDC hDC, LPRECT lprc ) ;
  21.  
  22. #define SHADOWWIDTH  1
  23.  
  24. /****************************************************************
  25.  *  VOID WINAPI tdDraw3DCrease( HDC hDC, LPRECT lprc, UINT uiFlags )
  26.  *
  27.  *  Description:
  28.  *
  29.  *
  30.  *
  31.  *  Comments:
  32.  *
  33.  ****************************************************************/
  34. VOID WINAPI tdDraw3DCrease( HDC hDC, LPRECT lpRect, UINT uiFlags )
  35. {
  36.    RECT       rc ;
  37.    COLORREF   rgbOld ;
  38.  
  39.    rc = *lpRect ;
  40.  
  41.    if (uiFlags & DRAW3D_OUT)
  42.       OffsetRect( &rc, 1, 1 ) ;
  43.  
  44.    rgbOld = SetBkColor( hDC, tdGetShadowColor( GetBkColor( hDC ) ) ) ;
  45.  
  46.    DrawFrame( hDC, &rc ) ;
  47.  
  48.    if (uiFlags & DRAW3D_OUT)
  49.       OffsetRect( &rc, -1, -1 ) ;
  50.    else
  51.       OffsetRect( &rc, 1, 1 ) ;
  52.  
  53.  
  54.    SetBkColor( hDC, tdGetHighlightColor( rgbOld ) ) ;
  55.  
  56.    DrawFrame( hDC, &rc ) ;
  57.  
  58.    SetBkColor( hDC, rgbOld ) ;
  59.  
  60. } /* tdDraw3DCrease()  */
  61.  
  62. /** VOID WINAPI tdDraw3DRect( HDC, LPRECT, UINT, UINT )
  63.  *
  64.  *  DESCRIPTION:
  65.  *      Draws a 3D rectangle that is shaded.  wFlags can be used to
  66.  *      control how the rectangle looks.
  67.  *
  68.  *  ARGUMENTS:
  69.  *      HDC hDC             :   Handle to the device context that will be
  70.  *                              used to display the rectangle.
  71.  *
  72.  *      RECT rect           :   A rectangle describing the dimensions of
  73.  *                              the rectangle in device coordinates.
  74.  *
  75.  *      UINT wShadowWidth   :   Width of the shadow in device coordinates.
  76.  *
  77.  *      UINT wFlags         :   The following flags may be passed to describe
  78.  *                              the style of the rectangle:
  79.  *
  80.  *                              DRAW3D_IN   :   The shadow is drawn such that
  81.  *                              the box appears to be sunk in to the screen.
  82.  *                              This is default if 0 is passed.
  83.  *
  84.  *                              DRAW3D_OUT  :   The shadow is drawn such that
  85.  *                              the box appears to be sticking out of the
  86.  *                              screen.
  87.  *
  88.  *  RETURN (VOID WINAPI):
  89.  *      The 3D looking rectangle will have been drawn into the DC.
  90.  *
  91.  *  NOTES:
  92.  *
  93.  ** cjp */
  94.  
  95. VOID WINAPI tdDraw3DRect( HDC hDC, LPRECT lpRect,
  96.                                UINT uiShadowWidth, UINT uiFlags )
  97. {
  98.    /* sanity check--don't work if you don't have to! */
  99.    if ( !uiShadowWidth || !RectVisible( hDC, lpRect ) )
  100.        return ;
  101.  
  102.    if (uiFlags & DRAW3D_CREASE)
  103.    {
  104.       tdDraw3DCrease( hDC, lpRect, uiFlags ) ;
  105.       return ;
  106.    }
  107.  
  108.    /* if width is 1 use lines instead of polygons */
  109.    if (uiShadowWidth == 1)
  110.    {
  111.       /* draw the top line */
  112.       Draw3DLine1( hDC, lpRect->left, lpRect->top,
  113.                      lpRect->right - lpRect->left,
  114.                      DRAW3D_TOPLINE | uiFlags ) ;
  115.  
  116.       /* right line */
  117.       Draw3DLine1( hDC, lpRect->right, lpRect->top,
  118.                      lpRect->bottom - lpRect->top,
  119.                      DRAW3D_RIGHTLINE | uiFlags ) ;
  120.  
  121.       /* bottom line */
  122.       Draw3DLine1( hDC, lpRect->left, lpRect->bottom,
  123.                      lpRect->right - lpRect->left,
  124.                      DRAW3D_BOTTOMLINE | uiFlags ) ;
  125.  
  126.       /* left line */
  127.       Draw3DLine1( hDC, lpRect->left, lpRect->top,
  128.                      lpRect->bottom - lpRect->top,
  129.                      DRAW3D_LEFTLINE | uiFlags ) ;
  130.    }
  131.    else
  132.    {
  133.       /* draw the top line */
  134.       tdDraw3DLine( hDC, lpRect->left, lpRect->top,
  135.                      lpRect->right - lpRect->left,
  136.                      uiShadowWidth, DRAW3D_TOPLINE | uiFlags ) ;
  137.  
  138.       /* right line */
  139.       tdDraw3DLine( hDC, lpRect->right, lpRect->top,
  140.                      lpRect->bottom - lpRect->top,
  141.                      uiShadowWidth, DRAW3D_RIGHTLINE | uiFlags ) ;
  142.  
  143.       /* bottom line */
  144.       tdDraw3DLine( hDC, lpRect->left, lpRect->bottom,
  145.                      lpRect->right - lpRect->left,
  146.                      uiShadowWidth, DRAW3D_BOTTOMLINE | uiFlags ) ;
  147.  
  148.       /* left line */
  149.       tdDraw3DLine( hDC, lpRect->left, lpRect->top,
  150.                      lpRect->bottom - lpRect->top,
  151.                      uiShadowWidth, DRAW3D_LEFTLINE | uiFlags ) ;
  152.    }
  153. } /* Draw3DRect() */
  154.  
  155.  
  156. /** VOID WINAPI tdDraw3DLine( HDC hDC, UINT x, UINT y, UINT nLen,
  157.  *
  158.  *  DESCRIPTION:
  159.  *      Draws a 3D line that can be used to make a 3D box.
  160.  *
  161.  *  ARGUMENTS:
  162.  *      HDC hDC             :   Handle to the device context that will be
  163.  *                              used to display the 3D line.
  164.  *
  165.  *      UINT x, y           :   Coordinates of the beginning of the line.
  166.  *                              These coordinates are in device UINTs and
  167.  *                              represent the _outside_ most point. Horiz-
  168.  *                              ontal lines are drawn from left to right and
  169.  *                              vertical lines are drawn from top to bottom.
  170.  *
  171.  *      UINT uiShadowWidth   :   Width of the shadow in device coordinates.
  172.  *
  173.  *      UINT  uiFlags        :   The following flags may be passed to
  174.  *                              describe the style of the 3D line:
  175.  *
  176.  *                              DRAW3D_IN   :   The shadow is drawn such that
  177.  *                              the box appears to be sunk in to the screen.
  178.  *                              This is default if 0 is passed.
  179.  *
  180.  *                              DRAW3D_OUT  :   The shadow is drawn such that
  181.  *                              the box appears to be sticking out of the
  182.  *                              screen.
  183.  *
  184.  *                              DRAW3D_TOPLINE, _BOTTOMLINE, _LEFTLINE, and
  185.  *                              _RIGHTLINE  :   Specifies that a "top",
  186.  *                              "Bottom", "Left", or"Right" line is to be
  187.  *                              drawn.
  188.  *
  189.  *  RETURN (VOID WINAPI):
  190.  *      The line will have been drawn into the DC.
  191.  *
  192.  *  NOTES:
  193.  *
  194.  ** cjp */
  195.  
  196. VOID WINAPI tdDraw3DLine( HDC hDC, UINT x, UINT y, UINT uiLen,
  197.                                UINT uiShadowWidth, UINT uiFlags )
  198. {
  199.    HBRUSH  hBrush ;
  200.    BOOL    fDark ;
  201.    POINT   Point[ 4 ] ;         /* define a polgon with 4 points    */
  202.  
  203.    /* if width is zero, don't do nothin'! */
  204.    if ( !uiShadowWidth )
  205.        return ;
  206.  
  207.    /* if width is 1 use lines instead of polygons */
  208.    if (uiShadowWidth == 1)
  209.    {
  210.       Draw3DLine1( hDC, x, y, uiLen, uiFlags ) ;
  211.       return ;
  212.    }
  213.  
  214.    /* define shape of polygon--origin is always the same */
  215.    Point[0].x = x ;
  216.    Point[0].y = y ;
  217.  
  218.    /*  To do this we'll simply draw a polygon with four sides, using
  219.     *  the appropriate brush.  I dare you to ask me why this isn't a
  220.     *  switch/case!
  221.     */
  222.    if ( uiFlags & DRAW3D_TOPLINE )
  223.    {
  224.        /* across to right */
  225.        Point[1].x = x + uiLen - (uiShadowWidth == 1 ? 1 : 0) ;
  226.        Point[1].y = y ;
  227.  
  228.        /* down/left */
  229.        Point[2].x = x + uiLen - uiShadowWidth ;
  230.        Point[2].y = y + uiShadowWidth ;
  231.  
  232.        /* accross to left */
  233.        Point[3].x = x + uiShadowWidth ;
  234.        Point[3].y = y + uiShadowWidth ;
  235.  
  236.        /* select 'dark' brush if 'in'--'light' for 'out' */
  237.        fDark = ( uiFlags & DRAW3D_IN ) ? TRUE : FALSE ;
  238.    }
  239.  
  240.    /* possibly the bottom? */
  241.    else if ( uiFlags & DRAW3D_BOTTOMLINE )
  242.    {
  243.        /* across to right */
  244.        Point[1].x = x + uiLen ;
  245.        Point[1].y = y ;
  246.  
  247.        /* up/left */
  248.        Point[2].x = x + uiLen - uiShadowWidth ;
  249.        Point[2].y = y - uiShadowWidth ;
  250.  
  251.        /* accross to left */
  252.        Point[3].x = x + uiShadowWidth ;
  253.        Point[3].y = y - uiShadowWidth ;
  254.  
  255.        /* select 'light' brush if 'in' */
  256.        fDark = ( uiFlags & DRAW3D_IN ) ? FALSE : TRUE ;
  257.    }
  258.  
  259.    /* ok, it's gotta be left? */
  260.    else if ( uiFlags & DRAW3D_LEFTLINE )
  261.    {
  262.        /* down */
  263.        Point[1].x = x ;
  264.        Point[1].y = y + uiLen - (uiShadowWidth == 1 ? 1 : 0) ;
  265.  
  266.        /* up/right */
  267.        Point[2].x = x + uiShadowWidth ;
  268.        Point[2].y = y + uiLen - uiShadowWidth ;
  269.  
  270.        /* down */
  271.        Point[3].x = x + uiShadowWidth ;
  272.        Point[3].y = y + uiShadowWidth ;
  273.  
  274.        /* select 'dark' brush if 'in'--'light' for 'out' */
  275.        fDark = ( uiFlags & DRAW3D_IN ) ? TRUE : FALSE ;
  276.    }
  277.  
  278.    /* well maybe it's for the right side? */
  279.    else if ( uiFlags & DRAW3D_RIGHTLINE )
  280.    {
  281.        /* down */
  282.        Point[1].x = x ;
  283.        Point[1].y = y + uiLen ;
  284.  
  285.        /* up/left */
  286.        Point[2].x = x - uiShadowWidth ;
  287.        Point[2].y = y + uiLen - uiShadowWidth ;
  288.  
  289.        /* up */
  290.        Point[3].x = x - uiShadowWidth ;
  291.        Point[3].y = y + uiShadowWidth ;
  292.  
  293.        /* select 'light' brush if 'in' */
  294.        fDark = ( uiFlags & DRAW3D_IN ) ? FALSE : TRUE ;
  295.    }
  296.    else
  297.         return ;
  298.  
  299.    /* select NULL_PEN for no borders */
  300.    SelectObject( hDC, GetStockObject( NULL_PEN ) ) ;
  301.  
  302.    /* select the appropriate color for the fill */
  303.    hBrush = CreateSolidBrush( GetNearestColor( hDC, fDark ?
  304.                               tdGetShadowColor( GetBkColor( hDC ) ) :
  305.                               tdGetHighlightColor( GetBkColor( hDC ) ) ) ) ;
  306.  
  307.    hBrush = (HBRUSH)SelectObject( hDC, hBrush ) ;
  308.  
  309.    /* finally, draw the dern thing */
  310.    Polygon( hDC, (LPPOINT)&Point, 4 ) ;
  311.  
  312.    /* restore what we killed */
  313.    hBrush = (HBRUSH)SelectObject( hDC, hBrush ) ;
  314.  
  315.    DeleteObject( hBrush ) ;
  316.  
  317. } /*tdDraw3DLine() */
  318.  
  319.  
  320.  
  321. /****************************************************************
  322.  *  COLORREF WINAPI tdGetHighLightColor( COLORREF rgb )
  323.  *
  324.  *  Description:
  325.  *
  326.  *    This function returns the highlight color that corresponds
  327.  *    to the given rgb value.  If there is no "high intensity"
  328.  *    color that matches, white is used (or yellow if the color
  329.  *    is white).
  330.  *
  331.  *  Comments:
  332.  *
  333.  ****************************************************************/
  334. COLORREF WINAPI tdGetHighlightColor( COLORREF rgb )
  335. {
  336.    BYTE  cRed, cGreen, cBlue ;
  337.  
  338.     #if _MFC_VER >= 0x0300
  339.         if (rgb == GetSysColor( COLOR_BTNFACE ))
  340.             return GetSysColor( COLOR_BTNHIGHLIGHT ) ;
  341.     #endif
  342.  
  343.    if (rgb == RGBLTRED     ||
  344.        rgb == RGBLTGREEN   ||
  345.        rgb == RGBLTBLUE    ||
  346.        rgb == RGBLTMAGENTA ||
  347.        rgb == RGBLTCYAN    ||
  348.        rgb == RGBLTGRAY    ||
  349.        rgb == RGBYELLOW)
  350.       return RGBWHITE ;
  351.  
  352.    if (rgb == RGBWHITE)
  353.       return RGBLTGRAY ;
  354.  
  355.    if (rgb == RGBBLACK || rgb == RGBGRAY)
  356.       return RGBLTGRAY ;
  357.  
  358.    cRed = (BYTE)(rgb & 0x000000FF) ;
  359.  
  360.    cGreen = (BYTE)((rgb & 0x0000FF00) >> 8) ;
  361.  
  362.    cBlue = (BYTE)((rgb & 0x00FF0000) >> 16) ;
  363.  
  364.    if (cRed == 128)
  365.       cRed += 64 ;
  366.  
  367.    if (cGreen == 128)
  368.       cGreen += 64 ;
  369.  
  370.    if (cBlue == 128)
  371.       cBlue += 64 ;
  372.  
  373.    return RGB( cRed, cGreen, cBlue ) ;
  374.  
  375. } /* tdGetHighlightColor()  */
  376.  
  377.  
  378. /****************************************************************
  379.  *  COLORREF WINAPI tdGetShadowColor( COLORREF rgb )
  380.  *
  381.  *  Description:
  382.  *
  383.  *    Returns an appropriate shadow color for the given rgb.
  384.  *
  385.  *  Comments:
  386.  *
  387.  ****************************************************************/
  388. COLORREF WINAPI tdGetShadowColor( COLORREF rgb )
  389. {
  390.     if (rgb == GetSysColor( COLOR_BTNFACE ))
  391.         return GetSysColor( COLOR_BTNSHADOW ) ;
  392.  
  393.    BYTE  cRed, cGreen, cBlue ;
  394.  
  395.    if (rgb == RGBBLACK)
  396.       return RGBGRAY ;
  397.  
  398.    if (rgb == RGBRED     ||
  399.        rgb == RGBGREEN   ||
  400.        rgb == RGBBLUE    ||
  401.        rgb == RGBBROWN   ||
  402.        rgb == RGBMAGENTA ||
  403.        rgb == RGBCYAN    ||
  404.        rgb == RGBWHITE   ||
  405.        rgb == RGBGRAY)
  406.       return RGBBLACK ;
  407.  
  408.    if (rgb == RGBLTGRAY)
  409.       return RGBGRAY ;
  410.  
  411.    cRed = (BYTE)(rgb & 0x000000FF) ;
  412.  
  413.    cGreen = (BYTE)((rgb & 0x0000FF00) >> 8) ;
  414.  
  415.    cBlue = (BYTE)((rgb & 0x00FF0000) >> 16) ;
  416.  
  417.    if (cRed > 128)
  418.       cRed -= 64 ;
  419.  
  420.    if (cGreen > 128)
  421.       cGreen -= 64 ;
  422.  
  423.    if (cBlue > 128)
  424.       cBlue -= 64 ;
  425.  
  426.    return RGB( cRed, cGreen, cBlue ) ;
  427. } /* tdGetShadowColor()  */
  428.  
  429.  
  430. /*
  431.  *====================================================================
  432.  *  Internal functions
  433.  *====================================================================
  434.  */
  435.  
  436. /****************************************************************
  437.  *  VOID NEAR PASCAL
  438.  *   Draw3DLine1( HDC hDC, UINT x, UINT y, UINT uiLen, UINT uiFlags )
  439.  *
  440.  *  Description:
  441.  *
  442.  *    Does the same thing astdDraw3DLine but for single width lines.
  443.  *
  444.  *  Comments:
  445.  *
  446.  ****************************************************************/
  447. VOID NEAR PASCAL
  448.    Draw3DLine1( HDC hDC, UINT x, UINT y, UINT uiLen, UINT uiFlags )
  449. {
  450.    BOOL    fDark ;
  451.    RECT    rc ;
  452.    COLORREF   rgbOld ;
  453.  
  454.    if ( uiFlags & DRAW3D_TOPLINE )
  455.    {
  456.       rc.left = x ;
  457.       rc.right = rc.left + uiLen - 1 ;
  458.       rc.top = y ;
  459.       rc.bottom = y + 1 ;
  460.  
  461.       fDark = ( uiFlags & DRAW3D_IN ) ? TRUE : FALSE ;
  462.    }
  463.  
  464.    /* possibly the bottom? */
  465.    else if ( uiFlags & DRAW3D_BOTTOMLINE )
  466.    {
  467.       rc.left = x ;
  468.       rc.right = rc.left + uiLen - 1 ;
  469.       rc.top = y - 1 ;
  470.       rc.bottom = y ;
  471.  
  472.       fDark = ( uiFlags & DRAW3D_IN ) ? FALSE : TRUE ;
  473.    }
  474.  
  475.    /* ok, it's gotta be left? */
  476.    else if ( uiFlags & DRAW3D_LEFTLINE )
  477.    {
  478.       rc.left = x ;
  479.       rc.right = x + 1 ;
  480.       rc.top = y ;
  481.       rc.bottom = y + uiLen ;
  482.  
  483.       fDark = ( uiFlags & DRAW3D_IN ) ? TRUE : FALSE ;
  484.    }
  485.  
  486.    /* well maybe it's for the right side? */
  487.    else if ( uiFlags & DRAW3D_RIGHTLINE )
  488.    {
  489.       rc.left = x - 1 ;
  490.       rc.right = x ;
  491.       rc.top = y ;
  492.       rc.bottom = y + uiLen ;
  493.  
  494.       fDark = ( uiFlags & DRAW3D_IN ) ? FALSE : TRUE ;
  495.    }
  496.  
  497.    /* bad drugs? */
  498.    else return ;
  499.  
  500.    /* select the appropriate color for the fill */
  501.    if ( fDark )
  502.       rgbOld = SetBkColor( hDC,
  503.                GetNearestColor( hDC, tdGetShadowColor( GetBkColor( hDC ) ) ) ) ;
  504.    else
  505.       rgbOld = SetBkColor( hDC,
  506.                GetNearestColor( hDC, tdGetHighlightColor( GetBkColor( hDC ) ) ) ) ;
  507.  
  508.    /* finally, draw the dern thing */
  509.  
  510.    ExtTextOut( hDC, x, y, ETO_OPAQUE, &rc, NULL, 0, NULL ) ;
  511.  
  512.    SetBkColor( hDC, rgbOld ) ;
  513.  
  514. } /* Draw3DLine1()  */
  515.  
  516. VOID NEAR PASCAL DrawFrame( HDC hDC, LPRECT lprc )
  517. {
  518.    RECT    rc1 ;
  519.  
  520.    /* perform CopyRect w/o bloody windows style overhead */
  521.    rc1 = *lprc ;
  522.  
  523.    /* top */
  524.    rc1.top = lprc->top ;
  525.    rc1.left = lprc->left ;
  526.    rc1.bottom = lprc->top + 1 ;
  527.    rc1.right = lprc->right ;
  528.  
  529.    /* blast it out */
  530.    ExtTextOut( hDC, rc1.left, rc1.top, ETO_OPAQUE, &rc1, NULL, 0, NULL ) ;
  531.  
  532.    /* right */
  533.    rc1.left = lprc->right - 1 ;
  534.    rc1.bottom = lprc->bottom ;
  535.  
  536.    /* blast this part now */
  537.    ExtTextOut( hDC, rc1.left, rc1.top, ETO_OPAQUE, &rc1, NULL, 0, NULL ) ;
  538.  
  539.    /* left */
  540.    rc1.left = lprc->left ;
  541.    rc1.right = lprc->left + 1 ;
  542.  
  543.    /* and another part */
  544.    ExtTextOut( hDC, rc1.left, rc1.top, ETO_OPAQUE, &rc1, NULL, 0, NULL ) ;
  545.  
  546.    /* bottom */
  547.    rc1.right = lprc->right ;
  548.    rc1.top = lprc->bottom - 1 ;
  549.  
  550.    /* finish it off */
  551.    ExtTextOut( hDC, rc1.left, rc1.top, ETO_OPAQUE, &rc1, NULL, 0, NULL ) ;
  552.  
  553. } /* DrawFaceFrame() */
  554.  
  555.  
  556. /************************************************************************
  557.  * End of File: shadow.c
  558.  ***********************************************************************/
  559.