Quantcast
Channel: Programming – Xinyustudio
Viewing all articles
Browse latest Browse all 284

How to use .Net Winform or UserControl in MFC

$
0
0

For VisualStudio 2005 or above versions, refer to below link

http://msdn.microsoft.com/en-us/library/ahdd1h97.aspx
http://msdn.microsoft.com/en-us/library/b1kyh79x(v=VS.80).aspx

The basic idea of this implementation is to use the class CWinFormsControl<NameSpce::WinformClass/UserControlClass> to host .Net Winform or UserControl.

This article presents how to implement this in VS2002 environment.

  • Create a C# project, select “Class Library” project type
    clip_image002
  • Add a UserControl and Winform to the project

clip_image004
SharpCtrl

clip_image006
SharpForm

 

 

  • Compile and run the C# project.
  • Insert a new Visual C++ project, select “MFC Application” as the project type

clip_image008

  • Create a dialog based application in the MFC wizard.

    Add a static control and two buttons in the dialog.
    Set the MFC application as the startup project, and set the dependency to make sure MFC application depends on the CSharp library.
    Compile and run the application, and the result should be as below.

clip_image010

  • In the MFC project setting, change the “Use Managed Extensions” from “No” to Yes.

clip_image011

  • type “#using <mscorlib.dll>” in the dialog.cpp file, compile and run. You will find such errors:

clip_image013

This is due to the conflicting compiling directives. Perform below actions:

Go to the Code Generation Tab, change “Basic Runtime Checks” from “Both (/RTC1, equiv. to /RTCsu)” to “Default”

Go to the Code Generation Tab, change “Enable Minimal rebuild” from “Yes” to “No”

Go to the General Tab,Change “Debug Information Format” from “/ZI” to “/Zi”

clip_image015

clip_image017

clip_image019

  • Rebuild and run, this should be fine now.
  • Add other necessary directives and references as below in the dialog.cpp file
#using <mscorlib.dll> #using <System.Windows.Forms.dll> //Winform #using <System.dll> //System #using “SharpLib.dll” //Our own Library using namespace System; using namespace System::Windows::Forms; //Replace”.” using namespace System::ComponentModel; //with “::”  
  • An compiling error pops up:

clip_image021

This is due to failure in finding the requested dll, in this case, our CSharp library project’s output.

  • To troubleshoot this, in the CSharp project setting, set the output directory to the MFC output directory. Note that the debug and release version should be separately configured.

clip_image023 clip_image025

  • Rebuild and run, this should work fine now.
  • In the MFC dialog.cpp file, create the two event handlers for these two buttons.
    void CMFCMainDlg::OnBnClickedTestSharpCtrl() { SharpForm* sc=new SharpForm(); sc->Visible=true; }  

Now the problem is not that the class SharpForm is not recognized inside MFC, but due to the “new” operator in MFC, specifically in MFC debug mode. The workaround is to temporarily override the “new” definition

void CMFCMainDlg::OnBnClickedTestSharpCtrl() { #pragma push_macro(“new”) #undef new //——————————— SharpForm* sc=new SharpForm(); sc->Visible=true; //——————————— #pragma pop_macro(“new”) }  

See also http://www.codeguru.com/forum/archive/index.php/t-184491.html for details.

  • Rebuild and run, wow, it works!

clip_image027

  • There might be another minor problem: the SharpForm is not a child window of the dialog! What is expected is to embed the dialog into the static control! And to troubleshoot this, add below code:
void CMFCMainDlg::OnBnClickedTestSharpCtrl() { #pragma push_macro(“new”) #undef new //——————————— SharpForm* sc=new SharpForm(); //——————————— #pragma pop_macro(“new”) CWnd* pStaticHolder=GetDlgItem(IDC_STATIC_HOLDER); HWND hParent=pStaticHolder->GetSafeHwnd(); HWND hChild=(HWND)sc->Handle.ToPointer(); ::SetParent(hChild, hParent); sc->Visible=true; sc->Refresh(); }  

Now, the CSharp form can no longer be moved outside the MFC dialog window!

  • To fine tune the location of the SharpForm, call Windows API ::MoveWindow:
CRect rect; pStaticHolder->GetClientRect(&rect); ::MoveWindow(hChild,0,0,rect.Width(),rect.Height(),true); sc->Visible=true;  
  • To get rid of the title bar of the SharpForm, add the below code in CSharpLibrary project:
private void SharpForm_Load(object sender, System.EventArgs e) { this.FormBorderStyle=FormBorderStyle.None; }  

Now, the title is removed!

clip_image029 clip_image031

  • Now, when you drag the dialog to other locations or simply click other client area of the dialog, you will see that the location of the SharpForm remains (or even disappeared), but the parent dialog has already changed. This will result in overlapped windows, which is to be avoided.

clip_image033

  • To make the embedded SharpForm to change accordingly with the move/size changes, define a function:
void CMFCMainDlg::RedrawSharpForm(void) { CWnd* pStaticHolder=GetDlgItem(IDC_STATIC_HOLDER); if(pStaticHolder==NULL || ! IsWindow(hSharpWnd)) return; CRect rect; pStaticHolder->GetClientRect(&rect); ::SetWindowPos( hSharpWnd,HWND_TOP, rect.left, rect.top,rect.right,rect.bottom, SWP_SHOWWINDOW); }  

This function is then called in the CXXXDlg::OnMove() and CXXXDlg::OnSize()to update the child CSharp form’s location.

Note that it is impossible to keep a “SharpForm*” object, as it is not feasible to keep a managed object pointer (reference) in a unmanaged class. However, keeping a handle, (i.e. HWND hSharpWnd) is plausible.

This concludes the tutorial.


Filed under: MFC

Viewing all articles
Browse latest Browse all 284

Trending Articles