본문 바로가기
개발언어/C#

[C#]포인터나 핸들은 IntPtr 이용해 받기

by 창용이랑 2020. 11. 2.
728x90

C# C++ 혼합 프로그래밍 4장

 

8. C#에서 Native 다이렉트 X 호출 dx_wrapping.zip다이렉트 X 디바이스를 생성해서 파란 화면을 보여주는 간단한 프로그램을 만들어 보자 !!!
Native 다이렉트 X를 호출 할려면 디바이스나 핸들의 값을 C#과 어떻게 통신 할것인지 고민 하게 되었다.
System.IntPtr을 이용 하면 통신이 가능하다는 것을 알게 되었다.

포인터나 핸들은 IntPtr 이용해 받기System.IntPtr을 사용하면 포인터나 핸들을 네이티브로 보내거나 받을수 있다.
C#에서 DllImport를 사용해서 윈도우즈 API 함수를 호출할 때, IntPtr을 본적이 있을 것이다.

[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
IntPtr.ToPointer()를 이용해서 C# Form의 윈도우 핸들을 Native C++로 넘겨주는 예는 많이 있지만,
Nativ C++에서 ,C#으로 넘겨주는 윈도우 핸들이나 포인터의 정확한 문서는 찾을수가 없었다.
DllImport 경우를 생각해서 아래 예제를 만들어 보면 "hWnd", "IPtr", "window" 3개의 값은 모두 똑같다.
    HWND hWnd = ::FindWindow("Notepad", "제목 없음 - 메모장");
    IntPtr iPtr = (IntPtr)hWnd;
    HWND window = (HWND)iPtr.ToPointer();
 
프로그램에 사용되는 파일들은 다음과 같다.
Unmanaged C++graphics.cpp, graphics.hCGraphics 클래스
다이렉트 X 디바이스를 생성해서 빈화면을 렌더링Managed C++mgraphics.cppMGraphics 클래스CGraphics 클래스 랩핑C#dxmain.csDXMain 클래스MGraphics 클래스를 참조하여 렌더링한다.앞장과는 다르게 Unmanaged C++과 Managed C++을 별도의 DLL로 만들지 않고 graphics.dll 하나로 만든다.
CGraphics 클래스는 압축 파일의 소스를 참고하고, MGraphics 클래스는 리스트만 보여줄것이다.
설명은 C# 부분만 자세하게 한다.
아직 C#에 익숙하지 않기 때문에 틀린 설명도 있을 것이다.
MGraphics 클래스는 다이렉트 X 디바이스를 생성, 렌더링, 소멸을 랩핑 하였다.
생성, 렌더링, 소멸을 DXMain 클래스 어디서 해줄건지 알면 문제는 쉽게 풀수 있다.
생성: WinForm이 화면에 출력되기 전에 Load 이벤트 발생
렌더링: WinForm 이벤트 없을 때 Idle 이벤트 발생
소멸: WinForm을 닫을 때 Closed 이벤트 발생
이벤트를 사용 할려면 이벤트를 생성자에 추가한다.
이벤트 등록:    public DXMain(string strText)
    {
        this.Text = strText;
        this.Load += new System.EventHandler(this.Form_Load);
        this.Closed += new System.EventHandler(this.Form_Closed);
        Application.Idle += new System.EventHandler(this.Form_Idle);
        //InitializeComponent();
        this.Show();
    }
생성 :    private void Form_Load(object sender, System.EventArgs e)
    {
        dxRender = new MGraphics();
        dxRender.Create(this.Handle);
        dxRender.SetupCamera();
    }
렌더링 :    private void Form_Idle(object sender, System.EventArgs e)
    {
        dxRender.BeginScene();
        dxRender.EndScene();
    }
소멸 :    private void Form_Closed(object sender, System.EventArgs e)
    {
        dxRender.Cleanup();
    }
 
//mgraphis.cpp
#include 
#using 
using namespace System;
 
#include "graphics.h"
 
public __gc class MGraphics
{
public:
    MGraphics()
    {
        m_pUnmanagedGraphics = new CGraphics();
    }
    ~MGraphics()
    {
        delete m_pUnmanagedGraphics;
    }
 
public:
    bool Create(IntPtr windowHandle)
    {
        HWND hWnd = (HWND)windowHandle.ToPointer();
        RECT rect;
        GetClientRect(hWnd, &rect);
        return m_pUnmanagedGraphics->Create(hWnd, rect.right - rect.left, rect.bottom - rect.top, false);
    }
 
    void   Cleanup()
    {
        m_pUnmanagedGraphics->Cleanup();
    }
 
    void    SetupCamera()
    {
        m_pUnmanagedGraphics->SetupCamera();
    }
    void    BeginScene()
    {
        m_pUnmanagedGraphics->BeginScene();
    }
    IntPtr  EndScene()
    {
        return m_pUnmanagedGraphics->EndScene();
    }
 
private:
    CGraphics * m_pUnmanagedGraphics;
};
 
//dxmain.cs
using System;
using System.Windows.Forms;
 
 
public class DXMain : Form
{
    private MGraphics dxRender = null;
 
    public DXMain(string strText)
    {
        this.Text = strText;
        this.Load += new System.EventHandler(this.Form_Load);
        this.Closed += new System.EventHandler(this.Form_Closed);
        Application.Idle += new System.EventHandler(this.Form_Idle);
        //InitializeComponent();
        this.Show();
    }
 
    [STAThread]
    static void Main()
    {
        Application.Run(new DXMain("DirectX Test"));
    }
 
    private void Form_Load(object sender, System.EventArgs e)
    {
        dxRender = new MGraphics();
        dxRender.Create(this.Handle);
        dxRender.SetupCamera();
    }
 
    private void Form_Closed(object sender, System.EventArgs e)
    {
        dxRender.Cleanup();
    }
 
    private void Form_Idle(object sender, System.EventArgs e)
    {
        dxRender.BeginScene();
        dxRender.EndScene();
    }
/*
    protected override void OnPaint(PaintEventArgs e)
    {
        Form_Idle(this, e);
    }
 
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        Form_Idle(this, e);
    }
*/   
}
[펌]http://www.gamedev.net/community/forums/topic.asp?topic_id=474894
[펌]Game Engine Toolset Development  (출판사: Course Technology)
www.courseptr.com/downloads/bonus/009638_BonusCh02.pdf[출처] 
[C#]포인터나 핸들은 IntPtr 이용해 받기|작성자 nimi315

[출처] [펌] [C#]포인터나 핸들은 IntPtr 이용해 받기|작성자 baek2187