Click here to Skip to main content
Click here to Skip to main content

Developing Windows Forms Control using MFC and Managed C++

By , 12 Mar 2002
 

Introduction

Windows Forms is the framework for developing rich client GUI applications under the .NET framework. There are many cool features in Windows Forms which greatly simplify development. The problem is that all the cool controls available at codeproject are written in MFC and cannot be used on Windows Forms Application directly. I know of at least three different ways by which existing controls can be migrated to .NET :-

  1. Rewriting the controls completely in managed code
  2. Making them ActiveX controls and using the ActiveX control on windows forms
  3. Using managed C++.

The purpose of this article is to demonstrate the last of the above techniques.

Demo Control

In order to demonstrate these techniques I select one of my favorite controls in codeproject Mark C. Malburg's Analog Meter Control. The aim is to be able to develop a windows forms control by wrapping the existing MFC control (with little or no changes to the original MFC code).  The final Windows Forms control developed can be placed on windows forms designer as shown in the image.

How the control looks like in the designer

The control has following properties :-

Property Name Property Type Description
Units System::String The text of units shown in the meter
Value double The value which determines the needle position and also shown at the bottom of the control
NeedleColor System::Drawing::Color The color of the needle

In addition the control supports a managed event called  OnValueChanged which is fired whenever the Value property is changed.

To start with we need to create a managed C++ class library with MFC support. I wrote a wizard that does it. The wizard is downloadable from http://www.codeproject.com/useritems/ManagedMFCDLL.asp. Download and install the wizard and also download the source for Analog Meter Control.

Using Managed C++ With MFC

Our aim is to retain as much existing MFC code as possible because all this code has been tested and runs well (assuming). VC++.NET allows to mix managed (a code that is compiled to IL) and unmanaged (native) code. It can even compile existing code to IL. But you cannot use the classes so compiled in other .NET languages unless they are marked with <code>__gc prefix. e.g <code>__gc class MyControl . A class that is marked __gc cannot derive from any class not marked __gc. This rules out use of CObject, CWnd classes as base class as thet are not marked __gc. The other restriction is that __gc classes cannot contain members of any (practically) other classes. But a __gc class can contain a pointer to MFC class. 

In order to develop a windows forms control we need to create a class that extends the managed class (marked with __gc) System::Windows::Forms::Control class just like an MFC custom control extends CWnd.  Within this managed object we will contain an instance of the MFC class. We will make the implementation of properties and methods of the managed control delegate to the MFC class and let the MFC code do all the hard work. The problem is that we need to associate the same window handle (all controls are windows) to both the MFC object and the System::Windows::Forms::Control object. This can be done in two ways :-

  1. Let the windows form control create its window an MFC subclass it.
  2. Let the windows form control superclass the window used by the MFC control.

Both the methods are covered in the article.

Subclassing Windows Forms control through MFC

We start with creating a blank VS.NET solution with any name.

Add a Managed MFC DLL project to the solution using the wizard named Control. This project will be used for any managed classes.

Next add to the solution a Win32 static library project with support  for MFC and precompiled headers. Call this ControlS (S stands for static). This will contain the MFC code for the control. Separation of managed and unmanaged code makes maintenance a bit easier. We will  make the project "Control" dependent on "ControlS" to link them together.

Place the files 3DMeterCtrl.cpp, 3DMeterCtrl.h and MemDC.h in the "ControlS" project. Modify the 3DMeterCtrl.cpp file to remove #include "MeterTestForm.h" as shown

#include "stdafx.h"
#include "math.h"
#include "3DMeterCtrl.h"
<FONT color=#3333ff>//#include "MeterTestForm.h" This line is to be removed</FONT>
#include "MemDC.h"
            

After this the project ControlS would build successfully.

We need to write a managed wrapper for the control. We call this class ThreeDMeter and it should derive from System::Windows::Forms::Control. In order to do this we need to import the required assemblies add required #using's to stdafx.h as shown. Any code that needs to be added is shown in blue

#include <afxwin.h>         // MFC core and standard components
<FONT color=#3333ff>#include "..\Controls\3DMeterCtrl.h"</FONT>
#using <mscorlib.dll>
<FONT color=#6633ff>#using <system.drawing.dll>
#using <system.dll>
#using <system.design.dll>
#using <system.windows.forms.dll></FONT>

