Microsoft MVP성태의 닷넷 이야기
C++ Dll 에서 C# 의 PictureBox이미지 변경문제 [링크 복사], [링크+제목 복사],
조회: 18530
글쓴 사람
박주만 (ubdown at nate.com)
홈페이지
첨부 파일
 

안녕하세요...

C# 의 PictureBox 이미지를 C++ DLL 에서 바꾸는 문제 입니다.

몇일째 찾아 보다가 도저히 답이 안나와서 문의 드리게 되었네요...

우선 개발 환경은 :
OS : window8.1
Tool : Visual Studio 2012

Code 의 주석으로 설명할께요...

//----------------------------------------------------------------------

Main.C#

//C++ DLL 호출
  [DllImport("CameraDll.dll")]
  static extern void dll_Button1_Click(IntPtr hwnd, int deviceIndex);

private void Button1_Click(object sender, EventArgs e)
{
  IntPtr inpt2 = pictureBox1.Handle;
  dll_Button1_Click( inpt2 , g_DeviceIndex);
}


//----------------------------------------------------------------------




CameraDll.CPP DLL

unsigned char*        m_pDisplayBuffer;
unsigned char* m_ppDisplayBuffer[2];
HWND hwnd;



////////////////////////////////////////////////////////////////////////////////////////////////
//    Display Image
////////////////////////////////////////////////////////////////////////////////////////////////
void DisplayImage(HDC hDC, int width, int height, int dw, int dh, unsigned char*pImage)
{
    HDC MemDC;
    BITMAPINFO        bmpInfo;
    BITMAPFILEHEADER bmFileHeader;
    BITMAP Bitmap;

    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = width;
    bmpInfo.bmiHeader.biHeight = height;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biBitCount = 24;
    bmpInfo.bmiHeader.biCompression = BI_RGB ;
    bmpInfo.bmiHeader.biSizeImage = 0;
    bmpInfo.bmiHeader.biXPelsPerMeter = 0;
    bmpInfo.bmiHeader.biYPelsPerMeter = 0;
    bmpInfo.bmiHeader.biClrUsed = 0;
    bmpInfo.bmiHeader.biClrImportant = 0;

    if(width == dw)
    {
        MemDC = CreateCompatibleDC(hDC); //<--- hdc : C#의 PictureBox HDC
        printf("Create BitMap\n");
    //    BitMapByteCallBackHandler(&h_bitmap); //<-- C#으로 이미지 Data를 가져와서 처리 하려고 시도...
                                                                         // C#의 PictureBox 이미지를 변경 안됨!!!!!!! 실행시 오류 없이 진행 됨, Debug 오류 없음..
        SetDIBitsToDevice(MemDC,    0, 0,    (width), (height),    0, 0, 0, (height),    pImage,    &bmpInfo, DIB_RGB_COLORS); //<--- WinAPI에서 실행할 경우 변경됨


        DeleteDC(MemDC);
    }
    else
    {
        
    }
}

void MakeDisplayImage(int width, int height, unsigned char* pSrc, unsigned char* pDst)
{
    int wbytes;
    wbytes = width * 3;

    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            pDst[i * wbytes + j * 3] = pSrc[((height - 1) - i) * width + ((width - 1) - j)];
            pDst[i * wbytes + j * 3 + 1] = pSrc[((height - 1) - i) * width + ((width - 1) - j)];
            pDst[i * wbytes + j * 3 + 2] = pSrc[((height - 1) - i) * width + ((width - 1) - j)];
        }
    }
}

void CALLBACK OnTimer(HWND fhwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
    int errorCode = 0;
    unsigned char*    pAddress;

    errorCode = UCamGetImageData(g_DeviceIndex, &pAddress); //<--- pAddress 를 통해 Display 할 이미지 Dataf가져옴
    if(errorCode == UCAM_NEW_FRAME)
    {
        SetWindowText(hwnd,"Test"); // <-- C# 의 Button Text 변경 X 안됨
        EnableWindow(hwnd, FALSE); // <-- C# 의 Button Enable 변경 O 됨
        
                HDC hdc = GetDC(hwnd);
        MakeDisplayImage(m_nWidth, m_nHeight, pAddress, m_ppDisplayBuffer[g_DisplayIndex]); // <--- ppDisplayBuffer

        DisplayImage(hdc, m_nWidth, m_nHeight, m_nDisplayWidth, m_nDisplayHeight, m_ppDisplayBuffer[g_DisplayIndex]); <---- 이미지를 Display 호출 ****

        //m_PictureControl.ReleaseDC(hdc);
        g_DisplayIndex++;
        if(g_DisplayIndex == DISPLAY_BUFFERCOUNT)
        {
            g_DisplayIndex = 0;
        }
    }else{
        printf("-----------------------\n");
    }

}

extern "C" __declspec(dllexport) void __cdecl dll_IDCUCAMSTART_Click(HWND fhwnd, int deviceIndex){ //<----- C#
    hwnd = fhwnd;
    
    BufferInitialize();
    USBReceiveCallback(USBReceiveHandler);
    SetTimer(NULL, ID_TIMER101, 500, OnTimer);

    m_ReceiveMode = 1;
    UCamStart(g_DeviceIndex, m_ReceiveMode);
    m_bDisplayMode = false;
}


//----------------------------------------------------

DisplayImage 함수에서 CallBack 으로

C++ Dll

