Windows NT Systems Programming: Spring 1999

[ Home | Syllabus | Course Notes | Assignments | Search]


Bitmaps


Using BitMaps

    CBitmap bitmap;
    BITMAP bm;
    CClientDC dc(this); // always and only attached to screen (frame buffer) bitmap
    CRect rect;
    CClientRect(&rect);
    bitmap.LoadBitmap(IDR_LOGOIMAGE); // load from "bmp" file identified in resource file
    bitmap.GetObject (sizeof (BITMAP), &bm); // get information on this bitmap
    CPoint size (bm.bmWidth, bm.bmHeight); // among which is width and height
    pDC->DPtoLP (&size); // to be sure convert to logical units

    CPoint org (0, 0);
    pDC->DPtoLP (&org);

    CDC dcMem; // memory device context for drawing on memory bitmap
    dcMem.CreateCompatibleDC (&dc); // make sure it is compatible with hardware device context
    dcMem.SelectObject (bitmap); // select bitmap into the memory device context
    dcMem.SetMapMode (dc.GetMapMode ()); // get compatible modes

    pDC->BitBlt (x, y, size.x, size.y, &dcMem, org.x, org.y, SRCCOPY); // transfer bitmap to screen

}

rainbow.gif (2243 bytes)


Device Independent Bitmaps (DIBs)


Drawing a BMP on the Screen.

int CMainWindow::OnCreate (LPCREATESTRUCT lpcs)
{
    if (CFrameWnd::OnCreate (lpcs) == -1)
        return -1;

    m_bitmap.LoadBitmap (IDR_BITMAP);
//....
    return 0;
}
void CMainWindow::OnPaint ()
{
    CRect rect;
    GetClientRect (&rect);
    CPaintDC dc (this);

    BITMAP bm;
    m_bitmap.GetObject (sizeof (BITMAP), &bm);
    int cx = (rect.Width () / (bm.bmWidth + 8)) + 1;
    int cy = (rect.Height () / (bm.bmHeight + 8)) + 1;

    int i, j, x, y;
    for (i=0; i<cx; i++) {
        for (j=0; j<cy; j++) {
            x = 8 + (i * (bm.bmWidth + 8));
            y = 8 + (j * (bm.bmHeight + 8));
            if (m_bDrawOpaque)
                m_bitmap.Draw (&dc, x, y);
            else
                m_bitmap.DrawTransparent (&dc, x, y, RGB (255, 0, 0));
        }
    }
}
void CMaskedBitmap::Draw (CDC* pDC, int x, int y)
{
    BITMAP bm;
    GetObject (sizeof (BITMAP), &bm);
    CPoint size (bm.bmWidth, bm.bmHeight);
    pDC->DPtoLP (&size);

    CPoint org (0, 0);
    pDC->DPtoLP (&org);

    CDC dcMem;
    dcMem.CreateCompatibleDC (pDC);
    CBitmap* pOldBitmap = dcMem.SelectObject (this);
    dcMem.SetMapMode (pDC->GetMapMode ());

    pDC->BitBlt (x, y, size.x, size.y, &dcMem, org.x, org.y, SRCCOPY);

    dcMem.SelectObject (pOldBitmap);
}

Having Fun with BitBLT

Problem: Let's use the transparent window to capture the desktop and then scramble it.

Need to Know: how to set a timer so we can scramble at a given pace.

Here is the header file.

//***********************************************************************
//
//  BitmapDemo.h
//
//***********************************************************************
const int FONTHEIGHT = 72;
class CMyApp : public CWinApp
{
public:
    virtual BOOL InitInstance ();
};


class CMainWindow : public CFrameWnd
{
private:
   void DoDrawText (CDC*, CRect*);
   void DoGradientFill (CDC*, CRect*);
   CBitmap m_bitmap;

public:
    CMainWindow ();
	
protected:
    afx_msg int OnCreate (LPCREATESTRUCT);
    afx_msg BOOL OnEraseBkgnd (CDC*);
    afx_msg void OnPaint ();
    afx_msg void OnTimer(UINT); // this controls the rate of scrambling
    afx_msg void OnOptionsExit ();

    DECLARE_MESSAGE_MAP ()
};
rainbow.gif (2243 bytes)
// here is the implementation file
//***********************************************************************
//
//  BitmapDemo.cpp
//
//***********************************************************************

#include <afxwin.h>
#include <stdlib.h>
#include "Resource.h"
#include "BitmapDemo.h"

CMyApp myApp;