Now we can create the main control class. Replace the default class generated by the wizard with class ThreeDMeter.

// Control.h

#pragma once

#include "resource.h"        // main symbols

using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;
using namespace System::Runtime::InteropServices;
using namespace System::Runtime::Remoting::Messaging;

namespace ControlDemo
{
    public __gc class ThreeDMeter : public Control
    {
    public:
        ThreeDMeter()
        {
            m_pCtrl = new C3DMeterCtrl();
        }
    protected:
        void Dispose(bool b)
        {
            Control::Dispose(b);
            
            if (m_pCtrl != NULL)
            {
                delete m_pCtrl;
                m_pCtrl = NULL;
            }
        }

        void OnHandleCreated(EventArgs* e)
        {
            System::Diagnostics::Debug::Assert(m_pCtrl->GetSafeHwnd() == NULL);
            
            m_pCtrl->SubclassWindow((HWND)get_Handle().ToPointer());

            Control::OnHandleCreated(e);
        }
    
    private:
        C3DMeterCtrl* m_pCtrl;
    };
}        
        

Compile and build the DLL. At this time we have got a windows forms control that can be used in a C# or a VB application. To test the control, launch another instance of VS.NET and create a VB or a VC# Windows Application. Add the ThreeDMeter control to the toolbox (Click here if you want to know how to do it). Double clicking on the ThreeDMeter toolbox item adds the control to the form as shown

If you get any errors try modifying the copy local property of the reference to Control assembly to false as shown below (I am not sure why this works, I would be glad if anyone can explain me why setting Copy Local to false makes fixes the problem)

So we have succeeded in wrapping an MFC control around a managed class and using it in the windows forms designer. How exactly does it work?

A windows forms control is a window with style of WS_CHILD by default. When a control is added to the form the window handle is created. When this happens System::Windows::Forms::Control 's protected method OnHandleCreated is called. We overload this method and subclass it with the C3DMeterCtrl object we create, using SubclassWindow method. If you are not familiar with subclassing refer to Chris Maunder's tutorial on Subclassing.

Even though our control paints successfully and can be used in the designer there is not much user can do to modify the behavior of the control. (like changing the needle color or changing the text of units etc.) In the next step we would add properties in the control that would allow us to do this.

Lets add code add the properties using managed extensions to C++ keyword __property. After adding the properties the code looks like this

__property Color get_NeedleColor()
{
    if (!m_pCtrl)
        throw new ObjectDisposedException(__typeof(ThreeDMeter)->ToString());

    return System::Drawing::ColorTranslator::FromWin32(m_pCtrl->m_colorNeedle);
}

__property void set_NeedleColor(Color clr)
{
    if (!m_pCtrl)
        throw new ObjectDisposedException(__typeof(ThreeDMeter)->ToString());

    AFX_MANAGE_STATE(AfxGetStaticModuleState());
            
    m_pCtrl->SetNeedleColor(ColorTranslator::ToWin32(clr));
}

__property void set_Units(String* units)
{
    if (!m_pCtrl)
        throw new ObjectDisposedException(__typeof(ThreeDMeter)->ToString());

    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    CString strUnits(units);
            
    m_pCtrl->SetUnits(strUnits);
}
        
__property String* get_Units()
{
    if (!m_pCtrl)
        throw new ObjectDisposedException(__typeof(ThreeDMeter)->ToString());

    LPCTSTR szUnits = (m_pCtrl->m_strUnits);

    return new String(szUnits);
}
        
__property double get_Value()
{
    if (!m_pCtrl)
        throw new ObjectDisposedException(__typeof(ThreeDMeter)->ToString());
            
    return m_pCtrl->m_dCurrentValue;
}
        
__property void set_Value(double d)
{
    if (!m_pCtrl)
        throw new ObjectDisposedException(__typeof(ThreeDMeter)->ToString());
            
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
            
    m_pCtrl->UpdateNeedle(d);

    OnValueChanged(this, EventArgs::Empty);
}
        

