<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 20.1 單個實例和多個實例 依照你的應用程序的性質的不同,你可能允許你的用戶同時運行多個你的應用程序的實例,或者你也可能希望同時只能存在一個你的應用程序的實例,如果用戶試圖打開第二個或者試圖通過資源管理器打開多個和你的應用程序關聯的文檔,它們都將只看到一個應用程序在運行.一種很通用的作法是,讓你的用戶根據他的工作習慣,自己選擇是否允許運行應用程序的多個實例.不過同時運行多個實例有一個大問題是,哪個程序實例首先將配置文件寫入磁盤是不一定的,因此用戶可能會丟失它們的設置.而且多個實例運行對一些新手來說也有麻煩,它們可能并沒有意識到它們已經運行了應用程序的多個實例.允許同時運行應用程序的多個實例在所有的平臺上都是默認選項(除了在Mac平臺上通過Finder(查找器)來啟動應用程序打開文檔的時候),因此,如果你不希望你的應用程序可以運行多個實例, 你需要一些額外的代碼. 在Mac OS(也僅在這個系統)上,使用單一實例打開多個文檔是非常容易的.你只需要重載MacOpenFile函數,這個函數采用一個wxString類型的文件名作為參數,這個函數將在Mac Os的Finder打開和這個應用程序關聯的文檔的時候被調用.如果當前還沒有運行任何這個應用程序的實例,Mac系統會先啟動一個實例,然后再調用這個函數(這個大多數系統不同,在別的系統上,打開文檔通常是通過調用應用程序并且將文件名作為參數的方法).如果你使用的是文檔/試圖框架,你可能并不需要重載這個函數,因為其在Mac OsX上的實現代碼如下: ``` void wxApp::MacOpenFile(const wxString& fileName) { wxDocManager* dm = wxDocManager::GetDocumentManager() ; if ( dm ) dm->CreateDocument(fileName, wxDOC_SILENT) ; } ``` 然后,即使在Mac Os上,用戶還是可以通過直接多次運行程序的方法運行你的應用程序的多個實例. 如果你想檢測和禁止運行超過一個應用程序實例,你可以在程序運行之初使用wxSingleInstanceChecker類.這個對象將保持在應用程序的整個生命周期,因此,在你的OnInit函數中,調用其IsAnotherRunning函數檢測是否已經有別的實例正在運行,如果返回true,你可以在警告你的用戶之后,立刻退出應用程序.如下所示: ``` bool MyApp::OnInit() { const wxString name = wxString::Format(wxT("MyApp-%s"), wxGetUserId().c_str()); m_checker = new wxSingleInstanceChecker(name); if ( m_checker->IsAnotherRunning() ) { wxLogError(_("Program already running, aborting.")); return false; } ... more initializations ... return true; } int MyApp::OnExit() { delete m_checker; return 0; } ``` 但是,如果你想把舊的實例帶到前臺,或者你想使用舊的實例打開傳遞給你的新的實例作為命令行參數的文件,該怎么辦呢?一般說來,這需要在這兩個實例間進行通訊.我們可以使用wxWidgets提供的高層進程間通訊類來實現. 在下面的例子中,我們將實現應用程序多個實例之間的通訊,以便允許第二個實例詢問第一個實例是否它自己打開相應的文件,還是將自己提到前臺以便提醒用戶它已經請求用這個應用程序來打開文件,下面的代碼聲明了一個連接類,這個類將被兩個實例使用.一個服務器類將被老的實例使用以便監聽別的實例的連接請求,一個客戶端類將被后來的實例使用以便和老的實例通訊. ``` #include "wx/ipc.h" // Server類,用來監聽連接請求 class stServer: public wxServer { public: wxConnectionBase *OnAcceptConnection(const wxString& topic); }; // Client類,在OnInit函數中被后來的實例使用 class stClient: public wxClient { public: stClient() {}; wxConnectionBase *OnMakeConnection() { return new stConnection; } }; // Connection類,被兩個實例同時使用以實現通訊 class stConnection : public wxConnection { public: stConnection() {} ~stConnection() {} bool OnExecute(const wxString& topic, wxChar*data, int size, wxIPCFormat format); }; ``` OnAcceptConnection函數在老實例(Server)中當有新實例(Client)進行連接請求的時候被調用.我們應該首先檢查老實例中沒有顯示任何模式對話框,因為如果有模式對話框,就不可能有別的行為可以引起用戶的注意. ``` // 接收到了來自別的實例的連接請求 wxConnectionBase *stServer::OnAcceptConnection(const wxString& topic) { if (topic.Lower() == wxT("myapp")) { // 檢查沒有活動的模式對話框 wxWindowList::Node* node = wxTopLevelWindows.GetFirst(); while (node) { wxDialog* dialog = wxDynamicCast(node->GetData(), wxDialog); if (dialog && dialog->IsModal()) { return false; } node = node->GetNext(); } return new stConnection(); } else return NULL; } ``` OnExecute函數在客戶端實例對其連接對象調用Execute函數的時候被調用. OnExecute函數可以有一個空的參數,這表示它需要將自己提到前臺就可以了,否則,它需要檢測參數中的文件名指示的文件是否已經被它打開,如果已經打開,將這個文件顯示給用戶,否則,就打開這個文件,再將其顯示給用戶. ``` // 打開別的實例傳來的文件參數. bool stConnection::OnExecute(const wxString& WXUNUSED(topic), wxChar *data, int WXUNUSED(size), wxIPCFormat WXUNUSED(format)) { stMainFrame* frame = wxDynamicCast(wxGetApp().GetTopWindow(), stMainFrame); wxString filename(data); if (filename.IsEmpty()) { // 只需要提升主窗口 if (frame) frame->Raise(); } else { // 檢查文件是否已經打開并且將其顯示給用戶 wxNode* node = wxGetApp().GetDocManager()->GetDocuments().GetFirst(); while (node) { MyDocument* doc = wxDynamicCast(node->GetData(),MyDocument); if (doc && doc->GetFilename() == filename) { if (doc->GetFrame()) doc->GetFrame()->Raise(); return true; } node = node->GetNext(); } wxGetApp().GetDocManager()->CreateDocument( filename, wxDOC_SILENT); } return true; } ``` 在OnInit函數中,應用程序應該首先象前面介紹的那樣使用wxSingleInstanceChecker檢查是否已經運行了多個實例,如果沒有別的實例運行,這個實例可以將自己設置位一個Server,等待別的應用程序實例的連接請求,如果已經有實例在運行,就創建一個和那個實例的連接,第二個實例請求第一個實例打開自己被請求的文件或者提升其主窗口.下面是相關的代碼: ``` bool MyApp::OnInit() { wxString cmdFilename; // code to initialize this omitted ... m_singleInstanceChecker = new wxSingleInstanceChecker(wxT("MyApp")); // 如果使用單實例,用IPC檢測是否有別的實例. if (!m_singleInstanceChecker->IsAnotherRunning()) { // 創建一個服務器 m_server = new stServer; if ( !m_server->Create(wxT("myapp") ) { wxLogDebug(wxT("Failed to create an IPC service.")); } } else { wxLogNull logNull; // OK, 已經有一個實例了,創建一個和它之間的連接,然后在自己退出之前發送文件名 stClient* client = new stClient; // 下面的參數在使用DDE的時候被忽略,在使用基于TCP/IP的類的時候代表主機名. wxString hostName = wxT("localhost"); // 創建連接 wxConnectionBase* connection = client->MakeConnection(hostName, wxT("myapp"), wxT("MyApp")); if (connection) { // 請求那個已經存在的實例打開文件或者提升它自己 connection->Execute(cmdFilename); connection->Disconnect(); delete connection; } else { wxMessageBox(wxT("Sorry, the existing instance may be too busy too respond.\nPlease close any open dialogs and retry."), wxT("My application"), wxICON_INFORMATION|wxOK); } delete client; return false; } ... return true; } ``` 如果你想要了解更多這里用到的進程間通訊的細節,你可以在wxWidgets自帶的utils/helpview/src目錄中,找到另外一個用在獨立的wxWidgets幫助閱讀器中的例子,在那個例子中,別的應用程序會通過進程間通訊的方式請求幫助閱讀器程序打開某個幫助文件,另外在 wxWidgets的samples/ipc例子中,也演示了wxServer, wxClient和wxConnection的用法.
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看