RESOURCE-ONLY LIBRARIES

Any function in a dynamic link library that Windows programs or other libraries can use must be exported. However, a dynamic link library need not contain any exported functions. What would such a DLL contain? The answer is resources.

Let's say you're working on a Windows application that requires a number of bitmaps. Normally, you would list these in the resource script of the program and load them into memory with the LoadBitmap function. But perhaps you want to create several sets of bitmaps, each set customized for one of the major display adapters used with Windows. It would make most sense to store these different sets of bitmaps in different files, because a user would need only one set of bitmaps on the fixed disk. These files are resource-only libraries.

Figure 19-5 shows how to create a resource-only library file called BITLIB.DLL that contains nine bitmaps. The BITLIB.RC file lists all the separate bitmap files and assigns each one a number. To create BITLIB.DLL, you need nine bitmaps named BITMAP1.BMP, BITMAP2.BMP, and so forth. You can create these bitmaps in SDK Paint.

BITLIB.MAK

#----------------------

# BITLIB.MAK make file

#----------------------

bitlib.dll : bitlib.obj bitlib.def bitlib.res

link bitlib libentry, bitlib.dll /align:16, NUL, /nod sdllcew libw, bitlib

rc bitlib.res bitlib.dll

bitlib.obj : bitlib.c

cl -c -ASw -Gsw -Ow -W2 -Zp bitlib.c

bitlib.res : bitlib.rc

rc -r bitlib.rc

BITLIB.C

/*--------------------------------------------------------------

BITLIB.C -- Code entry point for BITLIB dynamic link library

(c) Charles Petzold, 1990

--------------------------------------------------------------*/

#include <windows.h>

int FAR PASCAL LibMain (HANDLE hInstance, WORD wDataSeg, WORD wHeapSize,

LPSTR lpszCmdLine)

{

if (wHeapSize > 0)

UnlockData (0) ;

return 1 ;

}

BITLIB.RC

/*---------------------------

BITLIB.RC resource script

---------------------------*/

1 BITMAP bitmap1.bmp

2 BITMAP bitmap2.bmp

3 BITMAP bitmap3.bmp

4 BITMAP bitmap4.bmp

5 BITMAP bitmap5.bmp

6 BITMAP bitmap6.bmp

7 BITMAP bitmap7.bmp

8 BITMAP bitmap8.bmp

9 BITMAP bitmap9.bmp

BITLIB.DEF

;-----------------------------------

; BITLIB.DEF module definition file

;-----------------------------------

LIBRARY BITLIB

DESCRIPTION 'Bitmap DLL for SHOWBIT.EXE'

EXETYPE WINDOWS

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD MOVEABLE SINGLE

The SHOWBIT program, shown in Figure 19-6, reads the bitmap resources from BITLIB and copies them to the clipboard. You can cycle through the bitmaps by pressing a key on the keyboard.

SHOWBIT.MAK

#-----------------------

# SHOWBIT.MAK make file

#-----------------------

showbit.exe : showbit.obj showbit.def

link showbit, /align:16, NUL, /nod slibcew libw, showbit

rc showbit.exe

showbit.obj : showbit.c

cl -c -Gsw -Ow -W2 -Zp showbit.c

SHOWBIT.C

/*-----------------------------------------------------------

SHOWBIT.C -- Shows bitmaps in BITLIB dynamic link library

(c) Charles Petzold, 1990

-----------------------------------------------------------*/

#include <windows.h>

long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,

LPSTR lpszCmdLine, int nCmdShow)

{

static char szAppName [] = "ShowBit" ;

HWND hwnd ;

MSG msg ;

WNDCLASS wndclass ;

if (!hPrevInstance)

{

wndclass.style = CS_HREDRAW | CS_VREDRAW ;

wndclass.lpfnWndProc = WndProc ;

wndclass.cbClsExtra = 0 ;

wndclass.cbWndExtra = 0 ;

wndclass.hInstance = hInstance ;

wndclass.hIcon = NULL ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;

wndclass.lpszMenuName = NULL ;

wndclass.lpszClassName = szAppName ;

RegisterClass (&wndclass) ;

}

hwnd = CreateWindow (szAppName, "Show Bitmaps from BITLIB (Press Key)",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd, nCmdShow) ;

UpdateWindow (hwnd) ;

while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

return msg.wParam ;

}

