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
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
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.
# # #