wxWidgets 访问另一个进程的 TopFrame
wxWidgets Accessing TopFrame of Another Process
我有一个应用程序,它的父框架作为大型机,两个子框架,ChildA和ChildB。这应该是一个面向文档的 GUI,以便当用户单击文档时,它应该能够打开 FrameA 的另一个实例。
当我点击GUI的可执行文件时MainFrame
,ChildA
和ChildB
正常加载。但是,当可执行文件正在运行并且当我单击文档时,我意识到Windows正在将其作为另一个进程打开,以便MainFrame
,ChildA
和ChildB
再次加载,我不想要,因为我只想打开另一个ChildA
实例以显示文档的内容。
我的代码如下:
bool MainFrameApp::OnInit()
{
m_AnotherInstanceRunning=false;
m_checker = new wxSingleInstanceChecker;
if(m_checker->IsAnotherRunning()) m_AnotherInstanceRunning=true;
//Some other code
if(!m_AnotherInstanceRunning)
{
frame= new MainFrame(0L);
std::cout<<"Frame:"<<frame; //Prints the address
auto m_ChildA=new SomeChildFrame(frame);
frame->Show();
m_FrameA->Show(true);
wxTheApp->SetTopWindow(frame);
}
if(m_AnotherInstanceRunning)
{
frame=dynamic_cast<MainFrame*>(wxTheApp->GetTopWindow());
std::cout<<"Frame:"<<frame; //prints 0
frame->OpenDocument(frame,strDocDirectory,strDocName); //Does not work
return false;
}
我的问题是,当我单击一个文档时,如何在已经在运行的大型机中打开该文档。
编辑 1:
这就是我在无数小时后实现它的方式......
下面是 MainFrame.h 的代码。
const int SERVER_ID=wxNewId();
const int SERVERSOCKET_ID=wxNewId();
const int CLIENTSOCKET_ID=wxNewId();
class MainFrame;
class MainFrameApp : public wxApp
{
bool m_AnotherInstanceRunning;
wxSocketServer* m_server;
wxString m_DocDirectoryPath;
wxString m_DocFullName; //including extension
protected:
virtual void OnServerEvent(wxSocketEvent& event);
virtual void OnServerSocketEvent(wxSocketEvent& event);
virtual void OnClientSocketEvent(wxSocketEvent& event);
public:
MainFrame* m_MainFrame;
wxSingleInstanceChecker* m_checker;
};
static const wxCmdLineEntryDesc cmdLineDesc[] =
{
{wxCMD_LINE_PARAM, NULL, NULL, "", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE},
{wxCMD_LINE_NONE},
};
下面是大型机的代码.cpp
bool ScienceSuitApp::OnInit()
{
m_AnotherInstanceRunning=false;
m_checker = new wxSingleInstanceChecker;
if(m_checker->IsAnotherRunning()) m_AnotherInstanceRunning=true;
wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
glbStrExeDir=exePath.GetPath()+wxFileName::GetPathSeparator();
wxString strDocFullPath; //This is directory+name
if(argc>1)
{
wxCmdLineParser parser(cmdLineDesc, argc, argv);
parser.Parse();
strDocFullPath=argv[1];
wxFileName docPath(strDocFullPath);
m_DocDirectoryPath=docPath.GetPath()+wxFileName::GetPathSeparator();
m_DocFullName=docPath.GetFullName(); //we needed extension of document as well
}
if(!m_AnotherInstanceRunning)
{
//Some other code
//Here Process #1
m_MainFrame= new MainFrame(0L);
m_MainFrame->Show();
wxIPV4address addr;
addr.Service(3000);
m_server = new wxSocketServer(addr,wxSOCKET_WAITALL);
if (!m_server->Ok())
{
if (m_server->LastError() == wxSOCKET_INVPORT) wxMessageBox(wxT("Port in use!"));
m_server->Destroy();
}
m_server->SetEventHandler(*this, SERVER_ID);
m_server->SetNotify(wxSOCKET_CONNECTION_FLAG);
m_server->Notify(true);
Connect(SERVER_ID,wxID_ANY, wxEVT_SOCKET,wxSocketEventHandler(MainFrameApp::OnServerEvent));
Connect(SERVERSOCKET_ID,wxID_ANY,wxEVT_SOCKET,wxSocketEventHandler(MainFrameApp::OnServerSocketEvent));
}
if(m_AnotherInstanceRunning)
{
//Here is for Process #2
Connect(CLIENTSOCKET_ID,wxID_ANY,wxEVT_SOCKET,wxSocketEventHandler(MainFrameApp::OnClientSocketEvent));
wxIPV4address addr;
addr.Hostname(wxT("localhost"));
addr.Service(3000);
wxSocketClient* Socket = new wxSocketClient();
Socket->SetEventHandler(*this, CLIENTSOCKET_ID);
Socket->SetNotify(wxSOCKET_CONNECTION_FLAG | wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
Socket->Notify(true);
if(!Socket->Connect(addr, true)) wxMessageBox("Failed to connect to server");
return true;
}
return true;
}
void MainFrameApp::OnServerEvent(wxSocketEvent& event) //Process #1
{
wxSocketBase* sock = m_server->Accept(false);
sock->SetEventHandler(*this, SERVERSOCKET_ID);
sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
sock->Notify(true);
}
void MainFrameApp::OnServerSocketEvent(wxSocketEvent& event) //Process #1
{
wxSocketBase *sock = event.GetSocket();
wxCharBuffer buf(256);
switch(event.GetSocketEvent())
{
case wxSOCKET_CONNECTION:
{
break;
}
case wxSOCKET_INPUT:
{
sock->Read(buf.data(), 255);
wxString pathstr=wxString::FromUTF8(buf);
sock->Destroy();
wxFileName docPath(pathstr);
wxString DocDirectoryPath=docPath.GetPath()+wxFileName::GetPathSeparator();
wxString DocFullName=docPath.GetFullName(); //we needed extension of document as well
m_MainFrame->OpenDocument(m_MainFrame,DocDirectoryPath,DocFullName);
break;
}
case wxSOCKET_LOST:
{
sock->Destroy();
break;
}
}
}
void MainFrameApp::OnClientSocketEvent(wxSocketEvent& event) //Process #2
{
wxString str=m_DocDirectoryPath+m_DocFullName;
wxSocketBase* sock = event.GetSocket();
switch(event.GetSocketEvent())
{
case wxSOCKET_CONNECTION:
{
sock->Write(str.mb_str(),str.length());
}
}
//Exit the client process (Process #2) staying in the background, otherwise and no messages are sent
//Also we dont want to spawn background processes
exit(0);
}
如果要防止应用程序的多个实例同时运行,可以使用 wxSingleInstanceChecker 检查另一个实例是否正在运行,并使用 IPC 类将要打开的文档的名称发送到另一个实例(如果有)。
相关文章:
- boost::进程间消息队列引发错误
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 是否可以通过C++扩展强制多个python进程共享同一内存
- IPC使用多个管道和分支进程来运行Python程序
- 异常属于C++中的线程还是进程
- WMI检测进程创建事件-c++
- c++多进程编写一个唯一的文件
- 如何在C++中将函数发送到另一个进程
- 在Qt Creator中,如何在连接到正在运行的进程后查看控制台输出
- 终止 QProcess 不会终止子进程
- 将返回值从 exe 传递到 bat,并将其传递给 C# 中的进程
- COM :是否可以查看是否存在对我的某个 COM 对象的进程外引用?我可以释放它吗?
- Windows 进程间同步类似事件?
- 在挂钩启动新线程时解除挂钩进程
- pclose() 不会给我进程退出代码
- 运行代码时,c++ 会终止进程
- 可以读入进程内存的最大块大小是多少?
- 枚举进程模块在有效句柄上返回无效句柄
- 如何读取特定地址的进程内存?
- wxWidgets 访问另一个进程的 TopFrame