- 我已经写好了Qt窗口的查看DXF文件的类。想在MFC中使用
class Qt_DXF_API DxfTabWidget : public QTabWidget
{
Q_OBJECT
public:
DxfTabWidget(QWidget *parent = nullptr);
~DxfTabWidget();
void setDxf(const std::shared_ptr<DXF::DxfData> &dxfData);
private:
void onCurrentChanged(int index);
DxfTabWidgetPrivate* d_ptr;
};
- 使用qtwinmigrate来整合MFC和Qt两个系统,可以从网上下载源代码。
- 安装VS2017及其Qt插件。【已经有的跳过】
- 用VS2017打开qtwinmigrate的pro文件。
- 编译测试是否正确。同时会生成moc_qwinhost.cpp和moc_qwinwidget.cpp。
- 生成MFC对话框工程。
- 添加一个MFC扩展DLL工程。
- 把DxfTabWidget和Qt的相关lib、dll、h文件复制到3rd目录。
- 设置两个工程的include、lib目录,和引入的库。这两步比较繁琐,但是大部分程序员会做。
- 在dllmain加入下列代码
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("QtDxfViewerLib.DLL 正在初始化!\n");
if (!AfxInitExtensionModule(QtDxfViewerLibDLL, hInstance))
return 0;
new CDynLinkLibrary(QtDxfViewerLibDLL);
ownApplication = QMfcApp::pluginInstance(hInstance);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("QtDxfViewerLib.DLL 正在终止!\n");
delete qApp;
AfxTermExtensionModule(QtDxfViewerLibDLL);
}
- 添加类
#pragma once
#include <afxwin.h>
#include <memory>
#include "DxfData.h"
#include "qtdxfviewer_api.h"
class MFCDxfViewerPrivate;
class QT_DXF_ViEWER_API MFCDxfViewer :
public CWnd
{
public:
MFCDxfViewer();
~MFCDxfViewer();
BOOL CreateFromStatic(UINT nID, CWnd* pParent);
void setDxf(const std::shared_ptr<DXF::DxfData> &dxfData);
void setDxf(const char *dxfFileName, bool OnlyReadModelSpace);
DECLARE_MESSAGE_MAP()
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
private:
MFCDxfViewerPrivate* d_ptr = nullptr;
public:
afx_msg void OnDestroy();
afx_msg void OnSize(UINT nType, int cx, int cy);
};
#include "pch.h"
#include <QHBoxLayout>
#include "MFCDxfViewer.h"
#include "qtwinmigrate/qwinwidget.h"
#include "DxfViewer.h"
#include "DxfReader.h"
BEGIN_MESSAGE_MAP(MFCDxfViewer, CWnd)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SIZE()
END_MESSAGE_MAP()
class MFCDxfViewerPrivate
{
public:
QWinWidget* container = nullptr;
DxfTabWidget* dxfViewer = nullptr;
std::shared_ptr<DXF::DxfData> dxfData;
};
MFCDxfViewer::MFCDxfViewer()
: d_ptr(new MFCDxfViewerPrivate)
{
}
MFCDxfViewer::~MFCDxfViewer()
{
delete d_ptr;
d_ptr = nullptr;
}
BOOL MFCDxfViewer::CreateFromStatic(UINT nID, CWnd* pParent)
{
CStatic wndStatic;
if (!wndStatic.SubclassDlgItem(nID, pParent))
return FALSE;
CRect rc;
wndStatic.GetWindowRect(&rc);
pParent->ScreenToClient(&rc);
wndStatic.DestroyWindow();
return
Create(NULL,
NULL,
(WS_CHILD | WS_VISIBLE),
rc,
pParent,
nID,
NULL);
}
void MFCDxfViewer::setDxf(const std::shared_ptr<DXF::DxfData>& dxfData)
{
d_ptr->dxfData = dxfData;
if (d_ptr->dxfViewer)
d_ptr->dxfViewer->setDxf(dxfData);
}
void MFCDxfViewer::setDxf(const char * dxfFileName, bool OnlyReadModelSpace)
{
std::shared_ptr<DXF::DxfData> dxfData = std::make_shared<DXF::DxfData>();
DXF::DxfReader reader(*dxfData);
bool success = reader.ReadDxf(dxfFileName, OnlyReadModelSpace);
if (success)
{
setDxf(dxfData);
}
}
int MFCDxfViewer::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
d_ptr->container = new QWinWidget(this);
auto hbox = new QHBoxLayout(d_ptr->container);
hbox->setMargin(0);
hbox->setSpacing(0);
d_ptr->dxfViewer = new DxfTabWidget(d_ptr->container);
hbox->addWidget(d_ptr->dxfViewer);
d_ptr->container->setLayout(hbox);
d_ptr->container->show();
return 0;
}
void MFCDxfViewer::OnDestroy()
{
CWnd::OnDestroy();
delete d_ptr->container;
}
void MFCDxfViewer::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
RECT r;
GetClientRect(&r);
d_ptr->container->setGeometry(r.left, r.top, r.right - r.left, r.bottom - r.top);
}
- 在MFC对话框程序中,像普通的自定义MFC控件一样使用就行了。
- 编译通过。Debug运行正常,Release运行出错。
复制Qt plugin,设置环境变量QT_QPA_PLATFORM_PLUGIN_PATH统统没用。需要使用windeployqt进行部署,像qt程序一样。
部署完成后Release目录如下:
运行windeployqt.exe之后,Release目录复制了红框中这些文件。
结果如下:
源代码下载
MFC嵌入Qt窗口DXF查看器
可执行文件下载
MFC嵌入Qt窗口DXF查看器