Compartir a través de


Escalado de una imagen

Algunas aplicaciones escalan imágenes; es decir, muestran vistas ampliadas o reducidas de una imagen. Por ejemplo, una aplicación de dibujo puede proporcionar una característica de zoom que permita al usuario ver y editar un dibujo en píxeles.

Las aplicaciones escalan imágenes mediante una llamada a la función StretchBlt . Al igual que la función BitBlt , StretchBlt copia datos de mapa de bits de un mapa de bits en un contexto de dispositivo de origen (DC) en un mapa de bits en un controlador de dominio de destino. Sin embargo, a diferencia de la función BitBlt , StretchBlt escala la imagen en función de las dimensiones especificadas de los rectángulos de origen y de destino. Si el rectángulo de origen es mayor que el rectángulo de destino, parecerá que la imagen resultante se ha reducido; Si el rectángulo de origen es menor que el rectángulo de destino, parecerá que la imagen resultante se ha expandido.

Si el rectángulo de destino es menor que el rectángulo de origen, StretchBlt quita los datos de color de la imagen según un modo extendido especificado, tal como se muestra en la tabla siguiente.

Modo stretch Método
BLACKONWHITE Realiza una operación AND lógica en los datos de color de los píxeles eliminados y los datos de color de los píxeles restantes.
WHITEONBLACK Realiza una operación OR lógica en los datos de color de los píxeles eliminados y los datos de color de los píxeles restantes.
COLORONCOLOR Elimina completamente los datos de color de los píxeles eliminados.
SEMITONOS Aproxima los datos de color originales (origen) en el destino.

 

Para establecer el modo extendido, llame a la función SetStretchBltMode .

El código de ejemplo siguiente se toma de una aplicación que muestra los cuatro modos extendidos disponibles con la función StretchBlt .

#include "stdafx.h"
#include "GDIBitmapScaling.h"
#include <commctrl.h>
#include <CommDlg.h>




#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);


int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

     // TODO: Place code here.
    MSG msg;
    HACCEL hAccelTable;

    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_GDIBITMAPSCALING, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GDIBITMAPSCALING));

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GDIBITMAPSCALING));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_GDIBITMAPSCALING);
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//

#define NEW_DIB_FORMAT(lpbih) (lpbih->biSize != sizeof(BITMAPCOREHEADER))
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_SYSMENU,
      CW_USEDEFAULT, 0, 1024, 768, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

static   HCURSOR hcurSave;

WORD DIBNumColors (LPVOID lpv)
{
    INT                 bits;
    LPBITMAPINFOHEADER  lpbih = (LPBITMAPINFOHEADER)lpv;
    LPBITMAPCOREHEADER  lpbch = (LPBITMAPCOREHEADER)lpv;

    /*  With the BITMAPINFO format headers, the size of the palette
     *  is in biClrUsed, whereas in the BITMAPCORE - style headers, it
     *  is dependent on the bits per pixel ( = 2 raised to the power of
     *  bits/pixel).
     */
    if (NEW_DIB_FORMAT(lpbih)) {
      if (lpbih->biClrUsed != 0)
        return (WORD)lpbih->biClrUsed;
      bits = lpbih->biBitCount;
    }
    else
      bits = lpbch->bcBitCount;

    if (bits > 8) 
      return 0; /* Since biClrUsed is 0, we dont have a an optimal palette */
    else
      return (1 << bits); 
}
/* Macro to determine to round off the given value to the closest byte */
#define WIDTHBYTES(i)   ((((i)+31) >> 5) << 2)
/******************************************************************************
 *                                                                            *
 *  FUNCTION   : DIBInfo(HANDLE hbi, LPBITMAPINFOHEADER lpbih)                *
 *                                                                            *
 *  PURPOSE    : Retrieves the DIB info associated with a CF_DIB              *
 *               format memory block.                                         *
 *                                                                            *
 *  RETURNS    : TRUE  - if successful.                                       *
 *               FALSE - otherwise                                            *
 *                                                                            *
 *****************************************************************************/
