| Tenouk C & C++ | MFC Home | Bitmaps 3 | Bitmaps 5 | Download | Site Index |


 

 

 

 

 

 

Module 21c: The Bitmaps 4

 

 

 

 

 

 

This is a continuation from the previous module... Program examples compiled using Visual C++ 6.0 (MFC 6.0) compiler on Windows XP Pro machine with Service Pack 2. Topics and sub topics for this Tutorial are listed below:

  1. The CDib Class ...a continuation...

  2. DIB Display Performance

  3. The MYMFC26C Example

 

Here's a rundown of the CDib member functions, starting with the constructors and the destructor:

  • Default constructor: You'll use the default constructor in preparation for loading a DIB from a file or for attaching to a DIB in memory. The default constructor creates an empty DIB object.

  • DIB section constructor: If you need a DIB section that is created by the CreateDIBSection() function, use this constructor. Its parameters determine DIB size and number of colors. The constructor allocates info header memory but not image memory. You can also use this constructor if you need to allocate your own image memory.

Parameter

Description

size

CSize object that contains the width and height of the DIB.

nBitCount

Bits per pixel; should be 1, 4, 8, 16, 24, or 32.

 

Table 1.

  • Destructor: The CDib destructor frees all allocated DIB memory.

  • AttachMapFile(): This function opens a memory-mapped file in read mode and attaches it to the CDib object. The return is immediate because the file isn't actually read into memory until it is used. When you access the DIB, however, a delay might occur as the file is paged in. The AttachMapFile() function releases existing allocated memory and closes any previously attached memory-mapped file.

 

Parameter

Description

strPathname

Pathname of the file to be mapped.

bShare

Flag that is TRUE if the file is to be opened in share mode; the default value is FALSE.

Return value

TRUE if successful.

 

Table 2

  • AttachMemory(): This function associates an existing CDib object with a DIB in memory. This memory could be in the program's resources, or it could be clipboard or OLE data object memory. Memory might have been allocated from the CRT heap with the new operator, or it might have been allocated from the Windows heap with GlobalAlloc().

 

 

Parameter

Description

lpvMem

Address of the memory to be attached.

bMustDelete

Flag that is TRUE if the CDib class is responsible for deleting this memory; the default value is FALSE.

hGlobal

If memory was obtained with a call to the Win32 GlobalAlloc() function, the CDib object needs to keep the handle in order to free it later, assuming that bMustDelete was set to TRUE.

Return value

TRUE if successful.

 

Table 3.

Parameter

Description

pDC

Pointer to the display device context.

bCompress

TRUE (default) to compress the DIB; FALSE to uncompress it.

Return value

TRUE if successful.

 

Table 4.

Parameter

Description

strPathname

Pathname of the file to be mapped.

Return value

TRUE if successful.

 

Table 5.

Parameter

Description

pDC

Pointer to the display or printer device context.

Return value

Handle to a GDI bitmap, NULL if unsuccessful. This handle is not stored as a public data member.

 

Table 6.

Parameter

Description

pDC

Pointer to the display or printer device context.

Return value

Handle to a GDI bitmap, NULL if unsuccessful. This handle is also stored as a public data member.

 

Table 7.

Parameter

Description

pDC

Pointer to the display or printer device context that will receive the DIB image.

origin

CPoint object that holds the logical coordinates at which the DIB will be displayed.

size

CSize object that represents the display rectangle's width and height in logical units.

Return value

TRUE if successful.

 

Table 8.

Parameter

Description

Return value

CSize object

 

Table 9.

Parameter

Description

Return value

32-bit integer

 

Table 10.

Parameter

Description

Return value

32-bit integer

 

Table 11.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Parameter

Description

Return value

TRUE if successful

 

Table 12.

Parameter

Description

pFile

Pointer to a CFile object; the corresponding disk file contains the DIB.

Return value

TRUE if successful.

 

Table 13.

Parameter

Description

pFile

Pointer to a CFile object; the corresponding disk file contains the DIB.

pDC

Pointer to the display or printer device context.

Return value

TRUE if successful.

 

Table 14.

Parameter

Description

pDC

Pointer to the display context.

Return value

TRUE if successful.

 

Table 15.

Parameter

Description

pDC

Pointer to the display device context for realization.

bBackground

If this flag is FALSE (the default value) and the application is running in the foreground, Windows realizes the palette as the foreground palette (copies as many colors as possible into the system palette). If this flag is TRUE, Windows realizes the palette as a background palette (maps the logical palette to the system palette as best it can).

Return value

Number of entries in the logical palette mapped to the system palette. If the function fails, the return value is GDI_ERROR.

 

Table 16.

Parameter

Description

pFile

Pointer to a CFile object; the DIB will be written to the corresponding disk file.