These properties can be called at any time even when the handle is not created. So we need to make sure that none of the MFC methods that make use of Windows handle get called before the window is created this would lead MFC to fire assertions. We fix this in the MFC code in 3DMeterCtrl.cpp as shown

void C3DMeterCtrl::ReconstructControl() 
{
<font color="#0000ff">    if (!GetSafeHwnd())
        return;
</font>
    // if we've got a stored background - remove it!
    if ((m_pBitmapOldBackground) && 
          (m_bitmapBackground.GetSafeHandle()) && 
            (m_dcBackground.GetSafeHdc()))
    {
            m_dcBackground.SelectObject(m_pBitmapOldBackground);
            m_dcBackground.DeleteDC() ;
            m_bitmapBackground.DeleteObject();
    }
    
    Invalidate () ;
}

The above code demostrates a few points

  1. Using properties in C++ (refer to Chris Maunders tutorial on managed C++ properties for more details).
  2. Changing System::Drawing::Color to COLORREF using ColorTranslator
  3. Changing System::String type to CString using the new CString constructor for System::String. (Thanks to Anson Tsao for pointing that to me)
  4. Use of AFX_MANAGE_STATE to ensure proper MFC state. Those of you who developed COM objects using MFC and ATL must be familiar with this.

What we have actually done is to delegate the calls C3DMeterCtrl class. After you build the project it would be possible to set or change these properties from the designer and instantly see the change in the rendering of the control on the VB/VC# form.

It would be really cool if the properties can be organized in the property grid. This can be done simply by using managed C++ attributes e.g.

[property: System::ComponentModel::CategoryAttribute("Meter")]
__property Color get_NeedleColor()
{
    if (!m_pCtrl)
        throw new ObjectDisposedException(__typeof(ThreeDMeter)->ToString());

    return System::Drawing::ColorTranslator::FromWin32(m_pCtrl->m_colorNeedle);
}
        

In the above example we have applied CategoryAttribute to the property NeedleColor. The effect of this attribute can be seen in the property grid after you build the project with these changes.

The thing which is missing from the Control is that it doesn't fire any events. An example event could be OnValueChanged fired when the value changes. The following declaration indicates that the control supports OnValueChanged event.

__event EventHandler * OnValueChanged; 
        

In order to fire the event the set_Value method can be changed as following

__property void set_Value(double d)
{
    if (!m_pCtrl)
        throw new ObjectDisposedException(__typeof(ThreeDMeter)->ToString());
            
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
        
    m_pCtrl->UpdateNeedle(d);

    <FONT color=#6633ff>OnValueChanged(this, EventArgs::Empty);</FONT>
}
        

Thus we have a completely functional control based on an MFC control. The problem with this implementation is that MFC control gets a first shot at the events and not the managed control. This would be a major problem if the control needs to be enhanced later on in managed code for example by deriving another control written C# from this control. This brings us to the next technique - allowing windows forms to superclass our MFC control so that windows forms control gets a first shot at the messages.

Allowing Windows Forms control to superclass existing MFC controls

The System::Windows::Forms::Control class can use an existing Window Class to create its window. This can be done by overloading get_CreateParams method and specifying a new class name. The only restriction is that Window class should be registered with CS_GLOBALCLASS. So we register a new window class in InitInstance and unregister it in ExitInstance as shown

BOOL CControlApp::InitInstance()
{
    CWinApp::InitInstance();
    
    WNDCLASS wc;

    memset(&wc, 0, sizeof(wc));

    wc.lpszClassName = "Analog3dMeter";
    wc.hInstance = m_hInstance;
    wc.lpfnWndProc = Analog3dMeterWindowProc;
    wc.style = CS_DBLCLKS | CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;

    return RegisterClass(&wc);
}

int CControlApp::ExitInstance()
{
    UnregisterClass("Analog3dMeter", m_hInstance);

    return CWinApp::ExitInstance();
}        
        

Now we can overload get_CreateParams method. For demonstration purposes we create a totally new class called ThreeDMeter2 with much of the code same as ThreeDMeter except for the protected methods.

