C#的WinForm中嵌入Qt界面库

为何会有如此奇葩需求

  • 一处代码,多处运行

C#有两种写界面的框架,winFrom和WPF,这二者写的界面可以相互调用,但C#编写的界面组件在非托管C++虽然理论上可以,但是这种类似反射的机制使用其他来说特别不舒服。而对于编写组件式SDK而言,核心的界面组件可以在C++、C#、JAVA中使用而无需修改太多的代码是我们的终级目标。

  • ocx 编写难度太大

使用MFC编写的OCX控件可以嵌套在各种高级语言甚至浏览器中,但对于新时代的开发人员而言,会MFC开发的越来越少,开发难度也比较大,开发MFC的性价比并不高。对于使用C++编写界面的人员来说,用Qt是大多数人的选择。

  • 跨平台

ocx 不能跨平台,导致了无法在除windows操作系统下使用ocx控件,但是Qt的界面可以在跨平台环境下使用。

嵌入原理

界面的可视化本质上是使用绘图引擎绘制出来的,对于MFC、WinForm、Qt而言在编写界面库的本质上是没有太大的区别的,即都是基于windows的窗口句柄的绘制,windows SDK的很多函数都是需要指定窗口句柄(如控制窗口的消息循环、Hook钩子等)。其次解决消息发送问题。MFC、WinForm使用的是windows的消息机制,而Qt使用的信号槽机制(幸运的是Qt也可以接收windows的消息)

也就是说基于Qt编写界面dll理论上可以在MFC、Qt、JAVA、C# WinFrom以及WPF(这个还是要嵌入winfrom外壳)中使用,夸大点来说是可以在任何语言中调用

实现步骤

使用qtwinmigrate开源库

正常情况下,qt的界面库必须是qt的主程序调用才行,但是qtwinmigrate库在内部解决了qt主程问题。我们只需要使用即可.
qtwinmigrate 库的下载地址 https://github.com/qtproject/qt-solutions.git