BOOL DIBInfo (HANDLE hbi, LPBITMAPINFOHEADER lpbih)
{
    if (hbi){
      *lpbih = *(LPBITMAPINFOHEADER)hbi;

      /* fill in the default fields */
      if (NEW_DIB_FORMAT(lpbih)) {
        if (lpbih->biSizeImage == 0L)
          lpbih->biSizeImage = WIDTHBYTES(lpbih->biWidth*lpbih->biBitCount) * lpbih->biHeight;

        if (lpbih->biClrUsed == 0L)
          lpbih->biClrUsed = DIBNumColors (lpbih);
      }

      return TRUE;
    }
    return FALSE;
}
/* flags for mmioSeek() */
#ifndef SEEK_SET
#define SEEK_SET        0               /* seek to an absolute position */
#define SEEK_CUR        1               /* seek relative to current position */
#define SEEK_END        2               /* seek relative to end of file */
#endif  /* ifndef SEEK_SET */
VOID ReadPackedFileHeader(HFILE hFile, LPBITMAPFILEHEADER lpbmfhdr, LPDWORD lpdwOffset)
{
    *lpdwOffset = _llseek(hFile, 0L, (UINT) SEEK_CUR);
    _hread(hFile, (LPSTR) &lpbmfhdr->bfType, sizeof(WORD)); /* read in bfType*/            
    _hread(hFile, (LPSTR) &lpbmfhdr->bfSize, sizeof(DWORD) * 3); /* read in last 3 dwords*/
}




/* macro to determine if resource is a DIB */
#define ISDIB(bft) ((bft) == BFT_BITMAP)

