【问题标题】:wxWidgets Accessing TopFrame of Another ProcesswxWidgets 访问另一个进程的 TopFrame
【发布时间】:2016-02-09 05:08:41
【问题描述】:

我有一个应用程序,它的父框架作为 MainFrame 和两个子框架 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;
  }

我的问题是,当我点击一个文档时,如何在已经运行的 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); 
}

【问题讨论】:

    标签: c++ wxwidgets


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-11
      • 2020-12-19
      • 1970-01-01
      • 1970-01-01
      • 2013-03-17
      • 2011-02-10
      • 1970-01-01
      • 2019-04-12
      相关资源
      最近更新 更多