wxWidgets访问另一个进程的TopFrame

时间:2016-02-09 05:08:41

标签: c++ wxwidgets

我有一个应用程序,它具有父框架作为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); 
}

1 个答案:

答案 0 :(得分:0)

如果要阻止同时运行多个应用程序实例,可以使用wxSingleInstanceChecker检查另一个实例是否正在运行,并使用IPC classes发送名称如果是,则打开另一个实例的文档。