C#如何调用ActiveQT com控件的C++类?

建立ActiveQt项目

自动生成的demo代码如下:

#include "ActiveQtServerHourse.h"
#include <ActiveQt/QAxFactory>

ActiveQtServerHourse::ActiveQtServerHourse(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
}
QAXFACTORY_DEFAULT(ActiveQtServerHourse, //暴露给外部的类的名称,我们这里暴露的类名称为ActiveQtServerHourse,先就这么写
    "{82a36901-0766-498b-beaf-8b3e62e0b530}", //类ID,如果是一个DLL需要暴露多个类的话,调用的时候是通过这个ID连接到指定的类
    "{b8de8377-4185-4c9d-a803-77b1939b1360}", //接口ID,不用管
    "{70744dbb-3062-4ade-9a0c-fc42dafa5b8f}", //事件ID,不用管,如果当前的类需要发送事件的话需要定义
    "{f763f5b7-cc63-4a05-9757-9debc4a7078d}", //当前lib 的ID,这个是这个lib的唯一标识,如果只有一个类导出,我们可能会需要用到这个东西
    "{cd0da224-8eec-4739-a342-ecf88f6d3259}" //当前进程ID,这个如果是你将这个COM组件设定为EXE,那么我们可能就需要通过这个来建立连接

定义需要导出的类

QAXFACTORY_DEFAULT()宏的作用是导出一个AxtiveX控件,可以用于仅导出一个控件的ActiveX server。

当server要导出多个控件时,也就是一个DLL需要暴露多个类,需要重新修改代码格式:

ActiveQtServerHourse.h

#pragma once

#include <QtWidgets/QWidget>
#include <ActiveQt/QAxBindable>

#include "ui_ActiveQtServerHourse.h"

class ActiveQtServerHourse : public QWidget, public QAxBindable
{
    Q_OBJECT
        Q_CLASSINFO("ClassID", "{4f09dbb6-672f-46fa-89c6-06acc997209d}")
        Q_CLASSINFO("InterfaceID", "{54e54ad8-17db-4fd1-8156-a6a9f10ac8dd}")

public:
    ActiveQtServerHourse(QWidget *parent = nullptr);

private:
    Ui::ActiveQtServerHourseClass ui;
};

上面定义了有关这个类的属性,也就是ClassID,InterfaceID,EventsID。

类需要继承QObject和QAxBindable,前者可以保证signals和slots的使用,后者可以保证signals和slots和COM函数和事件对接上。

Qt官方demo一起集成里面

COM App Example (ActiveQt) | Active Qt 6.7.1

Document.h

#pragma once
#include <QObject>
#include <QApplication>
#include <QAxFactory>
#include <QTabWidget>
#include <QScopedPointer>
#include <QTimer>
#include <QList>


class Application;
class DocumentList;

class Document :  public QObject
{
    Q_OBJECT

        Q_CLASSINFO("ClassID", "{2b5775cd-72c2-43da-bc3b-b0e8d1e1c4f7}")
        Q_CLASSINFO("InterfaceID", "{2ce1761e-07a3-415c-bd11-0eab2c7283de}")

        Q_PROPERTY(Application* application READ application)
        Q_PROPERTY(QString title READ title WRITE setTitle)

public:
    explicit Document(DocumentList* list);
    virtual ~Document();

    Application* application() const;

    QString title() const;
    void setTitle(const QString& title);

private:
    QScopedPointer <QWidget> m_page;
};

class DocumentList : public QObject
{
    Q_OBJECT

        Q_CLASSINFO("ClassID", "{496b761d-924b-4554-a18a-8f3704d2a9a6}")
        Q_CLASSINFO("InterfaceID", "{6c9e30e8-3ff6-4e6a-9edc-d219d074a148}")

        Q_PROPERTY(Application* application READ application)
        Q_PROPERTY(int count READ count)

public:
    explicit DocumentList(Application* application);

    int count() const;
    Application* application() const;

public slots:
    void addDocument(Document*);
    Document* addDocument();
    Document* item(int index) const;

private:
    QList<Document*> m_list;
};
//! [1]

//! [2]
class Application : public QObject
{
    Q_OBJECT
        Q_CLASSINFO("ClassID", "{b50a71db-c4a7-4551-8d14-49983566afee}")
        Q_CLASSINFO("InterfaceID", "{4a427759-16ef-4ed8-be79-59ffe5789042}")
        //Q_CLASSINFO("RegisterObject", "yes")

        Q_PROPERTY(DocumentList* documents READ documents)
        Q_PROPERTY(QString id READ id)
        Q_PROPERTY(bool visible READ isVisible WRITE setVisible)

public:
    explicit Application(QObject* parent = nullptr);
    DocumentList* documents() const;

    QString id() const { return objectName(); }

    void setVisible(bool on);
    bool isVisible() const;

    QTabWidget* window() const { return m_ui.data(); }

public slots:
    void quit();

private:
    QScopedPointer <DocumentList> m_docs;
    QScopedPointer <QTabWidget> m_ui;
};

Document.cpp

#include "Document.h"

Document::Document(DocumentList* list)
    : QObject(list)
{
    QTabWidget* tabs = list->application()->window();
    m_page.reset(new QWidget(tabs));
    m_page->setWindowTitle(tr("Unnamed"));
    tabs->addTab(m_page.data(), m_page->windowTitle());

    m_page->show();
}

Document::~Document() = default;

Application* Document::application() const
{
    return qobject_cast<DocumentList*>(parent())->application();
}

QString Document::title() const
{
    return m_page->windowTitle();
}

void Document::setTitle(const QString& t)
{
    m_page->setWindowTitle(t);

    QTabWidget* tabs = application()->window();
    int index = tabs->indexOf(m_page.data());
    tabs->setTabText(index, m_page->windowTitle());
}

//! [3] //! [4]
DocumentList::DocumentList(Application* application)
    : QObject(application)
{
}

Application* DocumentList::application() const
{
    return qobject_cast<Application*>(parent());
}

int DocumentList::count() const
{
    return m_list.size();
}

Document* DocumentList::item(int index) const
{
    return m_list.value(index, nullptr);
}

void DocumentList::addDocument(Document* document) {
    m_list.append(document);
}

Document* DocumentList::addDocument()
{
    Document* document = new Document(this);
    m_list.append(document);

    return document;
}

//! [4] //! [5]
Application::Application(QObject* parent)
    : QObject(parent),
    m_ui(new QTabWidget),
    m_docs(new DocumentList(this))
{
    setObjectName(QStringLiteral("From QAxFactory"));
}

DocumentList* Application::documents() const
{
    return m_docs.data();
}

void Application::setVisible(bool on)
{
    m_ui->setVisible(on);
}

bool Application::isVisible() const
{
    return m_ui->isVisible();
}

void Application::quit()
{
    m_docs.reset();
    m_ui.reset();
    QTimer::singleShot(0 /*ms*/, qApp, &QCoreApplication::quit);
}

三、声明所有导出的多个类生成dll

然后我们还需要在总的宏编译,在CPP文件中定义需要导出的类:

#include "ActiveQtServerHourse.h"

#include <ActiveQt/QAxFactory>
#include "Document.h"

ActiveQtServerHourse::ActiveQtServerHourse(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
}

QAXFACTORY_BEGIN("{edd3e836-f537-4c6f-be7d-6014c155cc7a}", "{b7da3de8-83bb-4bbe-9ab7-99a05819e201}")
QAXTYPE(Document)
QAXCLASS(DocumentList)
QAXCLASS(Application)
QAXCLASS(ActiveQtServerHourse)
QAXFACTORY_END()

随后点击生成dll并用windeploy发布

 D:\Qt\6.7\6.7.0\msvc2019_64\bin\windeployqt.exe .\ActiveQtServerHourse.dll

四、C#调用Com C++类

4.1 添加类引用

4.2 查看可以访问的函数

4.3 C#代码使用Com类

using System;
using System.Windows.Forms;

namespace WindowsFormsApp4
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ActiveQtServerHourseLib.Application appobj = new ActiveQtServerHourseLib.Application();
            appobj.visible = true;
                        
            ActiveQtServerHourseLib.DocumentList docList = appobj.documents;
            docList.addDocument_1();
            docList.addDocument_1();
            docList.addDocument_1();
            docList.addDocument_1();

            int count = docList.count;            

            axActiveQtServerSnake1.set_text("Hello, I'm From C# text,docs count:" + count + ",doc title:" + docList.item(0).title);

        }
    }
}

参考文章

Qt的进程间通信,以Active服务器的形式,手把手教你VS上进行Qt的COM、ActivedQt Server的开发,比保姆还保姆

https://www.cnblogs.com/Leventure/p/16971934.html

如何用ActiveQt写导出类

https://www.cnblogs.com/chaoswong/p/3412349.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值