先讲一个基本的动态库,功能为自定义一个动态库,里面有一个函数MyMessage实现弹出MessageBox。
1、 先在头文件中定义:
#ifdef __cplusplus #define EXPORT extern "C" __declspec (dllexport) #else #define EXPORT __declspec (dllexport) #endif
2、在头文件中定义自己的需要函数,比如:EXPORT VOID MyMessage(HWND hwnd,LPCTSTR lstr);
3、在.cpp文件中实现自定义函数
EXPORT VOID MyMessage(HWND hwnd,LPCTSTR lstr)
{
MessageBox(hwnd,lstr,"tip",MB_OK);
}
4、新建项目使用该动态库。
(1)、附加包含目录。右击属性 -> 配置属性 -> C/C++ -> 常规 -> 附加包含目录。然后选择动态库的头文件目录添加进去。
(2)、加载动态库。定义HMODULE g_hModule = NULL;在OnCreate函数中加载
if(g_hModule == NULL) { g_hModule = ::LoadLibrary("mydll.dll"); }
(3)、加载函数与使用
VOID(*MYMESSAGE)(HWND,LPCTSTR); MYMESSAGE = (VOID(*)(HWND,LPCTSTR))::GetProcAddress(g_hModule,"MyMessage"); MYMESSAGE(hwnd,"hello world");
其中MYMESSAGE为函数指针。
(4)、在destroy的时候卸载动态库
if(g_hModule) { ::FreeLibrary(g_hModule); g_hModule = NULL; }
在动态库中加入资源,如何加载
提示:如果动态库为没有函数,则不要设置项目依赖,因为动态库没有函数不生成lib文件。在动态库中加入资源后,把资源文件resource改名,避免与调用dll文件的程序重名。
用法差不多,加载资源的时候把HINSTANCE改成HMODULE就行了。
#include<tchar.h> #include<stdio.h> #include<windows.h> #include"resource.h" #include"dllresource.h" HINSTANCE g_hInstance = NULL; HMODULE g_hModule = NULL; LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { g_hInstance = hInstance; WNDCLASS wndcls; wndcls.cbClsExtra = 0; wndcls.cbWndExtra = 0; wndcls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wndcls.hCursor = LoadCursor(NULL,IDC_ARROW); wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION); wndcls.hInstance = hInstance; wndcls.lpfnWndProc = WinSunProc; wndcls.lpszClassName = _T("sunxin2006"); wndcls.lpszMenuName = NULL; wndcls.style = CS_HREDRAW | CS_VREDRAW; RegisterClass(&wndcls); HWND hwnd = CreateWindow(_T("sunxin2006"),_T("helloworld"),WS_OVERLAPPEDWINDOW, 0,0,600,400,NULL,NULL,hInstance,NULL); ShowWindow(hwnd,SW_SHOW); UpdateWindow(hwnd); MSG msg; while(GetMessage(&msg,NULL,0,0)>0) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } VOID OnCreate(HWND hwnd,WPARAM wParam,LPARAM lParam) { int scrWidth,scrHeight; RECT rect; //获得屏幕尺寸 scrWidth = GetSystemMetrics(SM_CXSCREEN); scrHeight = GetSystemMetrics(SM_CYSCREEN); //取得窗口尺寸 GetWindowRect(hwnd,&rect); //重新设置rect里的值 rect.left = (scrWidth-rect.right)/2; rect.top = (scrHeight-rect.bottom)/2; //移动窗口到指定的位置 SetWindowPos(hwnd,HWND_TOP,rect.left,rect.top,rect.right,rect.bottom,SWP_SHOWWINDOW); g_hModule = LoadLibrary("testdll2.dll"); } POINT DrawBmp(HDC hdc,int x,int y,int bmpID) { HDC hMemdc = CreateCompatibleDC(hdc); //HBITMAP hBitmap = CreateCompatibleBitmap(hdc,rtClient.right,rtClient.bottom); HBITMAP hBitmap = LoadBitmap(g_hInstance,MAKEINTRESOURCE(bmpID)); BITMAP bmp; GetObject(hBitmap,sizeof(BITMAP),&bmp); SelectObject(hMemdc,hBitmap); BitBlt(hdc,x,y,bmp.bmWidth,bmp.bmHeight,hMemdc,0,0,SRCCOPY); DeleteObject(hBitmap); DeleteDC(hMemdc); POINT pt; pt.x = x+bmp.bmWidth; pt.y = y+bmp.bmHeight; return pt; } POINT DrawBmpFromDll(HDC hdc,int x,int y,int bmpID) { HDC hMemdc = CreateCompatibleDC(hdc); HBITMAP hBitmap = LoadBitmap(g_hModule,MAKEINTRESOURCE(bmpID)); BITMAP bmp; GetObject(hBitmap,sizeof(BITMAP),&bmp); SelectObject(hMemdc,hBitmap); BitBlt(hdc,x,y,bmp.bmWidth,bmp.bmHeight,hMemdc,0,0,SRCCOPY); DeleteObject(hBitmap); DeleteDC(hMemdc); POINT pt; pt.x = x+bmp.bmWidth; pt.y = y+bmp.bmHeight; return pt; } VOID OnPaint(HWND hwnd,WPARAM wParam,LPARAM lParam) { RECT rtClient; GetClientRect(hwnd,&rtClient); PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd,&ps); /*int IDs[] = {IDB_BMP1,IDB_BMP2,IDB_BMP3}; POINT pt = {0,0}; for(int i=0;i<sizeof(IDs)/sizeof(int);++i) { pt = DrawBmp(hdc,pt.x,pt.y,IDs[i]); } */ int IDs[] = {IDB_BITMAP1,IDB_BITMAP2,IDB_BITMAP3,IDB_BITMAP4,IDB_BITMAP5, IDB_BITMAP6,IDB_BITMAP7,IDB_BITMAP8,IDB_BITMAP9}; POINT pt = {0,0}; for(int i=0;i<sizeof(IDs)/sizeof(int);++i) { pt = DrawBmpFromDll(hdc,pt.x,pt.y,IDs[i]); } EndPaint(hwnd,&ps); } LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { switch(uMsg) { case WM_CREATE: OnCreate(hwnd,wParam,lParam); break; case WM_PAINT: OnPaint(hwnd,wParam,lParam); break; case WM_DESTROY: if(g_hModule) { FreeLibrary(g_hModule); g_hModule = NULL; } PostQuitMessage(0); break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0; }
windows动态库共享内存
windows共享内存,数据必须初始化,并且定义时需要特定格式,可以通过动态库共享内存,设计程序只被启动一次。在动态库的头文件或者cpp文件中加上以下代码。
#pragma data_seg("mysharedata") int app_count = 0; //共享内存, 必须初始化,否则共享内存失败 #pragma data_seg() #pragma comment(linker,"/SECTION:mysharedata,RWS")
动态库导出类
1、动态库中定义
#ifdef MYEXPORT #define EXPORT __declspec (dllexport) #else #define EXPORT __declspec (dllimport) #endif
2、动态库中新建类中头文件
class EXPORT MyClassTestDll { public: MyClassTestDll(void); ~MyClassTestDll(void); int Add(int,int); };
3、在动态库.cpp文件中实现上述类,并定义宏MYEXPORT
#define MYEXPORT MyClassTestDll::MyClassTestDll(void) { } MyClassTestDll::~MyClassTestDll(void) { } int MyClassTestDll::Add(int num1,int num2) { return num1 + num2; }
4、在测试程序中设置附加附加包含目录与附加库目录,分别在属性的c/c++与链接器的常规中设置。
5、在测试程序中使用
#pragma comment(lib,"testclassdll3.lib") MyClassTestDll myclasstestdll; int sum = myclasstestdll.Add(100,200); if(sum == 300) MessageBox(hwnd,"调用成功","",MB_OK);
动态库入口函数中获取HINSTANCE
HINSTANCE g_hInstance= NULL; BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH: g_hInstance= = (HINSTANCE)hModule; case DLL_PROCESS_DETACH: break; } return TRUE; }