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 / iviewers / shadow.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  15.0 KB  |  558 lines

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