Mobile Using Bitmaps in WinCE Applications

Using Bitmaps in WinCE Applications

Bitmaps raise all sorts of porting issues: color depth, bitmap organization, size

translations, and CE support for ROP codes. We are going to start with a look at basic

bitmap raster operations under CE, using the functions BitBlt() and StretchBlt().

Figure 3 – The Dinner Example





Click here for larger image

Device Independent vs. Device Dependent Bitmaps

The real business of the Dinner example happens in the function MyPaint(). First,

we fill the client area with gray, because this makes the actions of the various ROP

codes more dramatic. /p>

hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rt);
FillRect( hdc, &rt, (HBRUSH)GetStockObject( GRAY_BRUSH ) );

Next, we create a compatible memory DC, load a bitmap image, select it into the

memory DC.

hdcMemory = CreateCompatibleDC( hdc );
hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_DINNER ));
SelectObject( hdcMemory, hBmp );
GetObject( hBmp, sizeof(BITMAP), &bmp );

Finally, use either BitBlt() or StretchBlt() to paint it on the screen.

if ( iZoomFactor == NORMAL )
{
  BitBlt(hdc, (GetSystemMetrics(SM_CXSCREEN ) / 10 ),
              (GetSystemMetrics(SM_CYSCREEN ) / 6 ),
              bmp.bmWidth, bmp.bmHeight,
              hdcMemory,
              0, 0, iROPCode );

if ( iZoomFactor == ENLARGE )
{
  StretchBlt(hdc, (GetSystemMetrics(SM_CXSCREEN ) / 10 ),
                  (GetSystemMetrics(SM_CYSCREEN ) / 6 ),
                  bmp.bmWidth * 2, bmp.bmHeight* 2,
                  hdcMemory,
                  0, 0, 
                  bmp.bmWidth, bmp.bmHeight,
                  iROPCode );
}

if ( iZoomFactor == SHRINK )
{
  StretchBlt(hdc, (GetSystemMetrics(SM_CXSCREEN ) / 10 ),
                  (GetSystemMetrics(SM_CYSCREEN ) / 6 ),
                  bmp.bmWidth / 2, bmp.bmHeight / 2,
                  hdcMemory,
                  0, 0, 
                  bmp.bmWidth, bmp.bmHeight,
                  iROPCode );
}

This drawing code is 100% identical on Win 32 and Win CE, but it relies on one

pivotal assumption — it assumes that the CE device is capable of displaying the

device dependent bitmap identified by IDB_DINNER. As it turns out, this is a safe

assumption, and we see, voila, dinner.

This example introduces some of the larger issues of porting graphics to CE, to

wit, that getting a graphics application up on CE may well involve modifying data as

well as code.

Porting Tip: Porting graphics applications may require more modification

of graphics data than code.

We saw in the EtchASketch example that in order to draw a line, you must explicitly

supply its initial point. Now with bitmaps, we are confronted with another such

consideration: possible differences in color depth between a bitmap and a display

device. On the one hand device dependent bitmaps, are compact, ubiquitous, and

require very little coding to manipulate. On the other, you run a risk using device

dependent bitmaps that a device can’t handle them — possibly with catastrophic

results. There are two alternatives.

  • Use DDBs carefully and intelligently, limiting the risks involved.
  • Use DIBs, which are universally compatible, at the cost of a great deal more code

    and data

You probably already know which alternative I favor. If you can live with 16 color

or grayscale bitmaps, you will vastly reduce the effort of porting bitmap code.

Simply opening the bitmaps in a graphics application and saving them as 16 color or 4

bit gray scale format may allow you device dependent bitmap code to port to Win32

unchanged.

Your safety net on the CE side is provided by the GetDeviceCaps() function:

int GetDeviceCaps(HDC hdc, int nIndex);

The parameters, in the order shown, are the handle to the display context and a

constant identifying the device property you are querying. To find out how many colors

a device supports, use GetDeviceCaps() like this :

int iNumColors;

//Get the number of colors the device can display
iNumColors = GetDeviceCaps(hdc, NUMCOLORS );

if ( (iNumColors => 16) || (iNumColors == -1) )
{
   //safely use grayscale or 16 color DDBs
}

GetDeviceCaps() returns the number of colors the device can display if color depth

is 8 bits or less. If more than 8 bits are used to identify a color, then the

function returns -1.

Looking Ahead

In the next installment, we’ll examine techniques for making bitmap backgrounds

transparent. Transparent backgrounds allow bitmapped images to be layered and

seamlessly collaged.

About the Author

Nancy Nicolaisen is a software engineer who has designed and

implemented highly modular Windows CE products that include features such as full

remote diagnostics, CE-side data compression, dynamically constructed user interface,

automatic screen size detection, entry time data validation.

In addition to writing for Developer.com, she has written several books including

Making Win 32

Applications Mobile. She has also written numerous articles on programming

technology for national publications including Dr. Dobbs, BYTE Magazine, Microsoft

Systems Journal, PC Magazine; Computer Shopper, Windows Sources and Databased

Advisor.

# # #

Latest Posts

Related Stories