因为工作上的需要,开发了个小插件,然后对比较好的小伙伴可能会悄悄分享给他们用,也不想声张,反正又没有额外奖励。考虑到小伙伴的编程水平几乎是0(虽然大学都教了C语言),本人的编程水平经过这几年的磨练应该有0.2了吧……所以还是想办法把插件调用的资源全部整合在一个文件里,后面给小伙伴用的时候就不用再折腾什么了。

        1个文件都还不会用,那也别好意思说自己学过编程了。

        作为新手,关于资源的调用我也是初学,以为网上有视频资源,结果搜不到,然后就只有从图文教程出发了。一开始也找不到搜索关键词,经过三天的摸索,一个坑一个坑地踩,总算是迎来了曙光。

        主要参考的文献名称为《编程实现自定义资源释放》、《将文件作为资源存储与释放的技术》,主要代码如下:

程序逻辑:

    BOOL FreeMyResource(UINT uiResouceName, char *lpszResourceType, char *lpszSaveFileName)
    {
        // 获取指定模块里的指定资源
        HRSRC hRsrc = ::FindResource(NULL, MAKEINTRESOURCE(uiResouceName), lpszResourceType);
        if (NULL == hRsrc)
        {
            FreeRes_ShowError("FindResource");
            return FALSE;
        }
        // 获取资源的大小
        DWORD dwSize = ::SizeofResource(NULL, hRsrc);
        if (0 >= dwSize)
        {
            FreeRes_ShowError("SizeofResource");
            return FALSE;
        }
        // 将资源加载到内存里
        HGLOBAL hGlobal = ::LoadResource(NULL, hRsrc);
        if (NULL == hGlobal)
        {
            FreeRes_ShowError("LoadResource");
            return FALSE;
        }
        // 锁定资源
        LPVOID lpVoid = ::LockResource(hGlobal);
        if (NULL == lpVoid)
        {
            FreeRes_ShowError("LockResource");
            return FALSE;
        }
        // 保存资源为文件
        FILE *fp = NULL;
        fopen_s(&fp, lpszSaveFileName, "wb+");
        if (NULL == fp)
        {
            FreeRes_ShowError("LockResource");
            return FALSE;
        }
        fwrite(lpVoid, sizeof(char), dwSize, fp);
        fclose(fp);
        return TRUE;
    }

程序调用测试:

    BOOL FreeMyResource(UINT uiResouceName, char *lpszResourceType, char *lpszSaveFileName)
    {
        // 获取指定模块里的指定资源
        HRSRC hRsrc = ::FindResource(NULL, MAKEINTRESOURCE(uiResouceName), lpszResourceType);
        if (NULL == hRsrc)
        {
            FreeRes_ShowError("FindResource");
            return FALSE;
        }
        // 获取资源的大小
        DWORD dwSize = ::SizeofResource(NULL, hRsrc);
        if (0 >= dwSize)
        {
            FreeRes_ShowError("SizeofResource");
            return FALSE;
        }
        // 将资源加载到内存里
        HGLOBAL hGlobal = ::LoadResource(NULL, hRsrc);
        if (NULL == hGlobal)
        {
            FreeRes_ShowError("LoadResource");
            return FALSE;
        }
        // 锁定资源
        LPVOID lpVoid = ::LockResource(hGlobal);
        if (NULL == lpVoid)
        {
            FreeRes_ShowError("LockResource");
            return FALSE;
        }
        // 保存资源为文件
        FILE *fp = NULL;
        fopen_s(&fp, lpszSaveFileName, "wb+");
        if (NULL == fp)
        {
            FreeRes_ShowError("LockResource");
            return FALSE;
        }
        fwrite(lpVoid, sizeof(char), dwSize, fp);
        fclose(fp);
        return TRUE;
    }

    一路走来踩了各种“坑”,现在再提一个:按照上面的代码编译,其实是不通过的,因为找不到资源!

    原因就出现在下面这段代码:

HRSRC hRsrc = ::FindResource(NULL, MAKEINTRESOURCE(uiResouceName), lpszResourceType);

下文为引用:

在exe中,FindResource相关函数的第一个参数可以为NULL,表示当前模块,但是DLL中执行该函数时,参数使用NULL的话则代表在调用该DLL的程序的资源文件中搜索。所以该函数始终会返回空,搜索不到资源!\
通过GetModuleHandle可以获取到该DLL在当前进程空间中的位置,参数为DLL的字符串名称。

也就是说因为我们编译的是DLL文件,所以参数NULL必须改为GetModuleHandle(\_T("XXX.DLL"))

HRSRC hRsrc = ::FindResource(GetModuleHandle(\_T("XXX.DLL")), MAKEINTRESOURCE(uiResouceName), lpszResourceType);

发表评论