使用步骤

  • 新建一个C++的dll,将qtwinmigrate库的三个类(qwinhost、qmfcapp、qwinwidget三个类对应的头文件和cpp文件)文件拷贝到自己的工程目录下,并加入到工程中
  • 在dll入口函数dllmain 中加入如下代码
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpvReserved*/ )
{static bool ownApplication = FALSE;if ( dwReason == DLL_PROCESS_ATTACH ){//在dll加载的时候完成qapplication的创建,在内部通过SetWindowsHookEx这个函数解决消息的发送问题ownApplication = QMfcApp::pluginInstance( hInstance ); }if (dwReason == DLL_PROCESS_DETACH && ownApplication){delete qApp;//退出的时候delete qApp;}return TRUE;
}
  • 编写一个C++类来管理一个界面
class SampleWidget
{public:SampleWidget(void* ptr){_win_widget=new QWinWidget((HWND)ptr);//通过句柄创建一个QWinWidget类,这个QToolBar* tool_bar = new QToolBar(win);tool_bar->addAction("open");tool_bar->addAction("close");QComboBox* combo_box = new QComboBox();combo_box->addItem("zhang san");combo_box->addItem("li si");QVBoxLayout* box_layout = new QVBoxLayout(win);box_layout->addWidget(tool_bar);box_layout->addWidget(combo_box);QListView* list_view = new QListView(win);box_layout->addWidget(list_view);win->setLayout(box_layout);win->move(0, 0);win->show();}~ SampleWidget(){delete _win_widget;}private:QWinWidget* _win_widget;
}
  • 使用Swig生成对应的cxx文件和相应的C#文件

notes:在前面的一系列文章中,对swig有相应的使用说明

//## 建立对应的sample.i文件
%module(directors="1") sampledll
%{#include "SampleWidget.h"
%}/* turn on director wrapping Callback */
%apply void *VOID_INT_PTR { void * }
%include "SampleWidget.h"

建立好swig的i文件之后执行命令

swig -c++ -csharp  example.i //最简单的swig使用

执行之后将生成sample_wrap.cxx加入到dll工程中一起编译(smapledll是dll的名字),注意名字要跟你sample_wrap.cxx所在的工程名一致,负责会出现调用错误.

  • 新建C# winFrom程序,将生成C#文件纳入工程中
public partial class Form1 : Form{SampleWidget _sample_widget;public Form1(){InitializeComponent();_sample_widget=new  SampleWidget(this.Handle);}}

测试结果


可以看到窗体风格之类的也没有什么太大的问题,一个简单的类com组件的控件就完成了(窗口大小这样不会自动布满屏幕,需要重写winfrom中的大小改变的方法,还有一种方法是在C++截获From1这个的句柄消息如以下方式(这样对C#研发人员来说就只要写一句代码即可)

static LRESULT CALLBACK WindowsProc(HWND win_hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{switch (message){case  WM_SIZE:{int nHeight = HIWORD(lParam);int nWidth = LOWORD(lParam);if (_win_widget){_win_widget->setFixedSize(nWidth, nHeight);}break;}default:return DefWindowProc(win_hwnd, message, wParam, lParam);}return 0;
}SampleWidget(void* ptr,bool full_screen) //之前的Sample构造函数
{_win_widget=new QWinWidget((HWND)ptr);//通过句柄创建一个QWinWidget类,这个QToolBar* tool_bar = new QToolBar(win);tool_bar->addAction("open");tool_bar->addAction("close");if(full_screen){SetWindowLongPtr((HWND)parent, -4, (LONG_PTR)WindowsProc);//parent是之前传入的窗口句柄}QComboBox* combo_box = new QComboBox();combo_box->addItem("zhang san");combo_box->addItem("li si");QVBoxLayout* box_layout = new QVBoxLayout(win);box_layout->addWidget(tool_bar);box_layout->addWidget(combo_box);QListView* list_view = new QListView(win);box_layout->addWidget(list_view);win->setLayout(box_layout);win->move(0, 0);win->show();
}


C#的WinForm中嵌入Qt界面库相关推荐

  1. c# winform html 表,C# winform中嵌入Excel实现复杂表格的显示和控制

    龙源期刊网 http://www.doczj.com/doc/7c6e747d7375a417866f8fac.html C# winform中嵌入Excel实现复杂表格的显示和控制 作者:斯琴巴图杨 ...

  2. 在vc中使用xtremetoolkit界面库-----安装及环境配置

    近期想用一下xtremetoolkitPro界面库.网上的使用教程资源也不多,当中着实遇到了很多的困难,毕竟是首次使用. 首先当然是配置发开环境了: 我使用的是vc6.0+xtremetoolkitP ...

  3. VB.NET在WinForm中嵌入谷歌浏览器_制作全屏显示网页程序_并读取INI配置文件_根据配置文件显示不同的网页---VB.NET工作笔记016

    我们做了个项目,科技馆的,需要把绚丽的网页,全屏放到浏览器上显示,但是....他们做的这个网页...我去,只支持谷歌这样的浏览器,在IE这样的浏览器模式下,显示有问题... 不知道是不是因为,没有使用 ...

  4. .Net winform中嵌入Flash

    要在c# winform程序里嵌入FLASH,其实就是直接引用Flash的ocx控件. 那你就需要使用"COM 组件" Shockwave Flash Object.不过这个&qu ...

  5. QT打开外部程序并嵌入Qt界面

    一 启动程序 QT在运行的时候,要启动qws服务,如果用前面两种方法,运行的时候,要新开启一个qws,否则不能运行:而用第三种方法,则不需要再开启qws,它和主进程共用一个qws. 一.通过调用系统函 ...

  6. C#实现在Winform中嵌入Word和Excel

    在此只是介绍一个简单控件:dsoframer.ocx的使用,这个控件需要通过regsvr32进行注册,例如: regsvr32 C:\dsoframer.ocx 在注册完毕后,通过Vs开发环境中在工具 ...

  7. c++图形界面开发中,Qt和MFC谁更胜一筹?

    在C++语言主导下,有MFC和QT俩大平台,很很多读者对于这俩大平台不是很了解,不知道这俩大平台到底需要学习哪一种,有何优势?就这个问题我将我收集的各个观点总结为以下几点: 一.QT 跨平台C++图形 ...

  8. 在visualstudio中使用Qt

    1.  说明 在此说明一下IDE跟封装的之间的关系,他们之间本质上来说没有关系,是可以多对对的关系. Qt开发是个比较泛的概念,Qt是由很多一系列类组成的整体,就像boost里面也有很多的类,而boo ...

  9. Matplotlib画图教程:在QT界面中嵌入三维图片

    Matplotlib画图教程:在QT界面中嵌入三维图片 需求: 做项目报告的时候,有这么一个想法,就是能通过UI随时调用matplotlib进行二维图和三维图的绘制.因此就诞生了做这么一个小模块的想法 ...

最新文章

  1. Javadoc代码追踪记录
  2. HTTP状态码-HTTP Status Code
  3. Oracle 常用命令
  4. 关于上上文hashmap的深入-hashmap产生死锁的详解
  5. 开发者常用的 Sublime Text 3 插件
  6. NullPointerException的处理新方式,Java14真的太香了
  7. C语言算术运算符介绍和示例
  8. 生长区域算法的php实现
  9. LINUX Cacti 安装SOP FOR CentOS6.5
  10. CXF WebService视频教程,自己录的(更新第7集 异步调用 2009.1.15)。
  11. Android签名文件转化为pk8和pem
  12. 台安PLC通过手机热点远程在线模拟,远程编程,远程调试
  13. word自带公式编辑_原来有这样几种方式打开Word中的公式编辑器
  14. linux 进入recovery 命令行,liunx-fastboot命令行的使用方法
  15. java word水印
  16. lnmp安装tpshop
  17. iOS/MAC 数据压缩与解压缩及常用算法 LZMA、ZLIB
  18. IFC学习相关资料加强版 致敬黑夜的骑士
  19. 理解RTF和RTX指标
  20. 韦东山嵌入式第一期学习笔记DAY_1——3_1_linux命令入门演示

热门文章

  1. Android rtmp 推流(RtmLivePrj)源码
  2. Monkeyrunner安装以及介绍
  3. 题目:保护区里面有两只熊……,那么,在熊大熊二都不犯傻的前提下,都希望吃到最多的蜂蜜,请分析一下熊大熊二的行动逻辑,最优方案。
  4. ubuntu 安装flash plaer
  5. SkyWalking Agent 实现原理
  6. 华为Harmony鸿蒙开发笔记七:公共事件
  7. 【深度】交叉注意力机制
  8. ESP32-S3 自带usb/jtag初步尝试体验
  9. SmartKIT-ESP开发板和CNC shield v3拓展板的连接以及程序编写注意事项
  10. 《新学期,新FLAG》突破极限