• win32动态库


      先讲一个基本的动态库,功能为自定义一个动态库,里面有一个函数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;
    }
  • 相关阅读:
    LINUX 逻辑地址、线性地址、物理地址和虚拟地址 转
    Linux开机执行顺序
    Linux内核分析笔记 与Linux内核开发理论
    理解Linux系统中的load average(图文版)转
    Linux文件空洞与稀疏文件 转
    Linux中断(interrupt)子系统之一:中断系统基本原理 (图解)
    LINUX 内存结构
    LINUX 数据结构 &算法 网络协议 & 网络编程 多任务编程
    IO端口和IO内存的区别 转
    Linux内核高端内存 转
  • 原文地址:https://www.cnblogs.com/jlyg/p/8488076.html
Copyright © 2020-2023  润新知