typedef void (__cdecl * BitMapByteCallback)(const HBITMAP fbyte);

HBITMAP OldBitmap;
HBITMAP hBitmap;
BITMAP bit;
int bx,by;

MemDC = CreateCompatibleDC(hDC); //<--- hdc : C#의 PictureBox HDC

hBitmap = CreateDIBitmap(MemDC,(BITMAPINFOHEADER *)&bmpInfo,CBM_INIT, (PBYTE)pImage,(BITMAPINFO *)&bmpInfo,DIB_RGB_COLORS);
        
OldBitmap = (HBITMAP)SelectObject(MemDC, &hBitmap);

BitMapByteCallBackHandler(OldBitmap); <-- Callback C# Function 호출

C# CallBack

public void BitMapByteCallBackHandler(IntPtr hBitmap)
{
            
            Bitmap bitmap = null;
            try
            {
                bitmap = new Bitmap(Image.FromHbitmap(hBitmap)); // <-- System.Runtime.InteropServices.ExternalException (0x80004005): GDI+에서 일반 오류가 발생했습니다.
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
}

왜 System.Runtime.InteropServices.ExternalException (0x80004005): GDI+에서 일반 오류가 발생했습니다. 발생할까요???





요약:
1. C++ DLL 에서 C# 의 PictureBox의 이미지를 변경 하고 싶습니다.
2. BitMapByteCallBackHandler를 이용하여 C#으로 HBitMap 이미지를 보내서
   C#에서 구현 하려고 한다면 어떻게 해야 할까요??
3. System.Runtime.InteropServices.ExternalException
     








[최초 등록일: ]
[최종 수정일: 12/19/2013]


비밀번호

댓글 작성자
 



2013-12-19 04시30분
HBITMAP이 PVOID 값이니, C++에서 넘기기 전의 값과 C#에서 받은 IntPtr의 값이 동일한지 확인해 보세요. 딱히, 위의 소스코드만 봐서는 별다른 오류가 없어보이는데요.

다른 소스코드는 다 떼어버리고 문제가 재현되는 최소한의 코드를 구성해서 프로젝트로 파일로 올려주시면 확인해 보겠습니다.
정성태

... 76  77  78  79  80  81  82  [83]  84  85  86  87  88  89  90  ...
NoWriterDateCnt.TitleFile(s)
383정성태5/30/20068406            답변글 [답변]: [답변]: [답변]: ATL Event에서 스크립트가 값을 다시 돌려주는 방법은?
378guest5/26/20067968managed 와 unmanaged 의 차이가 뭐져?
379정성태5/26/20068278    답변글 [답변]: managed 와 unmanaged 의 차이가 뭐져? [1]
384guest5/30/20067751        답변글 감사합니다.
376노기도5/16/20068071vb6의 GetObjectContext 를 2005에서는 어떻게 사용해야 하나요? [3]
375이덕희5/15/20069961SmartClient 강좌를 보고... 엑박이 나옵니다... [2]파일 다운로드1
3745/12/20068912데이타셋을 레코드셋으로 변경하는 방법...... [2]파일 다운로드1
373아폴론5/12/20067877스마트 클라이언트.. 강좌대로 했는데.. 이런 에러가 나네요. [1]파일 다운로드1
372정보문5/11/20068477DHCP를 쓰는 이유 [1]
366임경훈5/8/20068305지정된 웹서버에서 ASP.NET 버전 1.1이 실행되고 있지 않아 ASP.NET 웹 응용 프로그램 또는 웹서비스를 실행할수 없습니다 [2]
365꿈의공장5/8/20068162스마트 클라이언트 사용시 안보이는 현상 [1]
364조준현5/3/200676222.0 스마트클라이언트에서.. public 메소드등을 스크립트에서 접근하는 방법이..? [2]
363혁이5/2/200610236스마트 클라이언트에 farpoint 컨트롤 올리기 2번째 질문입니다 [1]파일 다운로드1
361혁이4/28/20068548스마트 클라이언트에 FarPointSpread를 올렸는데요. 보이지가 않습니다..음.. [1]
360꿈의공장4/28/20068791스마트클라이언트와 오라클에 연결 [1]
359박호성4/28/20067943ASP.NET에서 COM Object를 사용하려면? [1]
358임동오4/27/20068475ASP -> COM+ Proxy 연결문제입니다. 151초동안 아무응답없습니다. ㅠㅠ
362정성태4/30/20069710    답변글 [답변]: ASP -> COM+ Proxy 연결문제입니다. 151초동안 아무응답없습니다. ㅠㅠ
354노기도4/24/20067823시스템 구성에 대해 의견을 듣고 십습니다.
355정성태4/25/20067898    답변글 [답변]: 시스템 구성에 대해 의견을 듣고 십습니다.
356노기도4/25/20067242        답변글 [답변]: 귀찮게 해드려 죄송스럽지만.
357정성태4/25/20067437            답변글 [답변]: [답변]: 귀찮게 해드려 죄송스럽지만. [1]
352산들바람4/19/20067270이번겨울방학때세도나를 여행하려구하는데요,,,
353정성태4/20/200612587    답변글 [답변]: 이번겨울방학때세도나를 여행하려구하는데요,,,
351오기4/18/20067105aspx [2]
350유지연4/17/20067917smartclient DB connection관련 질문 입니다. [2]파일 다운로드1
... 76  77  78  79  80  81  82  [83]  84  85  86  87  88  89  90  ...