从c ++ CLR / CLI项目的资源文件加载图像

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从c ++ CLR / CLI项目的资源文件加载图像相关的知识,希望对你有一定的参考价值。

我的项目是一个c ++ CLR / CLI,我的资源文件中有一些PNG图像,我想在单击按钮时更改System::Windows::Forms::Button的BackgroundImage,我的代码如下:

#include <Windows.h>
#include "resource.h"

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
    HBITMAP hBitMap = (HBITMAP) LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_PNG2), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    Bitmap^  bitMap = Bitmap::FromHbitmap((IntPtr) hBitMap);
    DeleteObject(hBitMap);
    button1->BackgroundImage = (System::Drawing::Image^) bitMap;
}

这是我的resource.h:

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Disneyy.rc
//
#define IDB_PNG1                        101
#define IDB_PNG2                        102
#define IDB_PNG3                        103

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        104
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

编译时我收到此错误:

1>MyForm.obj : error LNK2028: unresolved token (0A000036) "extern "C" void * __stdcall LoadImageW(struct HINSTANCE__ *,wchar_t const *,unsigned int,int,int,unsigned int)" (?LoadImageW@@$$J224YGPAXPAUHINSTANCE__@@PB_WIHHI@Z) referenced in function "private: void __clrcall Disneyy::MyForm::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@MyForm@Disneyy@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
1>MyForm.obj : error LNK2028: unresolved token (0A00003F) "extern "C" int __stdcall DeleteObject(void *)" (?DeleteObject@@$$J14YGHPAX@Z) referenced in function "private: void __clrcall Disneyy::MyForm::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@MyForm@Disneyy@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
1>MyForm.obj : error LNK2019: unresolved external symbol "extern "C" void * __stdcall LoadImageW(struct HINSTANCE__ *,wchar_t const *,unsigned int,int,int,unsigned int)" (?LoadImageW@@$$J224YGPAXPAUHINSTANCE__@@PB_WIHHI@Z) referenced in function "private: void __clrcall Disneyy::MyForm::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@MyForm@Disneyy@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
1>MyForm.obj : error LNK2019: unresolved external symbol "extern "C" int __stdcall DeleteObject(void *)" (?DeleteObject@@$$J14YGHPAX@Z) referenced in function "private: void __clrcall Disneyy::MyForm::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@MyForm@Disneyy@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)

编辑:好的我通过将User32.lib添加到Additional Dependencies并将Entry Point指定为main来修复它。但是这条线有问题:

HBITMAP hBitMap = (HBITMAP) LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_PNG2), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

现在我收到这个错误:

First-chance exception at 0x77130c3f in Disneyy.exe: 0xC0000005: Access violation reading location 0x00000066.
A first chance exception of type 'System.AccessViolationException' occurred in Disneyy.exe
An unhandled exception of type 'System.AccessViolationException' occurred in Disneyy.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

编辑:我再次通过将IMAGE_BITMAP更改为BI_PNG来修复它,但现在出现了一个新的错误:Bitmap^ bitMap = Bitmap::FromHbitmap((IntPtr) hBitMap);

A first chance exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Drawing.dll
An unhandled exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Drawing.dll
Additional information: A generic error occurred in GDI+.
答案

经过数小时和数小时的研究后,我找到了一个适用的解决方案,效果很好!

这个解决方案是Giuseppe Pischedda的答案:https://www.codeproject.com/Articles/17996/Load-JPEG-images-from-DLL-with-LoadResource-in-Man的组合

和Bordon的回答:https://social.msdn.microsoft.com/Forums/de-DE/c8dea6f9-0564-49d6-9782-117207031140/loadfromresource-fails-for-loading-png-files-from-resource?forum=vcmfcatl

由我改编为PNG图像:

public: System::Drawing::Image^  getImageFromRes(long resource_ID) {
    // Function getImageFromRes
    // A function for loading PNG images from resources in C++ CLR/CLI
    // Copyright (C) Giuseppe Pischedda 2007 for most code
    // and a little part of this code by Bordon and adapted by me for PNG images in C++ CLR/CLI.

    //Load the resource module:
    HMODULE hInst = NULL;

    // Find the resource using the resource ID from file "resource.h"
    HRSRC hResource = ::FindResource(hInst, MAKEINTRESOURCE(resource_ID), L"PNG");
    if (!hResource) return nullptr;

    // Load the resource and save the total size.
    DWORD Size = SizeofResource(hInst, hResource);
    HGLOBAL MemoryHandle = LoadResource(hInst, hResource);
    if (MemoryHandle == NULL) return nullptr;

    //Create a cli::array of byte with size = total size + 2
    cli::array<BYTE>^  MemPtr = gcnew array<BYTE>(Size + 2);

    //Cast from LPVOID to char *
    char *lkr = (char *) (LockResource(MemoryHandle));

    //Copy from unmanaged memory to managed array
    System::Runtime::InteropServices::Marshal::Copy((IntPtr) lkr, MemPtr, 0, Size);

    // Create a new MemoryStream with size = MemPtr
    System::IO::MemoryStream^  stream = gcnew System::IO::MemoryStream(MemPtr);

    //Write in the MemoryStream
    stream->Write(MemPtr, 0, Size);

    //Set the position for read the stream
    stream->Position = 0;

    //Free allocated resources
    FreeLibrary(hInst);

    //Create an Image abstract class pointer
    System::Drawing::Image^  ptrPNG;

    //Assign the stream to abstract class pointer
    ptrPNG = System::Drawing::Image::FromStream(stream);
    return ptrPNG;
}

用法:

System::Drawing::Image^  image = getImageFromRes(IDB_PNG2);
if (image != nullptr) button1->BackgroundImage = image;

以上是关于从c ++ CLR / CLI项目的资源文件加载图像的主要内容,如果未能解决你的问题,请参考以下文章

C++/CLI 为啥对托管不可见

无法使用 /clr 选项从 Visual C++ 项目加载 CLR

在Vue项目中加载krpano全景图

使用包含托管类的 /CLR 标志构建的本机 dll

vue-cli项目打包成dist文件夹后,放在服务器上,资源自动使用https加载

从 C++ 应用程序调试动态加载的 C++/CLI DLL