wxWidgets 访问另一个进程的 TopFrame

wxWidgets Accessing TopFrame of Another Process

本文关键字:TopFrame 进程 另一个 访问 wxWidgets      更新时间:2023-10-16

我有一个应用程序,它的父框架作为大型机,两个子框架,ChildA和ChildB。这应该是一个面向文档的 GUI,以便当用户单击文档时,它应该能够打开 FrameA 的另一个实例。

当我点击GUI的可执行文件时MainFrameChildAChildB正常加载。但是,当可执行文件正在运行并且当我单击文档时,我意识到Windows正在将其作为另一个进程打开,以便MainFrameChildAChildB再次加载,我不想要,因为我只想打开另一个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 类将要打开的文档的名称发送到另一个实例(如果有)。