当前位置: 首页 > news >正文

庆阳有人做农资网站吗网站优化有哪些类型

庆阳有人做农资网站吗,网站优化有哪些类型,广元建设机械网站,花垣做网站程序测试环境是:slackware系统,属于linux系统,有桌面(Xface Session)。系统镜像是:slackware64-15.0-install-dvd.iso。qt、c代码实现。 问题描述:延续上一篇文章,将wps软件窗口内嵌…

程序测试环境是:slackware系统,属于linux系统,有桌面(Xface Session)。系统镜像是:slackware64-15.0-install-dvd.iso。qt、c++代码实现。

问题描述:延续上一篇文章,将wps软件窗口内嵌到qt的窗口后,出现一个棘手的问题,就是无法正常的关闭wps进程,即使表面上关闭了,再次打开并内嵌到主窗口时,会出现打不开wps软件的问题,会发现有wps的僵尸进程。

必要条件:slackware系统里需要安装wps、qt5开发工具,本篇文章不做详述。

程序编译:编译还是和上一篇文章保持一致。

我直接说问题的原因,当我们通过fork打开wps软件时,linux系统会出现两个关于该软件的wps进程(wpspdf),通过linux命令查看下进程信息如下:

/office6/wpspdf  这个进程就是打开pdf文件的软件wpspdf进程。

/bin/bash/ 这个进程是wpspdf进程的父进程。qt主窗口创建该进程,该进程又创建打开pdf的进程。

这俩进程都必须正常退出,才能保证我们下一次正确的再次打开软件。

第一种情况:当我们关闭了wps的qt父窗口,而不关闭wps软件界面(比如通过wps右上角的那个关闭按钮)时,虽然wps软件界面没了,但是后台的两个进程都没有关闭,这就导致wps的软件进程处于一种异常状态,这就导致下次打开时,发现完全打不开软件了。

第二种情况:如上图,当我们关闭了wps软件(比如通过wps右上角的那个关闭按钮),也关闭了其qt父窗口,这时我们linux命令查看进程信息会发现,wps进程剩了一个,而且还是个僵尸进程。其实就是/bin/bash/ 那个进程变成了僵尸进程。主要原因就是我们qt主窗口在创建该进程时,我们没有做wait操作,所以该进程没有正常退出,成为了僵尸进程。(上面两张图的进程号不一样的原因是,这是两次测试,所以id值不一样)。

以下是我修改后的最终代码:

form.h

#ifndef FORM_H
#define FORM_H#include <QWidget>
#include <QProcess>namespace Ui {
class Form;
}class Form : public QWidget
{Q_OBJECTpublic:explicit Form(QWidget *parent = nullptr);~Form();void open_wps();static void open_wps_thread();void close_wps();void close_wps2();void find_window_id_in_tree();void find_window_id_by_class();void add_window_in_qt();private:Ui::Form *ui;QProcess *process;uint32_t window_id;
};#endif // FORM_H

form.cpp

#include "form.h"
#include "ui_form.h"
#include <QWindow>
#include <QVBoxLayout>
#include <QtX11Extras/QX11Info>
#include <xcb/xcb.h>
#include <QDebug>
#include <X11/Xlib.h> 
#include <X11/Xatom.h> 
#include <iostream>  
#include <vector>  
#include <string>  
#include <sstream>  
#include <fstream>
#include <unistd.h>
#include <sys/wait.h>
#include <thread>Form::Form(QWidget *parent) :QWidget(parent),ui(new Ui::Form)
{ui->setupUi(this);
}Form::~Form()
{delete ui;std::cout << "Form deleted" << std::endl;
}void Form::open_wps_thread(){pid_t pid = fork();if(pid == 0){const char* wpsCommand[] = {"wpspdf", nullptr};//wps(word)、et(excel)、wpspdf(pdf)、wpp(ppt)std::cout << "in sub process:" << pid << std::endl;if(execvp(wpsCommand[0], (char* const*)wpsCommand) == -1){perror("failed to exec WPS");}}else if(pid > 0){        std::cout << "in main process:" << pid << std::endl;int status;waitpid(pid, &status, 0);}else{perror("fork failed");}    
}// 打开默认软件
void Form::open_wps(){std::thread t(open_wps_thread);t.detach();
}// 这个函数不太好,只关闭了窗口,没关闭进程
void Form::close_wps(){// 连接到X服务器xcb_connection_t *connection = xcb_connect(NULL, NULL);const xcb_setup_t *setup = xcb_get_setup(connection);xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);xcb_screen_t *screen = iter.data;// 创建一个cookie,用于请求服务器关闭窗口xcb_void_cookie_t cookie = xcb_destroy_window_checked(connection, window_id);// 等待请求完成xcb_generic_error_t *error = xcb_request_check(connection, cookie);if (error) {// 处理错误printf("Error code: %d\n", error->error_code);free(error);}// 断开连接xcb_disconnect(connection);
}void Form::close_wps2(){Display *display = XOpenDisplay(NULL);if (!display) {fprintf(stderr, "Cannot open display.\n");return;}    // 创建一个临时窗口来获取默认的事件掩码Window root_return;int x_return, y_return;unsigned int width_return, height_return, border_width_return, depth_return;XGetGeometry(display, window_id, &root_return, &x_return, &y_return,&width_return, &height_return, &border_width_return, &depth_return);// 发送 WM_DELETE_WINDOW 消息XEvent event;memset(&event, 0, sizeof(event));event.type = ClientMessage;event.xclient.display = display;event.xclient.window = window_id;event.xclient.message_type = XInternAtom(display, "WM_PROTOCOLS", False);event.xclient.format = 32;event.xclient.data.l[0] = XInternAtom(display, "WM_DELETE_WINDOW", False);event.xclient.data.l[1] = CurrentTime; // 当前时间戳XSendEvent(display, window_id, False, NoEventMask, &event);XFlush(display);XCloseDisplay(display);
}// 通过系统窗口树形结构去一层层遍历窗口(我这里没有遍历子窗口,如果找不到某个窗口,或许是因为是子窗口)
void Form::find_window_id_in_tree()
{Display *display = XOpenDisplay(nullptr);if (!display) {std::cerr << "Cannot open display\n";return;}Window root = DefaultRootWindow(display);Window parent, *children;unsigned int num_children;if (!XQueryTree(display, root, &root, &parent, &children, &num_children)) {return;}std::vector<Window> windows;windows.push_back(root);for (unsigned int i = 0; i < num_children; ++i) {windows.push_back(children[i]);}XFree(children);for (Window win : windows) {char* name;int status = XFetchName(display, win, &name);if (status == 1) {// 这里的win就是窗口的id,也是窗口的句柄值find_window_id_by_classstd::cout << "Found window name: " << name << " " << win << std::endl;if (std::string(name).find("wpspdf") != std::string::npos) {
//                XFree(name);
//                return;}XFree(name);}// 递归检查子窗口(如果有的话)// 注意:这里为了简化示例,没有实现递归}
}// 将第三方软件(wps)窗口内嵌到qt窗口里
void Form::add_window_in_qt()
{QWindow *win = QWindow::fromWinId(window_id);QWidget *widget = QWidget::createWindowContainer(win);widget->setParent(this);QVBoxLayout *layout = new QVBoxLayout();layout->addWidget(widget);this->setLayout(layout);
}// 获取窗口id(句柄)(找到的另外一种比较快捷的拿到窗口句柄的方式)
void Form::find_window_id_by_class()
{Display* display = XOpenDisplay(NULL);if (!display) {std::cerr << "Failed to open display" << std::endl;return;}Atom netClientListAtom = XInternAtom(display, "_NET_CLIENT_LIST", False);Atom actualType;int format;unsigned long numItems, bytesAfter;unsigned char* data = NULL;int status = XGetWindowProperty(display, DefaultRootWindow(display),netClientListAtom, 0, ~0UL, False,AnyPropertyType,&actualType, &format, &numItems, &bytesAfter,&data);if (status == Success && actualType == XA_WINDOW) {Window* windows = reinterpret_cast<Window*>(data);for (unsigned long i = 0; i < numItems; ++i) {Window win = windows[i];Atom actualType;int format;unsigned long nitems;unsigned long bytes_after;unsigned char* prop_data = nullptr;// 获取WM_CLASS属性if (XGetWindowProperty(display, win, XInternAtom(display, "WM_CLASS", False), 0, 1024, False, XA_STRING,&actualType, &format, &nitems, &bytes_after, &prop_data) == Success) {std::string className(reinterpret_cast<char*>(prop_data));if (actualType == XA_STRING && className == "wpspdf") {std::cout << "Window class name for window " << win << ": " << className << std::endl;XFree(prop_data);window_id = win;}}}} else {std::cerr << "Failed to get window list property" << std::endl;}if (data != NULL) {XFree(data);}XCloseDisplay(display);
}

1、重点关注 open_wps_thread线程函数,在该函数里,waitpid(pid, &status, 0)行代码,就是qt主窗口单起个新线程来创建和等待wps的进程,这样该进程就能正常结束了。

2、重点关注close_wps2函数,该函数可以通过窗口id来正常的关闭wps(wpspdf)软件进程。

 mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "form.h"
#include <unistd.h>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{if(!f){f = new Form();}f->show();f->open_wps();sleep(2);f->find_window_id_by_class();
}void MainWindow::on_pushButton_2_clicked()
{if(f){f->close_wps2();}
}//
void MainWindow::on_pushButton_3_clicked()
{if(f){// f->showFullScreen(); // 全屏显示f->add_window_in_qt();// f->find_window_id_in_tree();}
}

 1、mainwindow.cpp也是对应到一个窗口,上面有三个按钮,分别用来调form.h的方法,用来测试的。先调用on_pushButton_clicked,再调用on_pushButton_3_clicked,最后调用on_pushButton_2_clicked就能测试出我们确实正确关闭了窗口。

http://www.ritt.cn/news/10837.html

相关文章:

  • 兰州做网站怎么样市场调查报告
  • 医院网站怎么做优化排名靠前百度推广要自己建站吗
  • 培训网站建设网站建设一条龙
  • 利用免费网站做SEO厦门网
  • 石家庄购物网站排名建站公司哪个好
  • wordpress怎么做图片预览seo信息查询
  • 网站开发的核心技术网站推广途径和推广要点有哪些?
  • 宁都网站建设预测2025年网络营销的发展
  • 自己服务器建设网站seo诊断工具有哪些
  • 公司网站建设北京手游推广平台代理
  • 摄影网站首页设计seox
  • 金华浦江网站建设网络营销策略概念
  • 我的网站要换新域名如何做友情链接平台
  • wordpress 网站积分打赏泰州网站建设优化
  • 安徽做网站的公司360投放广告怎么收费
  • 网站排名如何提升百度销售平台
  • 关于干外贸的一些好的学习网站网络广告发布
  • 天津市网站建设+网页制作郑州seo技术顾问
  • 长春网站制作都找源晟27全网品牌推广
  • 做网站一定需要服务器吗新网站秒收录技术
  • 重庆时时彩网站怎么做灰色推广引流联系方式
  • 北京市建设资格与执业资格注册中心网站关键词优化公司哪家效果好
  • 怎么做p2p的网站网站优化排名公司
  • 西安东郊做网站网站定制
  • 作文网站哪个平台好在百度上怎么卖自己的产品
  • 家用电脑如何做网站服务器网络推广需要花多少钱
  • 怎么做网页表白链接临沂seo公司稳健火星
  • 动漫制作技术是干什么的上海优化关键词的公司
  • 网站建设费需要分摊吗手机黄页怎么找
  • 个人网站备案怎么写优化设计三要素