protected:
    void Dispose(bool b)
    {
        Control::Dispose(b);
        
        m_pCtrl = NULL;
    }

    __property System::Windows::Forms::CreateParams * get_CreateParams()
    {
        System::Windows::Forms::CreateParams * pParams = 
                                          Control::get_CreateParams();

        pParams->ClassName = S"Analog3dMeter";
            
        return pParams;
    }
        

Specifying class name as Analog3dMeter makes the window forms control use this window class to create the window for the control. Now the problem is how do we associate m_pCtrl with the window handle so created. This is done at two places. First the CreateHandle method of a control which is actually responsible for creating the window.

void CreateHandle()
{
    __try
    {
        CallContext::SetData(S"Controls.CurrentControl", 
                             __box(IntPtr(m_pCtrl)));
        
        Control::CreateHandle();
    }
    __finally
    {
        CallContext::SetData(S"Controls.CurrentControl", NULL);
    }
}    
        

CallContext is an equivalent (kind of) of ThreadLocal storage here. In the above code we have set a named property for the thread called "Controls.CurrentControl" to the pointer value of  m_pCtrl. Observe __box operator which is used to convert a value type to Object* which is the type of SetData 's second parameter. After setting this property we call base classes implementation which actually calls CreateWindowEx and finally we clear the thread property.

Now the question is how to associate the window handle with the object. The place we need to do is in the Analog3dMeterWindowProc which is the window procedure. The code of the window procedure looks like this

//Retrieves the pointer set earlier in CreateHandle
CWnd* GetPointerFromCallContext()
{
    IntPtr ip = *dynamic_cast<IntPtr*>(CallContext::GetData(S"Controls.CurrentControl"));
    
    return (CWnd*)ip.ToPointer();
}

#pragma unmanaged

LRESULT CALLBACK Analog3dMeterWindowProc(HWND hwnd, UINT msg, 
                                         WPARAM wp, LPARAM lp)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    CWnd* pWnd = CWnd::FromHandlePermanent(hwnd);
    
    if (pWnd == NULL)
    {
        pWnd = GetPointerFromCallContext();
        ASSERT(pWnd != NULL);
        pWnd->Attach(hwnd);
    }
    
    LRESULT ret = AfxCallWndProc(pWnd, hwnd, msg, wp, lp);
    
    if (msg == WM_NCDESTROY)
        delete pWnd;

    return ret;
}

In the window procedure we first check to see if the window is already in the permanent handle map. If not (which is the case when the control gets the WM_NCCREATE message), obtain the object pointer from call context, which we set originally in the CreateHandle method, and attach the window handle to it. Once we have done that we call AfxCallWndProc to do all the hard work of window message handling. Finally, we delete the object pointer when we get WM_NCCDESTROY message.

Looking at the window through spy++ shows certain interesting things :-

Observe that the name of the class in WindowForms10.Analog3dMeter.xxx This is because windows forms framework superclasses our window class and uses the superclass to create our control.

There is one small implementation detail which I in the constructor of the ThreeDMeter2

ThreeDMeter2()
{
    m_pCtrl = new C3DMeterCtrl();
    SetStyle(ControlStyles::UserPaint, false);
}

The SetStyle(ControlStyles::UserPaint, false) makes it possible for the WM_PAINT messages to be forwarded to the original window proc Analog3dMeterWindowProc instead of them being handled in the managed code.

The class ThreeDMeter2 demonstrates that way windows forms superclasses an existing window class. We could have managed to do the something without creating a superclassed window. The control ThreeDMeter3 demonstrates this.

void DefWndProc(Message* m)
{
    if (m_pCtrl)
    {
        if (!m_pCtrl->GetSafeHwnd())
        {
            m_pCtrl->Attach((HWND)m->HWnd.ToPointer());
        }

        m->Result = AfxCallWndProc(m_pCtrl, (HWND)m->HWnd.ToPointer(), 
                                   m->Msg, (WPARAM)m->WParam.ToPointer(), 
                                   (LPARAM)m->LParam.ToPointer());
    }
    else
        //This woul happen after destroy messages
        Control::DefWndProc(m);
}

void OnHandleDestroyed(EventArgs* e)
{
    if (m_pCtrl)
    {
        m_pCtrl->Detach();
        delete m_pCtrl;
        m_pCtrl = NULL;
    }
}