Return value

TRUE if successful.

 

Table 17.

 

For your convenience, four public data members give you access to the DIB memory and to the DIB section handle. These members should give you a clue about the structure of a CDib object. A CDib is just a bunch of pointers to heap memory. That memory might be owned by the DIB or by someone else. Additional private data members determine whether the CDib class frees the memory.

 

DIB Display Performance

 

Optimized DIB processing is now a major feature of Windows. Modern video cards have frame buffers that conform to the standard DIB image format. If you have one of these cards, your programs can take advantage of the new Windows DIB engine, which speeds up the process of drawing directly from DIBs. If you're still running in VGA mode, however, you're out of luck; your programs will still work, but not as fast.

If you're running Windows in 256-color mode, your 8-bpp bitmaps will be drawn very quickly, either with StretchBlt() or with StretchDIBits(). If, however, you are displaying 16-bpp or 24-bpp bitmaps, those drawing functions will be too slow. Your bitmaps will appear more quickly in this situation if you create a separate 8-bbp GDI bitmap and then call StretchBlt(). Of course, you must be careful to realize the correct palette prior to creating the bitmap and prior to drawing it.

 

Here's some code that you might insert just after loading your CDib object from a BMP file:

 

// m_hBitmap is a data member of type HBITMAP

// m_dcMem is a memory device context object of class CDC

m_pDib->UsePalette(&dc);

m_hBitmap = m_pDib->CreateBitmap(&dc); // could be slow

::SelectObject(m_dcMem.GetSafeHdc(), m_hBitmap);

Here is the code that you use in place of CDib::Draw in your view's OnDraw member function:

m_pDib->UsePalette(pDC); // could be in palette msg handler

CSize sizeDib = m_pDib->GetDimensions();

pDC->StretchBlt(0, 0, sizeDib.cx, sizeDib.cy, &m_dcMem, 0, 0, sizeToDraw.cx, sizeToDraw.cy, SRCCOPY);

 

Don't forget to call DeleteObject() for m_hBitmap when you're done with it.

 

The MYMFC26C Example

 

Now you'll put the CDib class to work in an application. The MYMFC26C program displays two DIBs, one from a resource and the other loaded from a BMP file that you select at runtime. The program manages the system palette and displays the DIBs correctly on the printer. Compare the MYMFC26C code with the GDI bitmap code in MYMFC26A. Notice that you're not dealing with a memory device context and all the GDI selection rules! Following are the steps to build MYMFC26C.

 

Run AppWizard to produce \mfcproject\mymfc26C. Accept all the defaults but two: select Single Document and select the CScrollView view base class for CMymfc26CView in step 6. The options and the default class names are shown here.

 

MYMFC26C project summary.

 

Figure 16: MYMFC26C project summary.

 

Import the Soap Bubbles bitmap. Choose Resource from Visual C++'s Insert menu. Import Soap Bubbles.bmp from the \WINDOWS directory.

 

Importing Soap Bubbles.bmp into MYMFC26C project.

 

Figure 17: Importing Soap Bubbles.bmp into MYMFC26C project.

 

Visual C++ will copy this bitmap file into your project's \res subdirectory. Assign IDB_SOAPBUBBLE as the ID, and save the changes.

 

Modifying bitmap properties.

 

Figure 18: Modifying bitmap properties.

 

Integrate the CDib class with this project. If you've created this project from scratch, copy the cdib.h and cdib.cpp files to the \mfcproject\mymfc26C directory. Simply copying the files to disk isn't enough; you must also add the CDib files to the project. Choose Add To Project from Visual C++'s Project menu, and then choose Files. Select cdib.h and cdib.cpp, and click the OK button. If you now switch to ClassView in the Workspace window, you will see the class CDib and all of its member variables and functions.

 

 

Adding header and source files (class) to the project.

 

Figure 19: Adding header and source files (class) to the project.

 

Add two private CDib data members to the class CMymfc26CView. In the ClassView window, right-click the CMymfc26CView class. Choose Add Member Variable from the resulting pop-up menu, and then add the m_dibResource member as shown in the following illustration.

 

Adding private CDib type data members to the class CMymfc26CView.

 

Figure 20: Adding private CDib type data members to the class CMymfc26CView.

 

Add m_dibFile in the same way. The result should be two data members at the bottom of the header file as shown below:

 

CDib m_dibFile;

CDib m_dibResource;

 

MFC code segment snapshot

 

Listing 16.

 

ClassView also adds the #include statement at the top of the mymfc26CView.h file:

 

#include "cdib.h"   // Added by ClassView

 

MFC code segment snapshot

 

Listing 17.

 

