先讲一个基本的动态库,功能为自定义一个动态库,里面有一个函数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;
}
View Code

 

   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;
}