wxWidgets教程(11)——App与进程管理

一、wxApp与wxAppConsole介绍

1、创建一个自己的MyApp继承自wxApp。文档上说,必须重写OnInit方法。

然后在头文件中,调用wxDECLARE_APP;在cpp文件中,调用wxIMPLEMENT_APP

前者可以让你在其他文件中使用wxGetApp来获得App的实例。

后者可以创建App的实例。

2、wxApp有很多可以重载的虚函数,比如

OnExit:程序结束调用。

ProcessPendingEvents:QueueEvent与AddPendingEvent发送的事件,由此调用处理。

OnAssertFailure:wxASSERT判断失败会调用。

很多函数不太常用。

二、事件wxEvtHandler

1、Connect | DisConnect : 动态绑定事件与控件。

2、QueueEvent:工作线程向主窗口线程,异步发送事件,一般发送wxThreadEvent事件的clone版本,易携带wxString。

3、AddPendingEvent:和QueueEvent差不多,只是不能携带wxString。

三、wxExecute与wxProcess

1、wxExecute的参数之中有wxProcess,用来沟通主进程与子进程之间的通信管道,在做参数之前,需要调用wxProcess-》Redirect函数。

2、调用Kill与Open可以终止一个进程和执行一个cmd命令。

3、wxEXEC_ASYNC:异步调用子程序,wxProcess进程结束以后会自动销毁,不需要delete,wxExecute返回值为进程的id(pid)。

4、wxEXEC_SYNC:同步调用子程序,阻塞我们的应用程序,直到wxProcess结束,需要手动delete掉wxProcess,wxExecute返回值为进程的退出码。

5、通过wxProcess来获取子进程的标准输出流wxInputStream,要注意,异步调用的话,一旦子进程退出,wxProcess就被删除了,那么再去获取wxInputStream会报异常;同步调用的话,子进程退出,但是wxProcess并没有被删除,而是等待我们自己来删除,所以还是能获取到wxInputStream的。

6、为了解决wxProcess在异步调用下,仍然能获取到输出流,可以定义个成员变量缓冲区,在wxExecute调用后立即获取wxInputStream,并把所有的数据拷贝到成员变量缓冲区,留着以后使用。

四、wxSingleInstanceChecker

这个类可以实现单一进程。

下面是实际当中的使用示例:

MyApp的头文件:

#pragma once

#define  wxUSE_GUI 0

#include 
#include 
#include 
#include 
#include 

wxDECLARE_EVENT(wxMY_EVT_1, wxThreadEvent);

class MyApp :public wxAppConsole
{
public:
	virtual bool OnInit() override;
	virtual int OnExit() override;
	virtual int FilterEvent(wxEvent& event) override;
	virtual void OnInitCmdLine(wxCmdLineParser& parser) override;

	virtual bool OnCmdLineParsed(wxCmdLineParser& parser) override;

	virtual bool OnCmdLineHelp(wxCmdLineParser& parser) override;

	virtual bool OnCmdLineError(wxCmdLineParser& parser) override;
protected:
	wxSingleInstanceChecker * m_checker;
	wxProcess * m_process;
	wxDynamicLibrary m_dynlib;
};

wxDECLARE_APP(MyApp);

MyApp的cpp文件


#include "MyApp.h"
#include 
#include 

wxDEFINE_EVENT(wxMY_EVT_1, wxThreadEvent);

wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
	// 单一进程实例的实现,必须在堆上新建checker,保持活性才会让另一个进程检测到
	m_checker = new wxSingleInstanceChecker();
	if (m_checker->IsAnotherRunning()) {
		delete m_checker;
		m_checker = nullptr;
		return false;
	}
	// 获取User32.dll的MessageBox方法
	if (m_dynlib.Load(wxT("User32.dll"))) {
		if (m_dynlib.HasSymbol(wxT("MessageBoxA"))) {
			using msgBoxType = int __stdcall(int, const wchar_t*, const wchar_t*, int);
			msgBoxType* msgBox = (msgBoxType*)m_dynlib.GetSymbolAorW(wxT("MessageBox"));
			msgBox(NULL, wxT("消息内容"), wxT("消息标题"), 0);
		}
	}
	// wxProcess使用,异步读取另一个程序的标准输出
	m_process = new wxProcess(this);
	m_process->Redirect();
	wxExecute(wxT("cmd /k \"D:\\cpp\\pro\\win32demo1\\Debug\\win32demo1.exe\""),wxEXEC_ASYNC, m_process);
	wxTextInputStream tis(*(process->GetInputStream()));
	wxString buf = tis.ReadLine();
	// 临时开启一个detach线程,来模拟发送线程事件
	std::thread t([this]() {
			wxThreadEvent evt(wxMY_EVT_1);
			evt.SetString(wxT("I am a thread."));
			this->QueueEvent(evt.Clone());
	});
	t.detach();
	// 调用父类默认的初始化函数,初始化一些命令行参数注入等
	return __super::OnInit();
}

int MyApp::OnExit()
{
	delete m_checker;
	return 0;
}

int MyApp::FilterEvent(wxEvent& event)
{
	if (event.GetEventType() == wxMY_EVT_1) {
		wxThreadEvent * evt = (wxThreadEvent *)&event;
		wxLogDebug(wxT("Recieve a thread event string: %s"), evt->GetString());
	}
	return __super::FilterEvent(event);
}

void MyApp::OnInitCmdLine(wxCmdLineParser& parser)
{
	parser.AddOption(wxT("m"), wxT("name"), wxT("your real name"), wxCMD_LINE_VAL_STRING);
	parser.AddOption(wxT("n"), wxT("age"), wxT("your real age"), wxCMD_LINE_VAL_NUMBER);
	// 默认为/作为选项的前缀的,可以修改为-为前缀
	parser.SetSwitchChars(wxT("-"));
	// 调用基类,提供了一些标准的选项或参数,诸如--help等等
	__super::OnInitCmdLine(parser);
}

bool MyApp::OnCmdLineParsed(wxCmdLineParser& parser)
{
	//获取m参数
	wxString param_m;
	if (parser.Found(wxT("m"), ¶m_m)) {
		wxLogDebug(param_m);
	}
	//获取f参数
	long param_f;
	if (parser.Found(wxT("n"), ¶m_f)) {
		wxLogDebug(wxT("%d"), param_f);
	}
	// 返回false,这会让OnInit返回false来结束程序
	// 返回true,继续执行程序
	return true;
}

bool MyApp::OnCmdLineHelp(wxCmdLineParser& parser)
{
	std::cout << parser.GetUsageString() << std::endl;
	// 返回false,这会让OnInit返回false来结束程序
	// 返回true,继续执行程序
	return true;
}

bool MyApp::OnCmdLineError(wxCmdLineParser& parser)
{
	// 返回false,这会让OnInit返回false来结束程序
	// 返回true,继续执行程序
	return true;
}








你可能感兴趣的:(wxWidgets)