/* Header signatutes for various resources */
#define BFT_ICON   0x4349   /* 'IC' */
#define BFT_BITMAP 0x4d42   /* 'BM' */
#define BFT_CURSOR 0x5450   /* 'PT' */
HANDLE ReadDIBBitmapInfo (INT hFile)
{
    DWORD              dwOffset;
    HANDLE             hbi = NULL;
    INT                size;
    INT                i;
    WORD               nNumColors;
    LPRGBQUAD          lprgbq;
    BITMAPINFOHEADER   bih;
    BITMAPCOREHEADER   bch;
    LPBITMAPINFOHEADER lpbih;
    BITMAPFILEHEADER   bf;
    DWORD              dwDWMasks= 0;
    DWORD              dwWidth = 0;
    DWORD              dwHeight = 0;
    WORD               wPlanes, wBitCount;

    if (hFile == HFILE_ERROR)
        return NULL;

    /* Read the bitmap file header */
    ReadPackedFileHeader(hFile, &bf, &dwOffset);

    /* Do we have a RC HEADER? */
    if (!ISDIB (bf.bfType)) {    
      bf.bfOffBits = 0L;               
        _llseek(hFile, dwOffset, (UINT)SEEK_SET); /* seek back to beginning of file */
    }

    if (sizeof(bih) != _hread(hFile, (LPSTR)&bih, (UINT)sizeof(bih)))
      return FALSE;

    nNumColors = DIBNumColors (&bih);

    /* Check the nature (BITMAPINFO or BITMAPCORE) of the info. block
     * and extract the field information accordingly. If a BITMAPCOREHEADER, 
     * transfer it's field information to a BITMAPINFOHEADER-style block
     */
    switch (size = (INT)bih.biSize){
        case sizeof (BITMAPINFOHEADER):
            break;

        case sizeof (BITMAPCOREHEADER):

            bch = *(LPBITMAPCOREHEADER)&bih;

            dwWidth   = (DWORD)bch.bcWidth;
            dwHeight  = (DWORD)bch.bcHeight;
            wPlanes   = bch.bcPlanes;
            wBitCount = bch.bcBitCount;

            bih.biSize           = sizeof(BITMAPINFOHEADER);
            bih.biWidth          = dwWidth;
            bih.biHeight         = dwHeight;
            bih.biPlanes         = wPlanes;
            bih.biBitCount       = wBitCount;
            bih.biCompression    = BI_RGB;
            bih.biSizeImage      = 0;
            bih.biXPelsPerMeter  = 0;
            bih.biYPelsPerMeter  = 0;
            bih.biClrUsed        = nNumColors;
            bih.biClrImportant   = nNumColors;

            _llseek(hFile, (LONG)sizeof (BITMAPCOREHEADER) - sizeof (BITMAPINFOHEADER), (UINT)SEEK_CUR);
            break;

        default:
            /* Not a DIB! */
            return NULL;
    }

    /*  Fill in some default values if they are zero */
    if (bih.biSizeImage == 0){
        bih.biSizeImage = WIDTHBYTES((DWORD)bih.biWidth * bih.biBitCount) * bih.biHeight;
    }
    if (bih.biClrUsed == 0)
        bih.biClrUsed = DIBNumColors(&bih);

    /* Allocate for the BITMAPINFO structure and the color table. */
    if ((bih.biBitCount == 16) || (bih.biBitCount == 32))
      dwDWMasks = sizeof(DWORD) * 3;
    hbi = GlobalAlloc (GPTR, (LONG)bih.biSize + nNumColors * sizeof(RGBQUAD) + dwDWMasks);
    if (!hbi)
        return NULL;
    lpbih = (LPBITMAPINFOHEADER)hbi;
    *lpbih = bih;

    /* Get a pointer to the color table */
    lprgbq = (LPRGBQUAD)((LPSTR)lpbih + bih.biSize);
    if (nNumColors){
        if (size == sizeof(BITMAPCOREHEADER)){
            /* Convert a old color table (3 byte RGBTRIPLEs) to a new
             * color table (4 byte RGBQUADs)
             */
            _hread(hFile, (LPSTR)lprgbq, (UINT)nNumColors * sizeof(RGBTRIPLE));

            for (i = nNumColors - 1; i >= 0; i--){
                RGBQUAD rgbq;

                rgbq.rgbRed      = ((RGBTRIPLE*)lprgbq)[i].rgbtRed;
                rgbq.rgbBlue     = ((RGBTRIPLE*)lprgbq)[i].rgbtBlue;
                rgbq.rgbGreen    = ((RGBTRIPLE*)lprgbq)[i].rgbtGreen;
                rgbq.rgbReserved = (BYTE)0;

                lprgbq[i] = rgbq;
            }
        }
        else
            _hread(hFile, (LPSTR)lprgbq, (UINT)nNumColors * sizeof(RGBQUAD));
    } else
        if (dwDWMasks)
           _hread(hFile, (LPSTR)lprgbq, dwDWMasks);

    if (bf.bfOffBits != 0L){
        _llseek(hFile, dwOffset + bf.bfOffBits, (UINT)SEEK_SET);
        }
    
    return hbi;
}
HGLOBAL GlobalFreeDIB(HGLOBAL hDIB)
{
   LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)hDIB;

   if (!lpbi->biClrImportant)
     return GlobalFree(hDIB);

   if (GlobalFlags((HGLOBAL)lpbi->biClrImportant) == GMEM_INVALID_HANDLE) {
    SetLastError(0);
    return GlobalFree(hDIB);
  } else
    return GlobalFree((HANDLE)lpbi->biClrImportant); 
}
/******************************************************************************
 *                                                                            *
 *  FUNCTION   :  ColorTableSize(LPVOID lpv)                                  *
 *                                                                            *
 *  PURPOSE    :  Calculates the palette size in bytes. If the info. block    *
 *                is of the BITMAPCOREHEADER type, the number of colors is    *
 *                multiplied by 3 to give the palette size, otherwise the     *
 *                number of colors is multiplied by 4.                        *
 *                                                                            *
 *  RETURNS    :  Color table size in number of bytes.                        *
 *                                                                            *
 *****************************************************************************/
WORD ColorTableSize (LPVOID lpv)
{
    LPBITMAPINFOHEADER lpbih = (LPBITMAPINFOHEADER)lpv;
    
    if (NEW_DIB_FORMAT(lpbih))
    {
      if (((LPBITMAPINFOHEADER)(lpbih))->biCompression == BI_BITFIELDS)
         /* Remember that 16/32bpp dibs can still have a color table */
         return (sizeof(DWORD) * 3) + (DIBNumColors (lpbih) * sizeof (RGBQUAD));
      else
         return (DIBNumColors (lpbih) * sizeof (RGBQUAD));
    }
    else
      return (DIBNumColors (lpbih) * sizeof (RGBTRIPLE));
}

/******************************************************************************
 *                                                                            *
 *  FUNCTION   :OpenDIB(LPSTR szFilename)                                     *
 *                                                                            *
 *  PURPOSE    :Open a DIB file and create a memory DIB -- a memory handle    *
 *              containing BITMAPINFO, palette data and the bits.             * 
 *                                                                            *
 *  RETURNS    :A handle to the DIB.                                          *
 *                                                                            *
 *****************************************************************************/
