please I need your help, I googled a lot and any answer for this problem....
I have a solution that includes various Unmanaged C++ projects, but now I need to use a Visual C++ Form (that is Managed) into the main unmanaged project, and comunicate with it. It's possible to do it? via wrapper, dll.... how?
I googled a lot but all the cases I found talk about how use Unmanaged into Managed, or are incomplete examples. I found this example and seems that it works, but doesn't compile.
http://www.codeproject.com/Articles/9903/Calling-Managed-Code-from-Unmanaged-Code-and-vice
I'm using Visual Studio 2012.
Thanks a lot.
Finally I found a solution...
1 - When I want to have the FORM control into non managed code (for create, show, hide, set controls value...) I exported static methods as __declspec(dllexport)
2 - When I want to send info from FORM to non managed code I do it using callbacks.
I'm going to explain it....
Firstly... I create a CLR project as DLL, create a windows Form (MyForm.h) with some controls:
(I ommit the gode generated by visual studio)
namespace TestUnmanaged {
... code ommitted ...
private: System::Void QuitBtn_Click(System::Object^ sender, System::EventArgs^ e) {
this->Close();
}
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
//Call to non managed function!!!!
CallToCallBack();
}
};
}
Then, I create a static (non managed) class that has a pointer to the form, and manage it's creation, etc..
//Type of my specific callback function
typedef std::function<bool (int& _msg)> T_CALLBACK_FUNC;
public class unmanagedClass
{
public:
unmanagedClass();
~unmanagedClass();
void CreateForm( void );
HWND getFormHandle(void) const;
void setCallbackFunction(T_CALLBACK_FUNC _callbackFuntion);
void callToCallbackFunction(int _value);
//public for fast tests
gcroot<TestUnmanaged::MyForm^> p;
private:
HWND m_hWnd;
T_CALLBACK_FUNC m_funcionCallback;
};
unmanagedClass s_unmanaged;
Here's the .cpp implementation...
//////////////////////////////////////////////////////////////////////////
// Static Functions for DLL_EXPORT
//////////////////////////////////////////////////////////////////////////
void CloseForm( void )
{
Application::Exit();
}
void CallToCallBack( void )
{
int valor = 5;
s_unmanaged.callToCallbackFunction(valor);
}
//////////////////////////////////////////////////////////////////////////
// Methods for Unmanaged Class
//////////////////////////////////////////////////////////////////////////
HWND unmanagedClass::getFormHandle( void ) const
{
return m_hWnd;
}
unmanagedClass::unmanagedClass()
{
p = gcnew(TestUnmanaged::MyForm);
}
unmanagedClass::~unmanagedClass()
{
delete (p);
}
void unmanagedClass::CreateForm( void )
{
Application::Run(p);
}
void unmanagedClass::setCallbackFunction( T_CALLBACK_FUNC _callbackFuntion )
{
m_funcionCallback = _callbackFuntion;
}
void unmanagedClass::callToCallbackFunction( int _value )
{
m_funcionCallback(_value);
}
Now, I create all the static functions that will be exported as dllexport:
__declspec(dllexport) void CreateFormDLL(void)
{
s_unmanaged.CreateForm();
}
__declspec(dllexport) void CloseFormDLL(void)
{
s_unmanaged.p->Close();
}
__declspec(dllexport) void ShowFormDLL(void)
{
s_unmanaged.p->Show();
}
__declspec(dllexport) void HideFormDLL(void)
{
s_unmanaged.p->Hide();
}
__declspec (dllexport) void setCallbackFunctionDLL( T_CALLBACK_FUNC& _doFunction)
{
s_unmanaged.setCallbackFunction(_doFunction);
}
__declspec (dllexport) void setCheckBoxDLL( bool _newValue )
{
s_unmanaged.p->getCam01ChkBox()->Checked = _newValue;
}
__declspec (dllexport) HWND getFormHandleDLL( void )
{
return (HWND)s_unmanaged.p->Handle.ToPointer();
}
Now.... I create the Win32 console App project and link the Managed project. This will be the main process, and the class "ManagedWrapper". Here is the source....
class ManagedWrapper
{
public:
ManagedWrapper(void);
~ManagedWrapper(void);
void init(void);
void createForm(void);
void showForm(void);
void closeForm(void);
void setCam01ChkBox(const bool _newValue);
private:
void createFormThread(void);
static bool callBackReceiver(int a);
};
#include "ManagedWrapper.h"
#include <thread>
__declspec(dllimport) void CreateFormDLL(void);
__declspec(dllimport) void CloseFormDLL(void);
__declspec(dllimport) void ShowFormDLL(void);
__declspec(dllimport) void HideFormDLL(void);
typedef std::function<bool (int& _msg)> T_CALLBACK_FUNC;
__declspec (dllimport) void setCallbackFunctionDLL( T_CALLBACK_FUNC& _doFunction);
__declspec (dllimport) void setCheckBoxDLL( bool _newValue );
ManagedWrapper::ManagedWrapper(void)
{
}
ManagedWrapper::~ManagedWrapper(void)
{
}
void ManagedWrapper::createForm( void )
{
std::thread showThread (&ManagedWrapper::createFormThread, this);
showThread.detach();
}
void ManagedWrapper::createFormThread( void )
{
CreateFormDLL();
}
void ManagedWrapper::closeForm( void )
{
CloseFormDLL();
}
void ManagedWrapper::showForm( void )
{
ShowFormDLL();
}
void ManagedWrapper::init( void )
{
setCallbackFunctionDLL(T_CALLBACK_FUNC(&ManagedWrapper::callBackReceiver));
}
bool ManagedWrapper::callBackReceiver( int a )
{
printf("Hello world. Parameter value = %d\n",a);
return true;
}
void ManagedWrapper::setCam01ChkBox( const bool _newValue )
{
setCheckBoxDLL( _newValue );
}
And finally.... the simplest use from the main()
, create the Form, set the checkbox values, if the user click on the button the callback function writes on console... and finally close.
int _tmain(int argc, _TCHAR* argv[])
{
ManagedWrapper umWrap;
umWrap.init();
umWrap.createForm();
system("PAUSE");
umWrap.setCam01ChkBox(true);
system("PAUSE");
umWrap.setCam01ChkBox(false);
system("PAUSE");
umWrap.closeForm();
return 0;
}
Sorry for the long answer, but I believe that may be usefull for somebody.