纯资源链接库(位图)
-----Amoon 2005.09.23
关于纯资源动态链接库
可由Windows程序或其它链接库使用的动态链接库中的任何函 数都必须被输出。然而,DLL也可以不包含任何输出函数。那么,DLL到 底包含什么呢?答案是资源。
纯资源的DLL就是只包含资源的DLL,例如:图标,位图,字符 串,声音,视频,对话框等。使用纯资源DLL可以节约可执行文件的大 小,可以被所有的应用程序所共享,从而提高系统性能。纯资源DLL的 编写比普通的DLL要简单的多,首先创建一个WIN32 DLL工程,不是MFC 的DLL,然后创建一个资源文件 *.RC,添加到资源DLL的工程中去。然 后添加一个初始化DLL的原文件。
#include <windows.h>
extern "C"
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason,
LPVOID )
{
return 1;
}
这是纯资源DLL所必须需的代码,保存这个文件为*.CPP。编译这个资源 DLL。
在应用程序显示的调用这个DLL,使用LoadLibrary函数装入资源DLL, FindResource和LoadResource来装入各种资源,或者使用下列的特定的 资源装入函数:
FormatMessage
LoadAccelerators
LoadBitmap
LoadCursor
LoadIcon
LoadMenu
LoadString
当资源使用结束,你的应用程序须调用FreeLibrary函数来释放资源。
一个例子:
假设使用者正在使用需要几幅位图的Windows应用程序进行工作。 通常要在程序的资源描述文件中列出资源,并用LoadBitmap函数把它们 加载内存。但使用者可能希望建立若干套位图,每一套均适用于Windows所使用的不同显示卡。将不同套的位图存放到不同文件中可能 是明智的,因为只需要在硬盘上保留一套位图。这些文件就是纯资源文 件。
程序说明如何建立包含9幅位图的名为Bitmapdll.DLL的纯资源链接库文 件。为了建Bitmapdll.DLL,需要9幅名为b1.bmp,b2.bmp等等的位图 。可以使用Visual C++中建立这些位图。点击file---new--- 选择file 标签---Bitmap File。
(一) 创建Bitmapdll
1)首先创建一个空的WIN32 DLL(Win32 Dynamic-Link Library) 工程。命名为Bitmapdll。
2)新建C++文件。Bitmapdll.cpp.输入:
#include <windows.h>
int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason,
PVOID pvReserved)
{
return TRUE ;
}
3)新建位图。
使用Visual C++中建立这些位图。点击file---new--- 选择 file标签---Bitmap File。依次新建名为b1.bmp----b9.bmp 9幅位图 。(自己画,或者新建b*.bmp后用自己的位图覆盖之)
4)新建Resource Script 文件(名为Bitmpap.rc) 。 用记事本打开Bitmap.rc. 修改成如下形式:其中大部分代码 是自动生成的。
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
//////////////////////////////////////////////////////////////
///////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
//////////////////////////////////////////////////////////////
///////////////
#undef APSTUDIO_READONLY_SYMBOLS
//////////////////////////////////////////////////////////////
///////////////
// Chinese (P.R.C.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
//////////////////////////////////////////////////////////////
///////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
1 BITMAP DISCARDABLE "b1.bmp"
2 BITMAP DISCARDABLE "b2.bmp"
3 BITMAP DISCARDABLE "b3.bmp"
4 BITMAP DISCARDABLE "b4.bmp"
5 BITMAP DISCARDABLE "b5.bmp"
6 BITMAP DISCARDABLE "b6.bmp"
7 BITMAP DISCARDABLE "b7.bmp"
8 BITMAP DISCARDABLE "b8.bmp"
9 BITMAP DISCARDABLE "b9.bmp"
#endif // Chinese (P.R.C.) resources
//////////////////////////////////////////////////////////////
///////////////
#ifndef APSTUDIO_INVOKED
//////////////////////////////////////////////////////////////
///////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
//////////////////////////////////////////////////////////////
///////////////
#endif // not APSTUDIO_INVOKED
5)编译后即可得Bitmapdll.dll . ( ok,that's all ^_^ )
(二) 接下来创建测试程序:
1)新建一个名为 TestBitmapdll 的单文档工程。
2)在 *View.h 中添加如下变量及函数:
public:
int iCur;
HINSTANCE hLibrary ;
HBITMAP hBitmap ;
HDC hdc ;
PAINTSTRUCT ps ;
void DrawBitmap(HDC hdc, int xStart, int yStart,
HBITMAP hBitmap);
接下来,在*View.cpp 文件中添加 DrawBitmap 的实现代码如 下:
void CTestBitmapDllView::DrawBitmap(HDC hdc, int xStart, int
yStart, HBITMAP hBitmap)
{
BITMAP bm ;
HDC hMemDC ;
POINT pt ;
hMemDC = CreateCompatibleDC (hdc) ;
SelectObject (hMemDC, hBitmap) ;
GetObject (hBitmap, sizeof (BITMAP), &bm) ;
pt.x = bm.bmWidth ;
pt.y = bm.bmHeight ;
BitBlt (hdc, xStart, yStart, pt.x, pt.y, hMemDC, 0, 0,
SRCCOPY) ;
DeleteDC (hMemDC) ;
}
3)在类向导中为 *View 添加 消息函数: Create。编写代码使之 具有如下形式:
BOOL CTestBitmapDllView::Create(LPCTSTR lpszClassName, LPCTSTR
lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd*
pParentWnd, UINT nID, CCreateContext* pContext)
{
// TODO: Add your specialized code here and/or call
the base class
if ((hLibrary = LoadLibrary (TEXT ("Bitmapdll.dll")))
== NULL)
{
MessageBox ("Can't load Bitmapdll.dll.");
}
return CWnd::Create(lpszClassName, lpszWindowName,
dwStyle, rect, pParentWnd, nID, pContext);
}
4)在类向导中为 *View 添加 消息函数: DestoryWindow。编写代码 使之具有如下形式:
BOOL CTestBitmapDllView::DestroyWindow()
{
// TODO: Add your specialized code here and/or call
the base class
if (hLibrary)
FreeLibrary (hLibrary) ;
return CView::DestroyWindow();
}
5)修改* View.cpp 中的 OnDraw() 函数代码如下所示:
void CTestBitmapDllView::OnDraw(CDC* pDC)
{
CTestBitmapDllDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
hdc=pDC->GetSafeHdc();
hBitmap = LoadBitmap (hLibrary, MAKEINTRESOURCE
(iCur)) ;
if (!hBitmap)
{
iCur = 1 ;
hBitmap = LoadBitmap (hLibrary,MAKEINTRESOURCE (iCur))
;
}
if (hBitmap)
{
DrawBitmap (hdc, 0, 0, hBitmap) ;
DeleteObject (hBitmap) ;
}
}
6)将Bitmapdll.dll复制到此工程的 TestBitmap.exe 文件所在的目 录下。然后编译运行此程序。按任意键即可在9幅位图之间得到切换。
( 三 ) 关于测试程序的一点说明:
1)在处理WM_CREATE消息处理期间,获得了 Bitmapdll.dll 的句柄:
if ((hLibrary = LoadLibrary (TEXT ("Bitmapdll.dll"))) == NULL)
2)测试程序透过链接库句柄和位图号码来呼叫LoadBitmap,从而得到 一个位图句柄:
hBitmap = LoadBitmap (hLibrary, MAKEINTRESOURCE (iCur)) ;
如果号码iCurrent对应的位图无效或者没有足够的内存加载位图,则传 回一个错误。
3)在 DestoryWindow 函数中,测试程序释放链接库:
FreeLibrary (hLibrary) ;
4)当测试程序的最后一个执行实体终止时,Bitmapdll.dll的引用计数 变为0,并且释放所占用的内存。这就是实作「图片剪辑」程序的一种 简单方法,所谓的「图片剪辑」程序就是能够将预先建立的位图(或者 etafile、增强型metafile)加载到剪贴簿,以供其它程序使用的程序 。
参考:《windows 程序设计》