wxWidgets 访问另一个进程的TopFrame

wxWidgets Accessing TopFrame of Another Process

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

当我单击 GUI MainFrame 的可执行文件时,ChildAChildB 加载正常。然而,当可执行文件是 运行 并且当我单击一个文档时,我意识到 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;
  }

我的问题是,当我单击一个文档时,如何在已经 运行 MainFrame 中打开该文档。

编辑 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},
};

下面是 MainFrame.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 to check if another one is running and use the IPC classes 将要打开的文档的名称发送到另一个实例,如果它是。