/////////////////////////////////////////////////////////////////////////
// CMyApp member functions

BOOL CMyApp::InitInstance ()
{
    m_pMainWnd = new CMainWindow;
    m_pMainWnd->ShowWindow (m_nCmdShow);
    m_pMainWnd->UpdateWindow ();
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////
// CMainWindow message map and member functions

BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
    ON_WM_CREATE ()
    ON_WM_ERASEBKGND ()
    ON_WM_PAINT ()
    ON_WM_TIMER()
    ON_COMMAND (IDM_OPTIONS_EXIT, OnOptionsExit)
END_MESSAGE_MAP ()

CMainWindow::CMainWindow ()
{
  
    Create (NULL, "Bitmap Demo", WS_OVERLAPPEDWINDOW, rectDefault,
        NULL, MAKEINTRESOURCE (IDR_MAINFRAME));
}

int CMainWindow::OnCreate (LPCREATESTRUCT lpcs)
{
    if (CFrameWnd::OnCreate (lpcs) == -1)
        return -1;
    CClientDC dc (this);
    CRect rect;
    GetClientRect(&rect);
    
    srand(100); // initialize random number generator

    CDC dcMem;
    dcMem.CreateCompatibleDC(&dc);
    dcMem.SetMapMode(dc.GetMapMode());
    // create bitmap 1/100 the size of the main window
    // That is, divide the screen into 100 pieces
    m_bitmap.CreateCompatibleBitmap(&dc, rect.Width()/10, rect.Height()/10);
    SetTimer(ID_TIMER,100,NULL);	// sets timer for moving bitmap

    return 0;
}

BOOL CMainWindow::OnEraseBkgnd (CDC* pDC)
{
	return true; // transparent window

    CRect rect;
    GetClientRect (&rect);
    
    DoGradientFill (pDC, &rect);
    return TRUE;
}

// When painting, randomly swap two pieces of the main window
void CMainWindow::OnPaint ()
{
    CRect rect;
    GetClientRect (&rect);
    CPaintDC dc (this);

    BITMAP bm;
	
    m_bitmap.GetObject (sizeof (BITMAP), &bm);

    DoDrawText (&dc, &rect);

    CPoint size(bm.bmWidth,bm.bmHeight);
    CPoint org(0,0);
    dc.DPtoLP(&size);
    dc.DPtoLP(&org);
    // choose two pieces at random
    int x1 = size.x * (rand() % 10);
    int y1 = size.y * (rand() % 10);
    int x2 = size.x * (rand() % 10);
    int y2 = size.y * (rand() % 10);
    CPoint rect1(x1,y1);
    CPoint rect2(x2,y2);

    CDC dcMem; // temporary holding place for swap
    dcMem.CreateCompatibleDC(&dc);
    dcMem.SetMapMode(dc.GetMapMode());
    dcMem.SelectObject(m_bitmap);
    // BLT a piece of the main window from randomly chosen place
    dcMem.BitBlt(org.x,org.y,size.x,size.y,&dc,rect1.x,rect1.y,SRCCOPY);
    // move second piece to where first piece was
    dc.BitBlt(rect1.x,rect1.y,size.x,size.y,&dc,rect2.x,rect2.y,SRCCOPY);
    // move first piece to where second piece was
    dc.BitBlt(rect2.x,rect2.y,size.x,size.y,&dcMem,org.x,org.y,SRCCOPY);
	
}



void CMainWindow::OnOptionsExit ()
{
    SendMessage (WM_CLOSE, 0, 0);
}

void CMainWindow::OnTimer(UINT nTimerId)
{
	
	Invalidate();
}

void CMainWindow::DoDrawText (CDC* pDC, CRect* pRect)
{
    CFont font;
    int nHeight = -((pDC->GetDeviceCaps (LOGPIXELSY) * FONTHEIGHT) / 72);

    font.CreateFont (nHeight, 0, 0, 0, FW_BOLD, TRUE, 0, 0,
        DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
        DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Times New Roman");

    //pDC->SetBkMode (TRANSPARENT);
    pDC->SetBkColor(RGB(255,0,255));
    pDC->SetTextColor (RGB (255, 255, 255));
	
    CFont* pOldFont = pDC->SelectObject (&font);
    pDC->DrawText ("Hello, MFC", -1, pRect, DT_SINGLELINE | DT_CENTER |
        DT_VCENTER);

    pDC->SelectObject (pOldFont);
}

 


Experiments


Copyright chris wild 1999.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: April 13, 1999.