In ThreeDMeter3 we don't create any separate window class. We don't overload CreateHandle or get_CreateParams. We let Control do it's default creation. Instead we load DefWndProc and OnHandleDestroyed. DefWndProc is the function responsible for forwarding the call to the superclassed window procedure (if the control superclassed any window or else to the DefWindowProc function). We overload that and forward the calls to m_pCtrl using AfxCallWndProc. Finally we detach and delete m_pCtrl in OnHandleDestroyed function. Even though this method looks simpler this is not very clean (in my opinion) as there are two potential routes to DefWindowProc one through MFC implementation and other through System::Windows::Forms::Control 's implementation.

Thus, in short I have covered certain ways by which existing MFC controls can be moved to Windows Forms without completely rewriting them.

My special thanks to Mark C. Malburg for making his code available. My special thanks to Essam Ahmed for proof reading the article.

Updates

3/13/2002

  1. Modified string properties to use CString constructor for System::String*
  2. Added ThreeDMeter3

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Rama Krishna Vavilala
Architect
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionUsing MFC Controls in Managed C++ VS2008memberjoswr1ght2 Nov '08 - 5:33 
I'm a little stuck converting the 3D Meter control in this article using VS2008. The use of __gc requires /clr:oldSyntax.
 
Is there a preferred method for leveraging MFC controls in VS2008 managed C++?
 
Thanks,
 
-Josh
AnswerRe: Using MFC Controls in Managed C++ VS2008memberRama Krishna Vavilala2 Nov '08 - 5:42 
The article is fairly outdated. I will have to revise it some day.
 
The overall concept will work you may have to struggle with syntax a little bit.
 
Proud to be a CPHog user

GeneralRe: Using MFC Controls in Managed C++ VS2008memberjoswr1ght2 Nov '08 - 13:13 
Thanks Rama. Any pointers would be most appreciated.
 
-Josh
AnswerRe: Using MFC Controls in Managed C++ VS2008memberBart Jolling25 Nov '08 - 22:40 
I have given this a go on my blog for the first part of the article:
http://bartjolling.blogspot.com/2008/11/developing-windows-forms-control-using.html[^]
 
- Bart
Generalcan't find DLLmemberJPM200930 Oct '08 - 13:07 
your URL "http://www.codeproject.com/useritems/ManagedMFCDLL.asp." can't be located when I click on it.
Do you have a fix or another location where I can find your wizard?
QuestionCreating VC# ActiveX Control for other Visual Studio languages (or for VC++)memberAniket Salunkhe18 Sep '08 - 0:41 
Hi,
 
I want to create a C# (ActiveX) Control (using VC# 2008 .Net) that can be used in any language (mainly in VC++ 2008 .Net).
 

Please help me for that.
 
Thanks in advance.
 
Regards,
Aniket A. Salunkhe
Generalcannot view C# inherited Form in designer having refernce to C+/CLI wrappermemberramki_mars24 Apr '08 - 1:01 
Hi,
 
I am trying to open window form in designer (this form inherits another window form
 
"BaseForm") ,
am getting exception and Visual studio is asking to debug or cancel message alert.
 
I debugged and its said "Could not load file or assembly 'Wrappers.CLI,
Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies.
The system cannot find the file specified. "
 
The WSOD contains:
 
One or more errors encountered while loading the designer. The errors are listed below. Some
 
errors can be fixed by rebuilding your project, while others may require code changes.
 
"Could not load file or assembly 'Wrappers.CLI, Version=0.0.0.0, Culture=neutral,
 
PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified"
Hide
 
at MyProject.BaseForm..ctor()
 
this is in C# project it has refernce to 'Wrappers.CLI' dll.
 
When running the solution enery thing is working fine but when opening the design only it is throwing this excepetion.
I tried
 
1. rebuilding (deleting the dlls from debug folder)
2. steps in http://www.codeproject.com/KB/cs/wsod.aspx
but none was working..
 
Thanks,
Ramki
GeneralNeed help: I Failed to wrap regular MFC controls i.e. CEdit, CCombobox, (only owner drawn MFC controls - and direct CWnd inherited)memberbibiking16 Apr '08 - 2:41 
Using VS2005 SP1
Has any one here encountered this problem?
No way it went smooth for you guys, while I'm eating dirt here..
Help of any kind will be appreciated
 
