Draw the US flag using GDI

Environment: Win32 (VC++ 6 project)

Just for fun, or perhaps even useful, here is a function to draw the US flag to a given HDC, in a given RECT. Looks best on a hi-rez device. Would look great embedded as a static control in a dialog, as a backdrop for an MDI app, a screensaver, or draw it to printer DC for a hardcopy. Cheers!

////////////////////////////////////////////////////////////////
//
// Draws the Star-Spangled Banner.
//
// Params:
// hdc   - The patriotic device context.
// pRect - Rect in DC to draw Old Glory to.
//
////////////////////////////////////////////////////////////////
// Sines & cosines for the angles of the five-pointed stars
#define SIN72       0.95106
#define COS72       0.30902
#define SIN144      0.58779
#define COS144     -0.80902
#define STARSIZE    0.67 // scale factor for the size of the stars
void DrawOldGlory(HDC hdc, RECT * pRect)
{
  HPEN hpenOld;
  HBRUSH  hbrRed, hbrWhite, hbrBlue, hbrOld;
  int x0 = pRect->left;
  int y0 = pRect->top;
  int x1 = pRect->right;
  int y1 = pRect->bottom;
  int cx = x1 - x0;
  int cy = y1 - y0;
  int i, j, x, y, xx, yy;
  int cxStarBox, cyStarBox;
  int nOldFillMode;

  // Create some colors for us to work with.
  hbrRed = CreateSolidBrush(RGB(255, 0, 0));
  hbrWhite = CreateSolidBrush(RGB(255, 255, 255));
  hbrBlue = CreateSolidBrush(RGB(0, 0, 128));

  // Hide the default pen so that we don't get
  // black borders around the filled shapes.
  // Whenever a rectangle is drawn, we'll add one pixel to the
  // right and bottom to fill in for the missing pen.
  hpenOld = (HPEN) SelectObject(hdc, GetStockObject(NULL_PEN));

  // Draw white background.
  hbrOld = (HBRUSH) SelectObject(hdc, hbrWhite);
  Rectangle(hdc, x0, y0, x1 + 1, y1 + 1);

  // Draw the seven red stripes.
  SelectObject(hdc, hbrRed);
  for (i = 0; i < 13; i++)
    if ((i & 1) == 0)
      Rectangle(hdc,
                x0,
                y0 + (i * cy) / 13,
                x1 + 1,
                y0 + ((i + 1) * cy) / 13 + 1);

  // Draw blue box.
  // Size it so that it covers two fifths of the flag length and
  // the top seven stripes vertically.
  cxStarBox = (2 * cx) / 5;
  cyStarBox = (7 * cy) / 13 + 1;
  SelectObject(hdc, hbrBlue);
  Rectangle(hdc,
            x0,
            y0,
            x0 + cxStarBox,
            y0 + cyStarBox);

  // Draw fifty stars in the blue box.
  SelectObject(hdc, hbrWhite);
  // We're going to draw the stars with just a five point polygon.
  // Select the 'winding' fill mode so that the centers of the stars
  // get filled too.
  nOldFillMode = SetPolyFillMode(hdc, WINDING);
  // Shrink the blue box rect a bit to give some border around the stars.
  x0 += cxStarBox / 25;
  y0 += cyStarBox / 25;
  cxStarBox *= 23;
  cxStarBox /= 25;
  cyStarBox *= 23;
  cyStarBox /= 25;
  y = y0;
  // Now, divide the box into a grid of 11 x 9 squares and place a star
  // in every other square, like on a checker board.
  for (j = 1; j <= 9; j++)
  {
    yy = y0 + (j * cyStarBox) / 9;
    x = x0;
    for (i = 1; i <= 11; i++)
    {
      xx = x0 + (i * cxStarBox) / 11;
      // Determine 'black' or 'white' square status by checking to see
      // if the sum of 'i' and 'j' is odd or even.
      // This ensures that the square colors of each row are always
      // staggered regardless of whether there is an odd or even number
      // of squares in each row.
      if (((i + j) & 1) == 0)
      {
        // Get the width and height of the current square.
        int w = xx - x;
        int h = yy - y;
        // Use the smaller of the two (width or height) as a basis
        // for the radius of the star.
        double r = (w < h) ? (double)w * STARSIZE : (double)h * STARSIZE;
        // Find the center of the current square.
        int centerX = (x + xx) / 2;
        int centerY = (y + yy) / 2;
        POINT pts[5];

        // Calculate the actual points for the stars by rotating the
        // radius around the center point using the pre-computed
        // sines & cosines.
        pts[0].x = centerX;
        pts[0].y = centerY - (int)(r);
        pts[1].x = centerX + (int)(r * SIN144);
        pts[1].y = centerY - (int)(r * COS144);
        pts[2].x = centerX - (int)(r * SIN72);
        pts[2].y = centerY - (int)(r * COS72);
        pts[3].x = centerX + (int)(r * SIN72);
        pts[3].y = pts[2].y;
        pts[4].x = centerX - (int)(r * SIN144);
        pts[4].y = pts[1].y;

        // Finally, draw the filled polygon.
        Polygon(hdc, pts, 5);
      }
      x = xx;
    }
    y = yy;
  }

  // Clean up.
  SetPolyFillMode(hdc, nOldFillMode);
  SelectObject(hdc, (HBRUSH) hbrOld);
  SelectObject(hdc, (HPEN) hpenOld);

  DeleteObject(hbrBlue);
  DeleteObject(hbrWhite);
  DeleteObject(hbrRed);
}

Downloads

Download demo project - 12 Kb


Comments

  • Coincidence?

    Posted by Legacy on 07/11/2002 12:00am

    Originally posted by: Peter O.

    "Date Posted: September 10, 2001"
    
    

    It was merely a coincidence that the code was posted a day before the tragedies.

    To the author: Amazing code.

    Reply
  • Generic flag drawing library?

    Posted by Legacy on 10/16/2001 12:00am

    Originally posted by: Eugene Epshteyn

    Wouldn't it be neat to have a source code library that would draw a flag of any country? (At least those that don't have many complex elements.)

    --Eugene

    Reply
  • Very significant

    Posted by Legacy on 10/12/2001 12:00am

    Originally posted by: Vernero Cifagni

    Your code is very good and significant. Yours is a flag round which all sensible people should gather. I am Italian, and I have decided to put an American flag in every "About" box in my programmes, in honour of those who died one month ago in America, and of those who will die in defense of all of us. My best congratulations, and never mind insults.
    Vernero

    Reply
  • Very Good GDI Example

    Posted by Legacy on 10/11/2001 12:00am

    Originally posted by: Mark Henri

    A perfect example of GDI programming with a timely subject. The concepts could be used to create a myriad of of other graphics or reports.

    Thanks,

    Reply
  • Very Good GDI Example

    Posted by Legacy on 10/11/2001 12:00am

    Originally posted by: Mark Henri

    A perfect example of GDI programming with a timely subject. The concepts could be used to create a myriad of of other graphics or reports.

    Thanks,

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • On-demand Event Event Date: October 29, 2014 It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this webcast, Gene Kim discusses these survey findings and shares woeful tales of artifact management gone wrong! Gene also shares examples of how high-performing DevOps …

Most Popular Programming Stories

More for Developers

RSS Feeds