void DrawBitmap (HDC hdc, short xStart, short yStart, HBITMAP hBitmap)

{

BITMAP bm ;

DWORD dwSize ;

HDC hMemDC ;

POINT pt ;

hMemDC = CreateCompatibleDC (hdc) ;

SelectObject (hMemDC, hBitmap) ;

GetObject (hBitmap, sizeof (BITMAP), (LPSTR) &bm) ;

pt.x = bm.bmWidth ;

pt.y = bm.bmHeight ;

BitBlt (hdc, xStart, yStart, pt.x, pt.y, hMemDC, 0, 0, SRCCOPY) ;

DeleteDC (hMemDC) ;

}

long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)

{

static HANDLE hLibrary ;

static short nCurrent = 1 ;

HANDLE hBitmap ;

HDC hdc ;

PAINTSTRUCT ps ;

switch (message)

{

case WM_CREATE :

if ((hLibrary = LoadLibrary ("BITLIB.DLL")) < 32)

MessageBeep (0) ;

return 0 ;

case WM_CHAR :

if (hLibrary >= 32)

{

nCurrent ++ ;

InvalidateRect (hwnd, NULL, TRUE) ;

}

return 0 ;

case WM_PAINT :

hdc = BeginPaint (hwnd, &ps) ;

if (hLibrary >= 32)

{

if (NULL == (hBitmap = LoadBitmap (hLibrary,

MAKEINTRESOURCE (nCurrent))))

{

nCurrent = 1 ;

hBitmap = LoadBitmap (hLibrary,

MAKEINTRESOURCE (nCurrent)) ;

}

if (hBitmap)

DrawBitmap (hdc, 0, 0, hBitmap) ;

}

EndPaint (hwnd, &ps) ;

return 0 ;

case WM_DESTROY :

if (hLibrary >= 32)

FreeLibrary (hLibrary) ;

PostQuitMessage (0) ;

return 0 ;

}

return DefWindowProc (hwnd, message, wParam, lParam) ;

}

SHOWBIT.DEF

;------------------------------------

; SHOWBIT.DEF module definition file

;------------------------------------

NAME SHOWBIT

DESCRIPTION 'Program to show bitmaps from BITLIB (c) Charles Petzold, 1990'

EXETYPE WINDOWS

STUB 'WINSTUB.EXE'

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD MOVEABLE MULTIPLE

HEAPSIZE 1024

STACKSIZE 8192

EXPORTS WndProc

During processing of the WM_CREATE message, SHOWBIT gets a handle to BITLIB.DLL:

if ((hLibrary = LoadLibrary ("BITLIB.DLL")) < 32)

MessageBeep (0) ;

If BITLIB.DLL isn't in the current directory or in a directory accessible through the PATH string in the MS-DOS environment, Windows displays a message box asking the user to insert the BITLIB.DLL disk in drive A. If the user presses Cancel, LoadLibrary returns an MS-DOS error code (less than 32), in which case SHOWBIT simply beeps.

SHOWBIT can obtain a handle to a bitmap by calling LoadBitmap with the library handle and the number of the bitmap:

hBitmap = LoadBitmap (hLibrary, MAKEINTRESOURCE (nCurrent)) ;

This returns an error if the bitmap corresponding to the number nCurrent isn't valid or if not enough memory exists to load the bitmap.

While processing the WM_DESTROY message, SHOWBIT frees the library:

FreeLibrary (hLibrary) ;

When the last instance of SHOWBIT terminates, the reference count of BITLIB.DLL drops to 0 and the memory it occupies is freed. As you can see, this is a simple method of implementing a ”clip art“ program that could load precreated bitmaps (or metafiles) into the clipboard for use by other programs.