Edit the OnInitialUpdate() member function in mymfc26CView.cpp. This function sets the mapping mode to MM_HIMETRIC and loads the m_dibResource object directly from the IDB_REDBLOCKS resource. Note that we're not calling LoadBitmap() to load a GDI bitmap as we did in MYMFC26A. The CDib::AttachMemory function connects the object to the resource in your EXE file. Add the following code:

 

void CMymfc26CView::OnInitialUpdate()

{

    CScrollView::OnInitialUpdate();

    CSize sizeTotal(30000, 40000); // 30-by-40 cm

    CSize sizeLine = CSize(sizeTotal.cx / 100, sizeTotal.cy / 100);

    SetScrollSizes(MM_HIMETRIC, sizeTotal, sizeTotal, sizeLine);

 

    LPVOID lpvResource = (LPVOID) ::LoadResource(NULL,

        ::FindResource(NULL, MAKEINTRESOURCE(IDB_SOAPBUBBLE), RT_BITMAP));

    m_dibResource.AttachMemory(lpvResource); // no need for ::LockResource

    CClientDC dc(this);

    TRACE("bits per pixel = %d\n", dc.GetDeviceCaps(BITSPIXEL));

}

 

 

MFC code segment snapshot

 

Listing 18.

 

Edit the OnDraw() member function in the file mymfc26CView.cpp. This code calls CDib::Draw for each of the DIBs. The UsePalette() calls should really be made by message handlers for the WM_QUERYNEWPALETTE and WM_PALETTECHANGED messages. These messages are hard to deal with because they don't go to the view directly, so we'll take a shortcut. Add the following code:

 

void CMymfc26CView::OnDraw(CDC* pDC)

{

    BeginWaitCursor();

    m_dibResource.UsePalette(pDC); // should be in palette

    m_dibFile.UsePalette(pDC);     //  message handlers, not here

    pDC->TextOut(0, 0,

        "Press the left mouse button here to load a file.");

    CSize sizeResourceDib = m_dibResource.GetDimensions();

    sizeResourceDib.cx *= 30;

    sizeResourceDib.cy *= -30;

    m_dibResource.Draw(pDC, CPoint(0, -800), sizeResourceDib);

    CSize sizeFileDib = m_dibFile.GetDimensions();

    sizeFileDib.cx *= 30;

    sizeFileDib.cy *= -30;

    m_dibFile.Draw(pDC, CPoint(1800, -800), sizeFileDib);

    EndWaitCursor();

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

---------------------------------------------------------------------------------------------------------------------------------------------------------

MFC code segment snapshot

 

Listing 19.

 

Map the WM_LBUTTONDOWN message in the CMymfc26CView class. Edit the file mymfc26CView.cpp. OnLButtonDown() contains code to read a DIB in two different ways. If you leave the MEMORY_MAPPED_FILES definition intact, the AttachMapFile() code is activated to read a memory-mapped file. If you comment out the first line, the Read() call is activated. The SetSystemPalette() call is there for DIBs that don't have a color table.

 

Mapping the WM_LBUTTONDOWN message in the CMymfc26CView class for left mouse button click.

 

Figure 21: Mapping the WM_LBUTTONDOWN message in the CMymfc26CView class for left mouse button click.

 

Then, add the following code:

 

#define MEMORY_MAPPED_FILES

 

void CMymfc26CView::OnLButtonDown(UINT nFlags, CPoint point)

{

    CFileDialog dlg(TRUE, "bmp", "*.bmp");

    if (dlg.DoModal() != IDOK) {

        return;

    }

 

#ifdef MEMORY_MAPPED_FILES

    if (m_dibFile.AttachMapFile(dlg.GetPathName(),

            TRUE) == TRUE) { // share

        Invalidate();

    }

 #else

    CFile file;

    file.Open(dlg.GetPathName(), CFile::modeRead);

    if (m_dibFile.Read(&file) == TRUE) {

        Invalidate();

    }

#endif // MEMORY_MAPPED_FILES

    CClientDC dc(this);

    m_dibFile.SetSystemPalette(&dc);

}

 

MFC code segment snapshot

 

Listing 20.

 

Build and run the application. Try some other BMP files if you have them. Note that Soap Bubbles is a 16-color DIB that uses standard colors, which are always included in the system palette.

 

MYMFC26C program output.

 

Figure 22: MYMFC26C program output.

 

 

Continue on next module...part 5.

 

 

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

  1. MSDN MFC 7.0 class library online documentation.

  2. MSDN MFC 9.0 class library online documentation - latest version.

  3. MSDN Library

  4. Windows data type.

  5. Win32 programming Tutorial.

  6. The best of C/C++, MFC, Windows and other related books.

  7. Unicode and Multibyte character set: Story and program examples.

 

 


 

| Tenouk C & C++ | MFC Home | Bitmaps 3 | Bitmaps 5 | Download | Site Index |