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

  • Download the Information Governance Survey Benchmark Report to gain insights that can help you further establish business value in your Records and Information Management (RIM) program and across your entire organization. Discover how your peers in the industry are dealing with this evolving information lifecycle management environment and uncover key insights such as: 87% of organizations surveyed have a RIM program in place 8% measure compliance 64% cannot get employees to "let go" of information for …

  • You probably have several goals for your patient portal of choice. Is "community" one of them? With a bevy of vendors offering portal solutions, it can be challenging for a hospital to know where to start. Fortunately, YourCareCommunity helps ease the decision-making process. Read this white paper to learn more. "3 Ways Clinicians can Leverage a Patient Portal to Craft a Healthcare Community" is a published document owned by www.medhost.com

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds