# [Solved] Unmanaged DirectX and Winforms ?

## Recommended Posts

paic    645
Hi, I've build a little scenegraph editor with winforms (managed C++ with Visual C++ EE) and I'm now trying to create a DirectX control to render to. But a Control is a managed class. Does that mean I'll have to use MDX ? Or is there a way to use my old engine as is (in unmanaged C++ / DX) in a managed C++ project ? Thx in advance for any help. [Edited by - paic on March 15, 2006 3:06:26 AM]

##### Share on other sites
Let me see if I get this right...
You want to use your unmanaged DirectX engine in a winforms environment. If this is the case then sure...

What you can do is use C++/CLI to build a managed wrapper around your unmanaged code and then use this in your winforms app.. You can use native DirectX.

Example

//include your unmanaged class first#include "UnmanagedRenderer.h"//This directive is so that you can mix unmanaged and managed C++ in the same//project#pragma managednamespace Managed{    //declare a managed C++/CLI class (encapsulating your unmanaged renderer)    public ref class WrapperClass    {    private:	    Native::UnmanagedRenderer* unManagedRenderer;    public:	    WrapperClass()            {		    unManagedRenderer = new Native::UnmanagedRenderer;    	    }    };}

PS: Marshalling some types might be an issue but if you need any more help, please don't hesitate.

I hope this helps.
Take care.

##### Share on other sites
paic    645
Yup, that helps, thx ^^
I was hoping that I could avoid writing a lot of wrapper classes, though ^^''
I'm currently writing a small managed rendering loop, just to get used to it, and see what is the best option : switch to managed DirectX, and write wraper classes and keep my old engine unmanaged.

Thx again.

##### Share on other sites
paic    645
Hmm, I'm having a little difficulty with managed DX.
My app uses a main :
// the main entry point[STAThread]int main(array<System::String ^> ^ args){    // Enabling Windows XP visual effects before any controls are created    Application::EnableVisualstyles();    Application::SetCompatibleTextRenderingDefault(false);     // Create the main window and run it    Application::Run(gcnew SGE_MainForm());    return 0;}

But when I try to use MDX, I've got an exception which says :
"'C:\WINDOWS\assembly\GAC\Microsoft.DirectX.Direct3D\1.0.2902.0__31bf3856ad364e35\Microsoft.DirectX.Direct3D.dll' is attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initialization function since doing so can cause the application to hang."

In the SGE_MainForm (which is the main windowsform ^^) I have a menu, various splitter with propertygrids, treeview and other stuff. And on the middle, I would like to have a "Direct3D control" on which to draw my scene.

I couldn't find any tutorials on which to do that. Only tutorials on how to directly draw on the whole form. If you have any information on how to create a "Direct3D control", that would really help me ^^

##### Share on other sites
1 Hint, you should really not try to mix managed and unmanaged DirectX. The main part you have to remember when using Managed DirectX and Winforms is to explicitly pass the handle fo the control you want to render to. I mainly use a Panel control to render to. So you would pass Control.Handle to the Device constructor. If you are using unmanaged code you should still explicitly pass the handle.

With regards to the loaderlock error. This might be due to a couple of things but most of all I think it's due to debugging and this might be due to the fact that you might be using .NET2.0 against the .Managed DirectX 1.1 assemblies. You could try and disable it in your managed debugging assistants in your IDE.

I hope this helps.
Take care.

##### Share on other sites
paic    645
First : thx for taking the time to help me ^^
I've changed the MDX version I was using (the 1.0.XXXX something) and now it "works". I mean, I don't have the exception, but the device is still not created.

Here is how I did it :

// in the header, I declare this class which inherit from Control, so that// I can use it where I want in my form (currently, on the panel of a splitContainer)public ref class CDirect3DControl : public System::Windows::Forms::Control{    public:        CDirect3DControl(void);        ~CDirect3DControl(void);    public:        // I overload the OnCreateControl. I want to put the device        // creation code in this function so that I don't have to bother        // calling it myself.        virtual void OnCreateControl(void) override;    protected:        Direct3D::Device               ^ m_D3DDevice;        Direct3D::PresentParameters    ^ m_PresentParams;};// here is the code used in the OnCreateControl method :using namespace System::Windows::Forms;void CDirect3DControl::OnCreateControl(void){    try    {        Direct3D::AdapterDetails adapterInfo    = Microsoft::DirectX::Direct3D::Manager::Adapters[0];        m_PresentParams	= gcnew Direct3D::PresentParameters();        m_PresentParams->BackBufferFormat       = adapterInfo.CurrentDisplayMode.Format;        m_PresentParams->BackBufferWidth        = this->Width;        m_PresentParams->BackBufferHeight       = this->Height;        m_PresentParams->SwapEffect             = Direct3D::SwapEffect::Discard;        m_PresentParams->AutoDepthStencilFormat = Direct3D::DepthFormat::D24S8;        m_PresentParams->EnableAutoDepthStencil = true;        m_PresentParams->PresentationInterval   = Direct3D::PresentInterval::Immediate;        m_D3DDevice = gcnew Direct3D::Device(0, Direct3D::DeviceType::Hardware, this->Handle, Direct3D::CreateFlags::HardwareVertexProcessing, m_PresentParams);    }    catch (...)    {        MessageBox::Show(L"Error creating hardware device");    }}

But I get an "Invalid call" on the line "m_D3DDevice = gcnew ..."
I don't really understand why :/ The code is almost the same as the one I use in my unmanaged project, and almost the same as the one of the VolumeTextureTool (which I found on the websites linked in your signature ^^) ...

##### Share on other sites
I cannot see anything wrong reallly.
What you might want to try is set the Windowed variable of the PresentParameters to true and see if that works.

I hope this helps.
Take care.

##### Share on other sites
paic    645
I feel stupid ... PP->Windowed didn't exist, so I thought it didn't exist in the MDX ... it was just called IsWindowed, and setting it to true works perfectly ...

Thx again ^^

##### Share on other sites
paic    645
... I wasn't awake when I said it worked : I just had commented the call to the Device creation method, and after uncommented it, it still doesn't work, even with PP->IsWindowed = true;

On quicke question :
when I write "pp = gcnew PresentParameters()", does the constructor of PresentParameters initialize all its member to default values, are should I initialize all of them ? (in unmanaged C++, I had to write "memset(&pp, 0, sizeof(...))")

Edit : ok, my width / height were 0. Seems like in the OnCreateControl, the Control::Height / Width members are still not initialized.