bad025

GeneralMuch urgent!memberkellyonlyone5 Nov '07 - 1:55 
Thanks again for this nice sample!
For my own project, we used a few resources with my library (Such as icon, bitmap, cursor...), but when I tested it with C#, it crashes. Debug showes it cann't find the resources, who can help me?
 
Thanks
Kelly

GeneralRe: Much urgent!memberbibiking16 Apr '08 - 2:32 
call
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
 
before any use of resource
 
bad025

QuestionHow can I raise a managed control event from the unmanaged 3DMeterCtrl ? [modified]memberpanenhan16 Apr '07 - 18:08 
Great excellent Article!
And I have one question, very important, how can I raise a control event from the 3DMeterCtrl object? The managed control can raise some events, of course, when changed the unmanaged MFC control value members, but I need the more. For example, when the unmanaged 3DMeterCtrl re-painted, the managed control raises the OnPainted event. I got a solution to deal with this request which I will explain after, and I wander is there any better solution? Any suggestion is welcome!Big Grin | :-D
OK, it's time to describe my solution now.;) I have to notice you that I'm using VS 2005.
First step: at the 3DMeterCtrl.h header file, add two lines code like this:

#include "ThreeDMeter.h"
using namespace ControlDemo;

Then, add another two lines code to the unmanaged class declare space:

class C3DMeterCtrl : public CWnd
{
friend ref class ThreeDMeter; // add to make the managed class can access all the MFC class functions. Not essential
// Construction
public:
C3DMeterCtrl();
gcroot m_pManagedControl; // add to make the unmanaged class can access the managed control functions. Note that 'gcroot'.

Third, we change our eyes to the managed control class. At the ThreeDMeter.h, add the OnPainted event declare code:

event EventHandler^ OnPaintedChanged;

And a public function :

public: void RaisePaintedEvent(void);

The next steps, at the managed control class contrution implementation, add this code:

ThreeDMeter::ThreeDMeter( void )
{
m_pCtrl = new C3DMeterCtrl();
m_pCtrl->m_pManagedControl = this; // add
}

The final step : at the unmanaged class raise the event like this:
void C3DMeterCtrl::OnPaint()
{
.... // do all the works
m_pManagedControl->RaisePaintedEvent();
}

Done! We raise the managed class event from the unmanaged class. It seems very simple, right? But there is a problem: the RaisePaintedEvent function is declare as public, any one can call it from the out side of assembly! If you have the better idea to deal with this problem, please let me known. Thank you!Smile | :)
 

 
-- modified at 0:43 Wednesday 9th May, 2007
GeneralPreTranslateMessage not firingmemberMrNed25 Mar '06 - 23:29 
My control uses PreTranslateMessage to detect keystrokes (pMsg->message == WM_KEYDOWN) and act accordingly. However, with this method it no longer seems to fire. Can anyone help me?
GeneralRe: PreTranslateMessage not firingmemberbibiking16 Apr '08 - 2:35 
it will not be called.
the handling is done by the managed c++ control class.
Instead, override the DefWinProc (make sure to forward this call to base class)
it contains all messages
 
bad025

GeneralExcellent stuff RamastaffNishant Sivakumar12 Jan '06 - 5:29 
Cool | :cool:
 
Regards,
Nish
 

Generalpictures and sourcemembermsymalla27 Nov '05 - 23:02 
Hello,
 
I have problems downloading the source ("Page not found") and also the pictures inside this great article are not shown. Is this a general problem or a fault on my side?
 
Greeting
Mitch
GeneralA few questionsmemberTomer Noy25 Sep '05 - 21:33 
Great article! It's amazing how simple these things are when you have a good step by step tutorial.
 
1) I want to use this technique in my project; however, my manager is afraid that using internal techniques like these isn't recommended by Microsoft and might cause problems in the future. Does anyone know of any reference of Microsoft developers to this article?
 
2) The Managed MFC Dll Wizard doesn't work in Visual Studio 2005. I tried to configure such a Dll by myself and ran into a lot of problems. I'd appriciate a reference to a tutorial on how to do this manualy (including project configuration).
 
