/************************************************************************/
/* resDef.h
/* 资源DLL提供给外部使用的头文件
/* nick
/* 4-10-2009
/************************************************************************/
#pragma once
//位图ID定义
#define IDB_BITMAP1 0
#define IDB_BITMAP2 1
#define IDB_BITMAP3 2
#define IDB_BITMAP4 3
#define IDB_BITMAP5 4
#define IDB_BITMAP6 5
#define IDB_BITMAP7 6
#define MAX_BITMAP_WIDTH 1000
#define MAX_BITMAP_HEIGHT 900
#define PIX_BIT 16
//实际位图的大小不应该大小MAX_BMP_SIZE,否则显示将不正常
#define MAX_BMP_SIZE MAX_BITMAP_WIDTH*MAX_BITMAP_HEIGHT*(PIX_BIT>>3)
//位图结构体定义
typedef struct{
LONG bmWidth;
LONG bmHeight;
WORD bmBitsPixel;
DWORD bmSize;
BYTE bits[MAX_BMP_SIZE];
}rgbBITMAP;
==========================================================End
//DllDef.h 头文件,DLL内部使用
#pragma once
#include "resDef.h"
#define DEBUG_DLL 1
#define MAX_BITMAPS 7
#define ALL_MEM_ALLOCATED
//内存映射的文件名
#define lpResourceFileMapName L"ResourceShared"
//图片的长宽
#define DEFAULT_WIDTH 800
#define DEFAULT_HEIGHT 480
//图片与应用程序启动路径的相对位置
#define BITMAP1_PATH L"images//BITMAP1.rgb"
#define BITMAP2_PATH L"images//BITMAP2.rgb"
#define BITMAP3_PATH L"images//BITMAP3.rgb"
#define BITMAP4_PATH L"images//BITMAP4.rgb"
#define BITMAP5_PATH L"images//BITMAP5.rgb"
#define BITMAP6_PATH L"images//BITMAP6.rgb"
#define BITMAP7_PATH L"images//BITMAP7.rgb"
//图片的长宽
#define BITMAP1_WIDTH DEFAULT_WIDTH
#define BITMAP1_HEIGHT DEFAULT_HEIGHT
#define BITMAP2_WIDTH 808
#define BITMAP2_HEIGHT 461
#define BITMAP3_WIDTH 722
#define BITMAP3_HEIGHT 505
#define BITMAP4_WIDTH DEFAULT_WIDTH
#define BITMAP4_HEIGHT DEFAULT_HEIGHT
#define BITMAP5_WIDTH DEFAULT_WIDTH
#define BITMAP5_HEIGHT DEFAULT_HEIGHT
#define BITMAP6_WIDTH 1290
#define BITMAP6_HEIGHT 535
#define BITMAP7_WIDTH 1290
#define BITMAP7_HEIGHT 535
//图片的信息,包括长宽和路径
typedef struct{
LONG width;
LONG height;
LPTSTR path;
HANDLE handle;
} FILE_INFO;
//内存映射文件结构体定义
typedef struct{
rgbBITMAP hResBitmap[MAX_BITMAPS];
} RESOURCE_BITMAP, *PRESOURCE_BITMAP;
=======================================================End
//resDll.h DLL接口头文件
#ifdef COMMDRAW_EXPORTS
#define COMMDRAW_API __declspec(dllimport)
#else
#define COMMDRAW_API __declspec(dllexport)
#endif
extern "C" COMMDRAW_API HANDLE GetBitmapResourceFile( int resID );
=======================================================End
//resDll.cpp DLL的代码文件
//
#include "stdafx.h"
#include "DllDef.h"
#include "resDll.h"
//共享bDllInit变量,以便在所有模块加载本DLL时可以共享此变量,以判断在此之前是否DLL已被初始化
#pragma data_seg(".Shared")
BOOL bDllInit = TRUE;
PRESOURCE_BITMAP m_bitmapRes =NULL;
#pragma data_seg()
#pragma comment(linker,"/SECTION:.Shared,RWS")
//函数申明
BOOL CreateMapFile();
BOOL CloseMapFile();
BOOL LoadResource();
rgbBITMAP *OpenResourceMapFile( int resID );
BOOL CloseResourceMapFile();
//变量定义
#ifdef ALL_MEM_ALLOCATED
PRESOURCE_BITMAP resFile = NULL;
#else
rgbBITMAP *resFile = NULL;
#endif
HANDLE hResourceMap = NULL;
HANDLE hMap = NULL;
//DLL入口
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
//如果DLL第一次被加载,则初始化共享内存和加载图片资源
if( bDllInit )
{
LoadResource();
bDllInit = FALSE;
}
else
{
#ifdef ALL_MEM_ALLOCATED
//加载共享内存到本地进程中
OpenResourceMapFile( 0 );
#endif
}
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
{
//此DLL被设计为永远不会释放
//CloseMapFile();
#ifdef ALL_MEM_ALLOCATED
//释放本地进程中的内存拷贝
CloseResourceMapFile();
#endif
RETAILMSG(DEBUG_DLL,(L"[resDll]: DLL_PROCESS_DETACH /r/n"));
}
break;
}
return TRUE;
}
/************************************************************************/
/* 获取右边"/"之前的字符长度 */
/************************************************************************/
UINT8 SrightNo(WCHAR* Firststr,WCHAR c)
{
int i,len;
len=wcslen(Firststr);
for(i=len-1; i>0; i--)
{
if(*(Firststr+i) == c)
return i;
}
return 0;
}
/************************************************************************/
/* 获取调用DLL的程序启动路径 */
/************************************************************************/
TCHAR* GetModulePath( TCHAR* filePath)
{
TCHAR temp[MAX_PATH];
GetModuleFileName(NULL,temp,MAX_PATH);
wcsncpy(filePath,temp,SrightNo(temp,'//')+1);
return filePath;
}
/************************************************************************/
/* 加载图片资源,并初始化内存共享数据 */
/************************************************************************/
BOOL LoadResource()
{
//只加载一次资源
if( hMap != NULL )
return TRUE;
RETAILMSG(DEBUG_DLL,(TEXT("[resDll]: start loading bitmap resource..../r/n")));
if( CreateMapFile() )
{
//映射需要共享的模块数据到数组内,以便下面读文件
FILE_INFO fileInfo[MAX_BITMAPS] =
{
{
BITMAP1_WIDTH,BITMAP1_HEIGHT,BITMAP1_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP1])
}
,
{
BITMAP2_BITMAP_WIDTH,BITMAP2_BITMAP_HEIGHT,BITMAP2_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP2])
}
,
{
BITMAP3_WIDTH,BITMAP3_HEIGHT,COMM_CLOCK_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP3])
}
,
{
BITMAP4_WIDTH,BITMAP4_HEIGHT,BT01_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP4])
}
,
{
BITMAP5_WIDTH,BITMAP5_HEIGHT,BTT_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP5])
}
,
{
BITMAP6_WIDTH,BITMAP6_HEIGHT,BTT_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP6])
}
,
{
BITMAP6_WIDTH,BITMAP6_HEIGHT,BTT_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP6])
}
};
DWORD dwLength =0;
FILE *mStream =NULL;
TCHAR tempPath[MAX_PATH] ={0};
TCHAR filePath[MAX_PATH] ={0};
GetModulePath(tempPath);
wcscpy(filePath,tempPath);
rgbBITMAP * pBitmap =NULL;
int i=0;
for( i; i< MAX_BITMAPS; i++ )
{
memset(tempPath,0,MAX_PATH);
wcscpy(tempPath,filePath);
wcscat(tempPath, fileInfo[i].path);
if((mStream = _wfopen(tempPath, L"rb")))
{
//获得文件的长度
fseek(mStream, 0, SEEK_END); //文件指针移动到最后
dwLength = ftell( mStream ); //获得文件字节数
fseek(mStream, 0, SEEK_SET); //文件指针移动到开始
pBitmap = (rgbBITMAP*)fileInfo[i].handle;
//写入BUFFER的实际长度
pBitmap->bmSize = min(MAX_BMP_SIZE, dwLength);
pBitmap->bmBitsPixel = PIX_BIT;
pBitmap->bmWidth = fileInfo[i].width;
pBitmap->bmHeight = fileInfo[i].height;
fread(pBitmap->bits, pBitmap->bmSize, 1, mStream);
fclose(mStream);
mStream = NULL;
}
else
{
RETAILMSG(DEBUG_DLL,(TEXT("[resDll]: Load /"%s/" failed! /r/n"),filePath));
return FALSE;
}
}
}
else
{
RETAILMSG(DEBUG_DLL,(L"[resDll]: CreateMapFile failed /r/n"));
return FALSE;
}
return TRUE;
}
/************************************************************************/
/* 创建内存共享文件 */
/************************************************************************/
BOOL CreateMapFile()
{
hMap = CreateFileMapping(
INVALID_HANDLE_VALUE, //HANDLE hFile,
NULL, //LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
PAGE_READWRITE, //DWORD flProtect,
0, //DWORD dwMaximumSizeHigh,
sizeof(RESOURCE_BITMAP), //DWORD dwMaximumSizeLow,
lpResourceFileMapName //LPCTSTR lpName
);
if(hMap == NULL)
{
return false;
}
else if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS)
{
CloseHandle(hMap);
hMap = NULL;
RETAILMSG(DEBUG_DLL,(L"[resDll]: Mapping file already exist /r/n"));
return false;
}
m_bitmapRes = (PRESOURCE_BITMAP)MapViewOfFile(
hMap, //HANDLE hFileMappingObject,
FILE_MAP_WRITE | FILE_MAP_READ, //DWORD dwDesiredAccess,
0, //DWORD dwFileOffsetHigh,
0, //DWORD dwFileOffsetLow,
0 //DWORD dwNumberOfBytesToMap
);
if(m_bitmapRes)
{
RETAILMSG(DEBUG_DLL,(L"[resDll]: Mapping file address %x,hMap:%x/r/n",m_bitmapRes,hMap));
}
else
{
return false;
}
return true;
}
/************************************************************************/
/* 此DLL被主进程加载,按照系统设计将不会退出,
所以所有的DLL资源可以不写释放代码,但需了解! */
/************************************************************************/
BOOL CloseMapFile()
{
if(hMap)
{
CloseHandle(hMap);
hMap = NULL;
}
if(m_bitmapRes)
{
UnmapViewOfFile(m_bitmapRes);
m_bitmapRes = NULL;
}
return true;
}
/************************************************************************/
/* 打开内存共享文件 */
/************************************************************************/
rgbBITMAP *OpenResourceMapFile( int resID )
{
//如果图片资源无效,则直接返回
if( m_bitmapRes == NULL )
{
RETAILMSG(DEBUG_DLL,(L"[resDll]: invalid shared memory!/r/n"));
return NULL;
}
#ifdef ALL_MEM_ALLOCATED
hResourceMap = CreateFileMapping(
INVALID_HANDLE_VALUE, //HANDLE hFile,
NULL, //LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
PAGE_READONLY, //DWORD flProtect,
0, //DWORD dwMaximumSizeHigh,
0, //DWORD dwMaximumSizeLow,
lpResourceFileMapName //LPCTSTR lpName
);
if(hResourceMap == NULL)
{
DWORD ret;
ret = GetLastError();
RETAILMSG(DEBUG_DLL,(L"[resDll]: OpenResourceMapFile failed, error = %x/r/n",ret));
return NULL;
}
resFile = (PRESOURCE_BITMAP)MapViewOfFile(
hResourceMap, //HANDLE hFileMappingObject,
FILE_MAP_READ, //DWORD dwDesiredAccess,
0, //DWORD dwFileOffsetHigh,
0, //DWORD dwFileOffsetLow,
sizeof(RESOURCE_BITMAP) //DWORD dwNumberOfBytesToMap
);
return NULL;
#else
hResourceMap = CreateFileMapping(
INVALID_HANDLE_VALUE, //HANDLE hFile,
NULL, //LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
PAGE_READONLY, //DWORD flProtect,
0, //DWORD dwMaximumSizeHigh,
sizeof(rgbBITMAP), //DWORD dwMaximumSizeLow,
lpResourceFileMapName //LPCTSTR lpName
);
if(hResourceMap == NULL)
{
DWORD ret;
ret = GetLastError();
RETAILMSG(DEBUG_DLL,(L"[resDll]: OpenResourceMapFile failed, error = %x/r/n",ret));
return NULL;
}
resFile = (rgbBITMAP *)MapViewOfFile(
hResourceMap, //HANDLE hFileMappingObject,
FILE_MAP_READ, //DWORD dwDesiredAccess,
0, //DWORD dwFileOffsetHigh,
sizeof(rgbBITMAP)*resID, //DWORD dwFileOffsetLow,
sizeof(rgbBITMAP) //DWORD dwNumberOfBytesToMap
);
return resFile;
#endif
}
/************************************************************************/
/* 关闭内存共享文件 */
/************************************************************************/
BOOL CloseResourceMapFile()
{
if( hResourceMap )
{
CloseHandle(hResourceMap);
hResourceMap= NULL;
}
if(resFile)
{
UnmapViewOfFile(resFile);
resFile = NULL;
}
return true;
}
/************************************************************************/
/* 函数: GetBitmapResourceFile 获取指定图片的数据 */
/* 返回值:HANDLE为指向rgbBitmap数据的指针 */
/* 说明:
在DLL初始化时一次性加载所有共享内存到本地进程中
这样会大大提高获取共享内存的速度(几乎不耗时间,1MS内),
但带来比较大的内存消耗问题,而动态加载内存比较耗费时间(大概30MS左右, */
/************************************************************************/
HANDLE GetBitmapResourceFile( int resID )
{
DWORD dwTest = GetTickCount();
#ifdef ALL_MEM_ALLOCATED
if( resFile == NULL )
return NULL;
HANDLE pTemp = (HANDLE)&resFile->hResBitmap[resID];
#else
HANDLE pTemp = (HANDLE)OpenResourceMapFile( resID );
CloseResourceMapFile();
HANDLE pTemp = (HANDLE)&resFile->hResBitmap[resID];
#endif
RETAILMSG(DEBUG_DLL,(TEXT("[resDll]: GetBitmapResource....%x, spend %d ms/r/n"),pTemp,GetTickCount()-dwTest));
return pTemp;
}
(完)