HANDLE OpenDIB (LPSTR szFilename)
{
    HFILE               hFile;
    BITMAPINFOHEADER    bih;
    LPBITMAPINFOHEADER  lpbih;
    DWORD               dwLen = 0;
    DWORD               dwBits;
    HANDLE              hDIB;
    HANDLE              hMem;
    OFSTRUCT            of;

    /* Open the file and read the DIB information */
    hFile = OpenFile(szFilename, &of, (UINT)OF_READ);
    if (hFile == HFILE_ERROR)
        return NULL;

    hDIB = ReadDIBBitmapInfo(hFile);
    if (!hDIB)
        return NULL;
    DIBInfo(hDIB, &bih);

    /* Calculate the memory needed to hold the DIB */
    dwBits = bih.biSizeImage;
    dwLen  = bih.biSize + (DWORD)ColorTableSize (&bih) + dwBits;

    /* Try to increase the size of the bitmap info. buffer to hold the DIB */
    hMem = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE);

    if (!hMem){
        GlobalFreeDIB(hDIB);
        hDIB = NULL;
    }
    else
        hDIB = hMem;

    /* Read in the bits */
    if (hDIB){
        lpbih = (LPBITMAPINFOHEADER)hDIB;
        _hread(hFile, (LPSTR)lpbih + (WORD)lpbih->biSize + ColorTableSize(lpbih), dwBits);
    }
    _lclose(hFile);

    return hDIB;
}/* Macros to display/remove hourglass cursor for lengthy operations */
#define StartWait() hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT))
#define EndWait()   SetCursor(hcurSave)
/******************************************************************************
 *                                                                            *
 *  FUNCTION   : BitmapFromDIB(HANDLE hDIB, HPALETTE hPal)                    *
 *                                                                            *
 *  PURPOSE    : Will create a DDB (Device Dependent Bitmap) given a global   *
 *               handle to a memory block in CF_DIB format                    *
 *                                                                            *
 *  RETURNS    : A handle to the DDB.                                         *
 *                                                                            *
 *****************************************************************************/
HBITMAP BitmapFromDIB (HANDLE hDIB, HPALETTE  hPal)
{
    LPBITMAPINFOHEADER  lpbih;
    HPALETTE            hPalOld;
    HDC                 hDC;
    HBITMAP             hBitmap;  

    StartWait();

    if (!hDIB)
        return NULL;

    lpbih = (LPBITMAPINFOHEADER)hDIB;

    if (!lpbih)
        return NULL;

    hDC = GetDC(NULL);

    if (hPal){
        hPalOld = SelectPalette(hDC, hPal, FALSE);
        RealizePalette(hDC);     
    }                              
   
    hBitmap = CreateDIBitmap(hDC, 
                lpbih, 
                CBM_INIT, 
                (LPSTR)lpbih + lpbih->biSize + ColorTableSize(lpbih), 
                (LPBITMAPINFO)lpbih, 
                DIB_RGB_COLORS ); 

    if (hPal)
        SelectPalette(hDC, hPalOld, FALSE);

    ReleaseDC(NULL, hDC);

    EndWait();

    return hBitmap;
}
/******************************************************************************
 *                                                                            *
 *  FUNCTION   : DrawBitmap(HDC hDC, int x, int y,                            *
 *                          HBITMAP hBitmap, DWORD dwROP)                     * 
 *                                                                            *
 *  PURPOSE    : Draws bitmap <hBitmap> at the specified position in DC <hDC> *
 *                                                                            *
 *  RETURNS    : Return value of BitBlt()                                     *
 *                                                                            *
 *****************************************************************************/
BOOL DrawBitmap (HDC hDC, INT x, INT y, HBITMAP hBitmap, DWORD dwROP)
{
    HDC       hDCBits;
    BITMAP    Bitmap;
    BOOL      bResult;

    if (!hDC || !hBitmap)
        return FALSE;

    hDCBits = CreateCompatibleDC(hDC);
    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
    SelectObject(hDCBits, hBitmap);
    bResult = BitBlt(hDC, x, y, Bitmap.bmWidth, Bitmap.bmHeight, hDCBits, 0, 0, dwROP);
    DeleteDC(hDCBits);

    return bResult;
}

  /*FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)

  PURPOSE:  Processes messages for the main window.

  WM_COMMAND    - process the application menu
  WM_PAINT    - Paint the main window
  WM_DESTROY    - post a quit message and return*/



#define ID_LOADBITMAP 1

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    //Handle to a GDI device context
    HDC hDC;
    //Handle to a DDB(device-dependent bitmap)
    HBITMAP hBitmap;
    

    HFONT hFont;
    NONCLIENTMETRICS ncm={0};
    ncm.cbSize= sizeof(NONCLIENTMETRICS);
    
    
    static HWND hwndButton;
    static HWND hwndButtonExit;
    static HANDLE hDIB = NULL;
    
    char szDirName[MAX_PATH];
    char szFilename[MAX_PATH]="\0";
    char szBitmapName[MAX_PATH]="\\Waterfall.bmp";
    //char szBitmapName[MAX_PATH]="\\tulips256.bmp";
    OPENFILENAMEA ofn;
        
    
    switch (message)
    {
    
    case WM_CREATE:
        
        //Creates a font from the current theme's caption font
        SystemParametersInfo(SPI_GETNONCLIENTMETRICS, NULL, &ncm, NULL);
        hFont = CreateFontIndirect(&ncm.lfCaptionFont);
        
        //Gets the device context for the current window
        hDC = GetDC(hWnd);
        
        //Gets the directory of the current project and loads Waterfall.bmp
        GetCurrentDirectoryA(MAX_PATH, szDirName);
        strcat_s(szDirName, szBitmapName);
        strcat_s(szFilename,szDirName);
        hDIB = OpenDIB(szFilename);
        hBitmap = BitmapFromDIB(hDIB, NULL);

        //Draws Waterfall.bmp as a device dependent bitmap
        DrawBitmap(hDC,0,0,hBitmap,SRCCOPY);
        InvalidateRect(hWnd, NULL, FALSE);
        ReleaseDC(hWnd,hDC);
    
        //Draws the "Load Bitmap" button
        hwndButton = CreateWindowW(TEXT("button"),TEXT("Load Bitmap"), 
            WS_CHILD | WS_VISIBLE | WS_BORDER, 600, 200, 150,50,
            hWnd, 
            (HMENU)ID_LOADBITMAP, 
            ((LPCREATESTRUCT) lParam)-> hInstance, NULL);

        //Set the font of the button to the theme's caption font
        SendMessage(hwndButton, WM_SETFONT, (WPARAM)hFont, TRUE );
        
    
        return 0;


    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        
        
        //if Load Bitmap button is pressed
        if (wmId == ID_LOADBITMAP && wmEvent == BN_CLICKED)
        {
                            
            //Get the current directory name, and store in szDirName 
            GetCurrentDirectoryA(MAX_PATH, szDirName);
            
            //Set all structure members to zero. 
            ZeroMemory(&ofn, sizeof(OPENFILENAMEA));
            
            //Initializing the OPENFILENAMEA structure 
            ofn.lStructSize = sizeof(OPENFILENAMEA);
            ofn.hwndOwner = hWnd;
            ofn.lpstrFilter ="BMP Files (*.BMP)\0 *.BMP\0\0";
            ofn.lpstrFile = szFilename;
            ofn.nMaxFile = sizeof(szFilename);
            ofn.lpstrDefExt = "BMP";
            ofn.lpstrInitialDir = szDirName;
            ofn.Flags = OFN_EXPLORER | OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

                            

            if (GetOpenFileNameA(&ofn)) {
               hDIB = OpenDIB((LPSTR)szFilename);   
               if (!hDIB)
                  MessageBox(hWnd, TEXT("Unable to load file!"), TEXT("Oops"), MB_ICONSTOP);
            } else {
                if (strlen((const char *)szFilename) != 0)
                  MessageBox(hWnd, TEXT("Unable to load file!"), TEXT("Oops"), MB_ICONSTOP);
                
                return 0;
            }
            
            
            

            InvalidateRect(hWnd, NULL, FALSE);
                            
                        
        }
        
        
        break;
    case WM_PAINT:
        {
            //Initializing arrays for boxes
            POINT pRect1[5] = {{0,0},{400,0},{400,400},{0,400},{0,0}};
            POINT pRect2[5] = {{0,500}, {200, 500}, {200, 700}, {0,700},{0,500}};
            POINT pRect3[5] = {{210,500}, {410, 500}, {410, 700}, {210,700},{210,500}};
            POINT pRect4[5] = {{420,500}, {620, 500}, {620, 700}, {420,700},{420,500}};
            POINT pRect5[5] = {{630,500}, {830, 500}, {830, 700}, {630,700},{630,500}};
            
            //For the white background
            RECT clientRect;
            HRGN hRegion1;
            HRGN hRegion2;
            HRGN hRegion3;
            HBRUSH hBGBrush;
            
            //Handle to a logical font
            HFONT hFont;

            //Get the caption font that is currently in use
            SystemParametersInfo(SPI_GETNONCLIENTMETRICS, NULL, &ncm, NULL);
            hFont = CreateFontIndirect(&ncm.lfCaptionFont);
            
            //Begin drawing
            hDC = BeginPaint(hWnd, &ps);

            //Draw and fill rectangles for the background
            GetClientRect(hWnd, &clientRect);
            hRegion1 = CreateRectRgn(clientRect.left,clientRect.top,clientRect.right,clientRect.bottom);
            hBGBrush = CreateSolidBrush(RGB(255,255,255));
            FillRgn(hDC, hRegion1, hBGBrush);
            
            //Create an HBITMAP(device dependent bitmap) to be drawn
            hBitmap = BitmapFromDIB(hDIB,NULL);
            //Draw the DDB
            DrawBitmap(hDC,0,0,hBitmap,SRCCOPY);
            
            
            if(hDIB)
            {
                hRegion2 = CreateRectRgn(401,0,clientRect.right,401);
                hRegion3 = CreateRectRgn(0,401,clientRect.right,clientRect.bottom);
                FillRgn(hDC,hRegion2,hBGBrush);
                FillRgn(hDC,hRegion3,hBGBrush);
                //Set stretch mode as BLACKONWHITE and then copy from the 
                //source rectangle into the smaller rectangle
                SetStretchBltMode(hDC,BLACKONWHITE);
                StretchBlt(hDC,0,500,200,200,hDC, 0,0,400,400,SRCCOPY);
            
                //Set stretch mode as WHITEONBLACK and then copy from the 
                //source rectangle into the smaller rectangle
                SetStretchBltMode(hDC,WHITEONBLACK);
                StretchBlt(hDC,210,500,200,200, hDC, 0,0,400,400, SRCCOPY);
            
                //Set stretch mode as COLORONCOLOR and then copy from the 
                //source rectangle into the smaller rectangle
                SetStretchBltMode(hDC,COLORONCOLOR);
                StretchBlt(hDC,420,500,200,200, hDC, 0,0,400,400, SRCCOPY);

                //Set stretch mode as HALFTONE and then copy from the 
                //source rectangle into the smaller rectangle
                SetStretchBltMode(hDC,HALFTONE);
                StretchBlt(hDC,630,500,200,200, hDC, 0,0,400,400, SRCCOPY);

            }
            //Select the caption font created earlier
            SelectObject(hDC,hFont);

            //Create captions for each demonstration of color loss modes
            TextOut(hDC,50,480,TEXT("BLACKONWHITE"),12);
            TextOut(hDC,250,480,TEXT("WHITEONBLACK"),12);
            TextOut(hDC,460,480,TEXT("COLORONCOLOR"),12);
            TextOut(hDC,680,480,TEXT("HALFTONE"),8);
            DeleteObject(hFont);

            //Selecting the stock object pen to draw with
            SelectObject(hDC, GetStockObject(DC_PEN));
            //The pen is gray
            SetDCPenColor(hDC, RGB(80,80,80));
            
            //Polylines are drawn from arrays of POINTs
            Polyline(hDC, pRect1, 5);
            Polyline(hDC, pRect2, 5);
            Polyline(hDC, pRect3, 5);
            Polyline(hDC, pRect4, 5);
            Polyline(hDC, pRect5, 5);
            
            FillRgn(hDC,hRegion2,hBGBrush);
            EndPaint(hWnd, &ps);
            
            break;
        }
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}