3) Are there any improvements in wrapping MFC controls in Visual Studio 2005 and the C++/CLI?
 
-- modified at 6:25 Monday 26th September, 2005
Generalcrush with create functionmemberib200321 Apr '05 - 5:02 
I am getting an error when excuting a create function.
I try to add somthing like :
 
C3DMeterCtrl::C3DMeterCtrl()
{
m_dCurrentValue = 0.0 ;
m_dMaxValue = 5.0 ;
m_dMinValue = -5.0 ;
 
m_nScaleDecimals = 1 ;
m_nValueDecimals = 3 ;
 
m_strUnits.Format("Volts") ;
 
m_colorNeedle = RGB(255, 0, 0) ;

//Added code
CToolTipCtrl tooltip;
tooltip.Create(this);//error happen here
 
}
 
anyone have a clue!
GeneralRe: crush with create functionmemberbibiking16 Apr '08 - 2:47 
Come on man - it too soon to call Create while C3DMeterCtrl::m_hWnd is null.
implement ON_WM_CREATE()
 
int CyourControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(!CBase::OnCreate(lpCreateStruct))
{
CToolTipCtrl tooltip;
tooltip.Create(this);
}
 

return 0;
}
 
bad025

GeneralDrawItem not getting called...membershareeef15 Jul '04 - 6:54 
I used the first approach to subclass ownerdrawn combo box. But I am not getting the DrawItem call back in the unmanaged control. Do I have to do anything else.
 
Thanks.
GeneralRe: DrawItem not getting called...memberJohn Stephens6 Aug '04 - 17:02 
It is because the WM_NOTIFY message needed for owner draw is reflected as OCM_NOTIFY by the parent.
 
It has something to do with the Winform container control acting like an ActiveX container.
 
I was able to get an ownerdraw list view working by handling OCM_NOTIFY in the MFC control's WindowProc and calling my DrawItem function.
 
Also, I was only able to get technique #1 to work.
I think it is because the DefWndProc should be point to the common control but when using method #2 or #3, the common controls proc gets lost.
 
Let me know if you need further info. I spent about 2 weeks trying to get it working. Finally appear to have.
GeneralDeveloping Windows Forms using MDI classes (CDocTemplate,CDocument, CView, CMDIChildWnd)membershalnov15 Apr '04 - 5:14 
I have old complicated MDI with some DocTemplates, Views and so on. Can I use this way for connect my forms with this MDI? When I try create Frame window I need pParentWnd:
 
     CMultiDocTemplate* pDocTemplate;
     pDocTemplate = new CMultiDocTemplate(IDR_tmpTYPE,
          RUNTIME_CLASS(CtmpDoc),
          RUNTIME_CLASS(CChildFrame), // custom MDI child frame
          RUNTIME_CLASS(CtmpView));
            CWnd* pParentWnd = CWnd::FromHandlePermanent(Handle.ToInt32);
 

            m_pNewFrm = pDocTemplate ->CreateNewFrame(pDoc,(CFrameWnd*)pParentWnd);
 
But it always NULL!!!!Cry | :((
GeneralRe: Developing Windows Forms using MDI classes (CDocTemplate,CDocument, CView, CMDIChildWnd)memberbibiking16 Apr '08 - 2:49 
You must read this article

[^]
 
bad025

GeneralRe: Developing Windows Forms using MDI classes (CDocTemplate,CDocument, CView, CMDIChildWnd)memberbibiking16 Apr '08 - 2:51 
http://www.codeproject.com/KB/miscctrl/HostMFC.aspx
 
bad025

GeneralRe: Developing Windows Forms using MDI classes (CDocTemplate,CDocument, CView, CMDIChildWnd)memberAlexey Shalnov16 Apr '08 - 23:48 
Thanks, but it's my article Smile | :)
GeneralUsing Windows Forms Control in MFCmemberJain Mohit10 Mar '04 - 20:22 
I am trying to achieve the vice versa of this article. i.e. Use a Win Form Control in MFC, and place it on a CWnd. Any suggestion how to do so.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 13 Mar 2002
Article Copyright 2002 by Rama Krishna Vavilala
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid