在 C++ 中使用 Winform 作为视图

Posted

技术标签:

【中文标题】在 C++ 中使用 Winform 作为视图【英文标题】:Using a Winform as a View in C++ 【发布时间】:2012-08-28 07:06:11 【问题描述】:

我试图在我的 MFC 应用程序中使用 Winform 作为视图,但我似乎无法让它工作。它编译并运行,但是在启动视图时它崩溃,表明无法创建控件: afxwinforms.inl

return CreateControl(info,dwStyle,&pt,&size,pParentWnd,nID);

有人可以在这里帮助我吗,将不胜感激 我目前有以下代码:

MyWinFormsView .h:

#pragma once
#include <vcclr.h>
#include <afxwinforms.h>
#include "MyViewUserControl.h"

#include "MyDoc.h"

// CMyWinFormsView view

class CMyWinFormsView : public CWinFormsView

    DECLARE_DYNCREATE(CMyWinFormsView)

protected:
    CMyWinFormsView();           // protected constructor used by dynamic creation
    virtual ~CMyWinFormsView();

public:
    CMyDoc* GetDocument();
    DspAnalog::MyViewUserControl^ GetControl();

public:
    virtual void OnDraw(CDC* pDC);      // overridden to draw this view
#ifdef _DEBUG
    virtual void AssertValid() const;
#ifndef _WIN32_WCE
    virtual void Dump(CDumpContext& dc) const;
#endif
#endif

protected:
    DECLARE_MESSAGE_MAP()
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
public:
    virtual void OnInitialUpdate();
protected:
    virtual void PostNcDestroy();

public:

BEGIN_DELEGATE_MAP( CMyWinFormsView )
END_DELEGATE_MAP()

    //afx_msg void OnTextChanged(System::Object ^ o, System::EventArgs ^ e);
    //afx_msg void OnSaveChangesClick(System::Object ^ o, System::EventArgs ^ e);
;

#ifndef _DEBUG  // debug version in View.cpp
inline CMyDoc* CMyWinFormsView::GetDocument()
    return (CMyDoc*)m_pDocument; 
#endif

MyWinFormsView.cpp:

#include "stdafx.h"
#include "MyWinFormsView.h"
#include "MyViewUserControl.h"


// CMyWinFormsView

IMPLEMENT_DYNCREATE(CMyWinFormsView, CWinFormsView)

CMyWinFormsView::CMyWinFormsView() : CWinFormsView(DspAnalog::MyViewUserControl::typeid)



CMyWinFormsView::~CMyWinFormsView()



BEGIN_MESSAGE_MAP(CMyWinFormsView, CWinFormsView)
END_MESSAGE_MAP()



// CMyWinFormsView drawing

void CMyWinFormsView::OnDraw(CDC* pDC)

    CMyDoc* pDoc = GetDocument();


// CMyWinFormsView diagnostics

#ifdef _DEBUG
void CMyWinFormsView::AssertValid() const

    CWinFormsView::AssertValid();


#ifndef _WIN32_WCE
void CMyWinFormsView::Dump(CDumpContext& dc) const

    CWinFormsView::Dump(dc);

#endif

CMyDoc* CMyWinFormsView::GetDocument() // non-debug version is inline

    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc)));
    return (CMyDoc*)m_pDocument;


#endif //_DEBUG

DspAnalog::MyViewUserControl^ CMyWinFormsView::GetControl()

    System::Windows::Forms::Control^ control = CWinFormsView::GetControl();
    return safe_cast<DspAnalog::MyViewUserControl^>(control);



BOOL CMyWinFormsView::PreCreateWindow(CREATESTRUCT& cs)

    return CWinFormsView::PreCreateWindow(cs);


void CMyWinFormsView::OnInitialUpdate()

    CWinFormsView::OnInitialUpdate();

    // *** Workaround bottom dock initial sizing issue
   /*   System::Windows::Forms::ScrollableControl ^scrlCtrl = dynamic_cast<System::Windows::Forms::ScrollableControl^>(GetControl());
    if (scrlCtrl != nullptr)
       
        CRect rcView;
        GetClientRect(&rcView);
        System::Drawing::Size size(0,0);
        scrlCtrl->AutoScrollMinSize = size;
    */
    // *** End workaround

    CMyDoc* pDoc = GetDocument();
    DspAnalog::MyViewUserControl^ viewControl = GetControl();


void CMyWinFormsView::PostNcDestroy()

    CWinFormsView::PostNcDestroy();

MyViewUserControl.h:

#pragma once
    #using <mfcmifc80.dll>

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    //using namespace System::Runtime::InteropServices;

namespace MyDsp 


    /// <summary>
    /// Summary for MyViewUserControl
    /// </summary>
    public ref class MyViewUserControl : public System::Windows::Forms::UserControl,
                                         public Microsoft::VisualC::MFC::IView,
                                         public Microsoft::VisualC::MFC::ICommandTarget
    
    public:
    MyViewUserControl(void)
    
        InitializeComponent();
        //
        //TODO: Add the constructor code here
        //
    

    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~MyViewUserControl()
        
            if (components)
            
                delete components;
            
        
    private: DevExpress::XtraEditors::SimpleButton^  simpleButton1;
    protected: 

    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>
        System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent(void)
        
            this->simpleButton1 = (gcnew DevExpress::XtraEditors::SimpleButton());
            this->SuspendLayout();
            // 
            // simpleButton1
            // 
            this->simpleButton1->Location = System::Drawing::Point(44, 101);
            this->simpleButton1->Name = L"simpleButton1";
            this->simpleButton1->Size = System::Drawing::Size(75, 23);
            this->simpleButton1->TabIndex = 0;
            this->simpleButton1->Text = L"simpleButton1";
            // 
            // MyViewUserControl
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->Controls->Add(this->simpleButton1);
            this->Name = L"MyViewUserControl";
            this->ResumeLayout(false);

        
#pragma endregion

    public:
        // Implementing IView and ICommandTarget interfaces
        virtual void OnInitialUpdate();
        virtual void OnUpdate();
        virtual void OnActivateView(bool bActivate);
        virtual void Initialize(Microsoft::VisualC::MFC::ICommandSource^ cmdSrc);
        System::Void Command1Handler(System::UInt32 cmdUI);
        int iActivateCount;
    ;

MyViewUserControl.cpp

#include "MyViewUserControl.h"

namespace MyDsp 


#define ID_CVIEWCMDS_COMMAND1   32771

void MyViewUserControl::OnInitialUpdate()

    this->iActivateCount = 0;


void MyViewUserControl::OnUpdate()



void MyViewUserControl::OnActivateView(bool activate)

    this->iActivateCount++;


void MyViewUserControl::Initialize(Microsoft::VisualC::MFC::ICommandSource^ cmdSrc)

    //Microsoft::VisualC::MFC::CommandHandler^ command;

    //command = gcnew Microsoft::VisualC::MFC::CommandHandler( this, &MyViewUserControl::Command1Handler );

    // Use the same control ID as in the resource.h of the MFC project
    //cmdSrc->AddCommandHandler( ID_CVIEWCMDS_COMMAND1, command );


// Handler for the MFC menu command

void MyViewUserControl::Command1Handler(System::UInt32 cmdUI)

    //this->toolStripStatusLabel1->Text = "Selected Command1";


【问题讨论】:

当您的任何应用程序崩溃时,您的第一反应应该是在调试器中运行程序。它将帮助您定位程序崩溃的位置,让您查看函数的调用方式和位置,并让您检查变量和参数以帮助您了解是什么可能导致崩溃。 就像我说的,但是我忘了提到行号 (122) afxwinforms.inl return CreateControl(info,dwStyle,&pt,&size,pParentWnd,nID); 是的,但它是一个系统文件。如果您将调用堆栈向上转到您的代码,那在哪里? wfrmview.cpp 第 108 行 fSucceeded=fSucceeded && m_control.CreateManagedControl(m_pManagedViewType,WS_VISIBLE, rect, this,nID); 【参考方案1】:

你知道the microsoft mfc-winform integration example吗?

开始的一些提示: 不要在 System... 命名空间上使用 using,导致 c++/cli 有时不匹配

看例子中每个c++文件的编译器选项,有很多东西要设置(/clr等)

【讨论】:

其实我是以此为出发点的。好的,所以现在我决定在我的项目中使用示例中的代码,并尝试首先让它工作。现在我遇到以下问题:使用命名空间 System::Runtime::InteropServices;原因:错误 C2872:'FILETIME':模棱两可的符号,所以现在我坚持使用 FILETIME 的多个定义:S 删除使用命名空间 System::Runtime::InteropServices;解决了这个问题,但我仍然有我原来的问题,解决方案现在构建并运行,但是当创建视图时,它在 wfrmview.cpp 第 108 行崩溃 fSucceeded=fSucceeded && m_control.CreateManagedControl(m_pManagedViewType,WS_VISIBLE, rect, this,nID); 为什么需要winform作为mfc视图,就不能使用带有winform控件的原生mfc视图吗?

以上是关于在 C++ 中使用 Winform 作为视图的主要内容,如果未能解决你的问题,请参考以下文章

如何在 c++ winform 中同时运行两个函数?

WPF与WinForm

winform程序访问Microsoft.Win32空间的问题

HwndHost for Windows Form - Win32 / WinForm 互操作性

解决Winform应用程序中窗体背景闪烁的问题

解决Winform应用程序中窗体背景闪烁的问题