Поделиться через


Масштабирование изображения

Некоторые приложения масштабировать изображения; то есть они отображают увеличенные или уменьшенные представления изображения. Например, приложение для рисования может предоставить функцию масштабирования, которая позволяет пользователю просматривать и редактировать рисунок в пикселях.

Приложения масштабировать изображения путем вызова функции StretchBlt . Как и функция BitBlt , StretchBlt копирует данные растрового изображения из растрового изображения в контексте исходного устройства (DC) в растровое изображение в целевом контроллере домена. Однако, в отличие от функции BitBlt , StretchBlt масштабирует изображение на основе заданных размеров исходного и целевого прямоугольников. Если исходный прямоугольник больше целевого прямоугольника, результирующий рисунок будет сжат; Если исходный прямоугольник меньше целевого прямоугольника, результирующий рисунок будет выглядеть развернутым.

Если целевой прямоугольник меньше исходного прямоугольника, StretchBlt удаляет данные цвета с изображения в соответствии с заданным режимом растяжения, как показано в следующей таблице.

Режим растяжения Метод
BLACKONWHITE Выполняет логическую операцию AND с данными цвета для исключенных пикселей и цветными данными для оставшихся пикселей.
WHITEONBLACK Выполняет логическую операцию OR с данными цвета для исключенных пикселей и цветными данными для оставшихся пикселей.
COLORONCOLOR Полностью удаляет данные цвета удаленных пикселей.
ПОЛУТОНАХ Приблизительный исходный (исходный) цвет данных в назначении.

 

Режим растяжения можно задать, вызвав функцию SetStretchBltMode .

Следующий пример кода взят из приложения, которое демонстрирует все четыре режима растяжения, доступные с помощью функции 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;
}