软件开发|编程技术|编程代码|编程入门先学什么—程序设计语言

多进程界面开发

  多进程界面开发-Qt试玩儿

  目录

  一、概述

  二、效果展示

  三、使用方法

  1、启动外部进程

  2、创建Qt窗口

  3、加入到主进程布局

  四、嵌入NotePad

  五、调用Ping命令

  六、嵌入其他QWidget窗体

  七、相关文章

  一、概述

  做客户端开发已经有好几个年头了,今天看到同事发了一篇关于富途牛牛的文章,核心思想就是想说,新版本的富途支持多进程架构了,效率大大提升啦,可以更好的里有多核CPU,提供软件运行效率。

  听到这个消息,我不仅感叹,我靠,真的好牛逼。

  但是心里又在默默的想,这个东西到底有什么好处,多进程写界面!!!从来没这么搞过呀,会不会有坑,到底比多线程好在了哪里?带着这个问题,从百度上看了几篇相关文章,主要是讲解了线程和进程的一些区别。当然了,最重要的还是目前的多进程架构的客户端已经开始变得多了起来。

  其实很早以前就接触过多进程,支持自己好想也没有想那么多,一直对多进程架构的概念不是那么清晰。今天和同事聊了一些相关话题,感觉自己的知识面豁然开朗,要学习的东西好像还挺多。

  看下面这张图,是任务管理器的应用截图,以前还真是没发现,居然我自己用的这么多应用都是多进程架构的。

  我们平时最常用的Chrome浏览器,客户端版本微信,还有有道云笔记等等

  有了这么多的多进程架构开发的客户端软件,难道说多进程开发已经是势在必行了?

  说这么多,还不如来点儿实际的干货,这篇文章是我初步开始使用多进程开发段产品的初步尝试,有不对的地方欢迎大家指出,可以给出更好建议

  二、效果展示

  下面是我做的一个demo程序截图,测试程序中一共包含了4个使用场景,分别是:

  Qt嵌入系统自带计算机

  Qt嵌入系统自带记事本

  Qt调用系统ping命令,并收集结果

  Qt嵌入其他Qt可执行程序

  大家可以先看看效果图,如果觉着有价值的可以继续往下看,下面我会分章节把四个事例进行讲解。

  三、使用方法

  首先需要清楚,我们是多进程界面开发,那么我们的exe启动后,势必是需要启动其他可执行程序的,并且把其他进程的界面嵌入到我们的窗口中来

  1、启动外部进程

  启动外部进程有多重方式,Qt使用比较习惯的同学可以直接使用QProcess类,这个类是Qt封装的一个跨平台的类。

  启动方式可能像下面这样

  QProcess*myProcess=newQProcess(this);

  QStringListarguments;

  myProcess-start(C:/Windows/System32/notepad.exe);

  myProcess-waitForFinished(2000);

  除过QProcess之外,Windows系统上我们还可以使用CreateProcess方法来创建进程。

  QStringcmd=C:/Windows/system32/calc.exe;

  STARTUPINFOsi={sizeof(si)};

  PROCESS_INFORMATIONpi;

  si.dwFlags=STARTF_USESHOWWINDOW;

  si.wShowWindow=true;

  boolbRet=CreateProcess(

  NULL,

  (LPWSTR)cmd.toStdWString().c_str(),

  NULL,

  NULL,

  FALSE,

  CREATE_NEW_CONSOLE,

  NULL,

  NULL,si,pi);

  2、创建Qt窗口

  外部进程启动后,我们可以在任务管理器中找到启动的进程

  接着我们需要使用SPY++工具进行查看外部进程的类名称和窗口名称,并使用FindWindow接口进程查找,找到这个进程的主窗口句柄后,嵌入到我们的程序中来。

  类名和窗口名称查找过程可以参考外部进程嵌入到Qt进程界面这篇文章中的内容。

  WIdwid=(WId)FindWindow(QStringLiteral(Notepad).toStdWString().c_str()

  ,QStringLiteral(无标题-记事本).toStdWString().c_str());

  QWindow*window=QWindow::fromWinId(wid);

  if(window)

  {

  window-setFlags(window-flags()|Qt::CustomizeWindowHint|Qt::WindowTitleHint);//这边可以设置一下属性

  QWidget*widget=QWidget::createWindowContainer(window,this,Qt::Widget);

  }

  如上代码所示,我们如果找到外部进程的主窗口句柄后,就可以使用Qt提供的createWindowContainer这个接口进行创建QWidget,并加入到我们的程序中来。

  3、加入到主进程布局

  外部进程被封装成为一个QWidget后,我们只需要加入到自己的布局中即可。

  ui.verticalLayout_2-addWidget(widget);

  接下来我们分别讲解不同场景下的多进程界面开发的简单使用

  四、嵌入NotePad

  第三小节已经把嵌入其他程序的流程大致说了一遍,这里我就不在详细说明了,直接给出具体代码。

  代码中比较关键的有2个地方

  QProcess不能使用临时变量,要不然函数执行完毕notepad.exe进程也就退出了。

  FindWindow的两个参数,一个是类名,一个窗口标题栏名称,这两个信息都可以用个SPY++进行查找。

  voidEmbedCalculate::on_pushButton_2_clicked()

  {

  //创建进程

  QStringcmd=C:/Windows/System32/notepad.exe;

  QProcess*myProcess=newQProcess(this);

  QStringListarguments;

  myProcess-start(cmd);

  myProcess-waitForFinished(2000);

  WIdwid=(WId)FindWindow(QStringLiteral(Notepad).toStdWString().c_str()

  ,QStringLiteral(无标题-记事本).toStdWString().c_str());

  QWindow*window=QWindow::fromWinId(wid);

  if(window)

  {

  window-setFlags(window-flags()|Qt::CustomizeWindowHint|Qt::WindowTitleHint);//这边可以设置一下属性

  QWidget*widget=QWidget::createWindowContainer(window,this,Qt::Widget);

  ui.verticalLayout_2-addWidget(widget);

  }

  }

  五、调用Ping命令

  ping命令使用场景主要是想展示主进程和外部进程是怎样通信的,虽然这个事例比较简单,但也算是两者之间发生了信息交换

  子进程在执行完ping一个地址之后,会把得到的结果传递给主进程,主进程使用readAll函数全部读入到主进程中。

  voidEmbedCalculate::on_pushButton_3_clicked()

  {

  //创建进程

  QProcess*myProcess=newQProcess(this);

  connect(myProcess,static_castvoid(QProcess::*)(int)(QProcess::finished),this,[this,myProcess](intexitCode){

  if(exitCode==0){

  QTextCodec*gbkCodec=QTextCodec::codecForName(GBK);

  QStringresult=gbkCodec-toUnicode(myProcess-readAll());

  ui.textEdit-setText(result);

  }

  });

  //myProcess-start(cmd.exe,QStringList()/cpingwww.baidu.com);

  myProcess-start(cmd.exe,QStringList()/cping+ui.lineEdit-text().trimmed());

  myProcess-waitForFinished(2000);

  

  }

  六、嵌入其他QWidget窗体

  虽然这个东西是最后讲的,但是这个才是重头戏,有了这个实验之后,我们以后的Qt多进程界面开发也可以进行投入正式环境了。

  如下所示,ChildWidget外部程序的主窗体被我们嵌入到了EmbedCalculate这个进程的主界面上,突然觉着好神奇,给自己点赞,哈哈哈哈。

  由于我这里的ChildWidget外部程序和EmbedCalculate主程序在一个目录中,因此cmd变量直接就指向了ChildWidget这个外部程序的名称。

  其他部分的代码基本上就和前边几种使用场景差不多。

  voidEmbedCalculate::on_pushButton_4_clicked()

  {

  //创建进程

  QStringcmd=ChildWidget.exe;

  QProcess*myProcess=newQProcess(this);

  QStringListarguments;

  myProcess-start(cmd);

  myProcess-waitForFinished(2000);

  WIdwid=(WId)FindWindow(QStringLiteral(Qt5QWindowIcon).toStdWString().c_str()

  ,QStringLiteral(ChildWidget).toStdWString().c_str());

  QWindow*window=QWindow::fromWinId(wid);

  if(window)

  {

  window-setFlags(window-flags()|Qt::CustomizeWindowHint|Qt::WindowTitleHint);//这边可以设置一下属性

  QWidget*widget=QWidget::createWindowContainer(window,this,Qt::Widget);

  ui.verticalLayout_3-addWidget(widget);

  }

  }

  七、相关文章

  外部进程嵌入到Qt进程界面