X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f6bcfd974ef26faf6f91a62cac09827e09463fd1..71ec83d2fd6dde4fd6ad1905cf74c6cf23d13c2a:/samples/exec/exec.cpp diff --git a/samples/exec/exec.cpp b/samples/exec/exec.cpp index e8483a828a..50c351e463 100644 --- a/samples/exec/exec.cpp +++ b/samples/exec/exec.cpp @@ -39,12 +39,16 @@ #include "wx/msgdlg.h" #include "wx/textdlg.h" #include "wx/listbox.h" + #include "wx/filedlg.h" + #include "wx/choicdlg.h" #endif #include "wx/txtstrm.h" #include "wx/process.h" +#include "wx/mimetype.h" + #ifdef __WINDOWS__ #include "wx/dde.h" #endif // __WINDOWS__ @@ -80,6 +84,8 @@ public: // event handlers (these functions should _not_ be virtual) void OnQuit(wxCommandEvent& event); + void OnKill(wxCommandEvent& event); + void OnClear(wxCommandEvent& event); void OnSyncExec(wxCommandEvent& event); @@ -88,7 +94,7 @@ public: void OnExecWithRedirect(wxCommandEvent& event); void OnExecWithPipe(wxCommandEvent& event); - void OnDDEExec(wxCommandEvent& event); + void OnFileExec(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); @@ -104,8 +110,26 @@ private: const wxArrayString& output, const wxString& title); + void DoAsyncExec(const wxString& cmd); + + // the PID of the last process we launched asynchronously + int m_pidLast; + + // last command we executed wxString m_cmdLast; +#ifdef __WINDOWS__ + void OnDDEExec(wxCommandEvent& event); + void OnDDERequest(wxCommandEvent& event); + + bool GetDDEServer(); + + // last params of a DDE transaction + wxString m_server, + m_topic, + m_cmdDde; +#endif // __WINDOWS__ + wxListBox *m_lbox; MyProcessesArray m_running; @@ -174,11 +198,14 @@ enum { // menu items Exec_Quit = 100, + Exec_Kill, Exec_ClearLog, Exec_SyncExec = 200, Exec_AsyncExec, Exec_Shell, + Exec_OpenFile, Exec_DDEExec, + Exec_DDERequest, Exec_Redirect, Exec_Pipe, Exec_About = 300 @@ -195,6 +222,7 @@ static const wxChar *DIALOG_TITLE = _T("Exec sample"); // simple menu events like this the static method is much simpler. BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(Exec_Quit, MyFrame::OnQuit) + EVT_MENU(Exec_Kill, MyFrame::OnKill) EVT_MENU(Exec_ClearLog, MyFrame::OnClear) EVT_MENU(Exec_SyncExec, MyFrame::OnSyncExec) @@ -203,8 +231,13 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(Exec_Redirect, MyFrame::OnExecWithRedirect) EVT_MENU(Exec_Pipe, MyFrame::OnExecWithPipe) - EVT_MENU(Exec_DDEExec, MyFrame::OnDDEExec) + EVT_MENU(Exec_OpenFile, MyFrame::OnFileExec) +#ifdef __WINDOWS__ + EVT_MENU(Exec_DDEExec, MyFrame::OnDDEExec) + EVT_MENU(Exec_DDERequest, MyFrame::OnDDERequest) +#endif // __WINDOWS__ + EVT_MENU(Exec_About, MyFrame::OnAbout) EVT_IDLE(MyFrame::OnIdle) @@ -250,6 +283,8 @@ bool MyApp::OnInit() MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame((wxFrame *)NULL, -1, title, pos, size) { + m_pidLast = 0; + #ifdef __WXMAC__ // we need this in order to allow the about menu relocation, since ABOUT is // not the default id of the about menu @@ -258,6 +293,9 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) // create a menu bar wxMenu *menuFile = new wxMenu(_T(""), wxMENU_TEAROFF); + menuFile->Append(Exec_Kill, _T("&Kill process...\tCtrl-K"), + _T("Kill a process by PID")); + menuFile->AppendSeparator(); menuFile->Append(Exec_ClearLog, _T("&Clear log\tCtrl-C"), _T("Clear the log window")); menuFile->AppendSeparator(); @@ -276,9 +314,13 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) execMenu->Append(Exec_Pipe, _T("&Pipe through command...\tCtrl-P"), _T("Pipe a string through a filter")); + execMenu->AppendSeparator(); + execMenu->Append(Exec_OpenFile, _T("Open &file...\tCtrl-F"), + _T("Launch the command to open this kind of files")); #ifdef __WINDOWS__ execMenu->AppendSeparator(); execMenu->Append(Exec_DDEExec, _T("Execute command via &DDE...\tCtrl-D")); + execMenu->Append(Exec_DDERequest, _T("Send DDE &request...\tCtrl-R")); #endif wxMenu *helpMenu = new wxMenu(_T(""), wxMENU_TEAROFF); @@ -295,6 +337,10 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) // create the listbox in which we will show misc messages as they come m_lbox = new wxListBox(this, -1); + wxFont font(12, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, + wxFONTWEIGHT_NORMAL); + if ( font.Ok() ) + m_lbox->SetFont(font); #if wxUSE_STATUSBAR // create a status bar just for fun (by default with 1 pane only) @@ -303,8 +349,9 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) #endif // wxUSE_STATUSBAR } - -// event handlers +// ---------------------------------------------------------------------------- +// event handlers: file and help menu +// ---------------------------------------------------------------------------- void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { @@ -319,10 +366,130 @@ void MyFrame::OnClear(wxCommandEvent& WXUNUSED(event)) void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { - wxMessageBox(_T("Exec sample\n© 2000 Vadim Zeitlin"), + wxMessageBox(_T("Exec wxWindows Sample\n© 2000-2001 Vadim Zeitlin"), _T("About Exec"), wxOK | wxICON_INFORMATION, this); } +void MyFrame::OnKill(wxCommandEvent& WXUNUSED(event)) +{ + long pid = wxGetNumberFromUser(_T("Please specify the process to kill"), + _T("Enter PID:"), + _T("Exec question"), + m_pidLast, + 1, INT_MAX, + this); + if ( pid == -1 ) + { + // cancelled + return; + } + + static const wxString signalNames[] = + { + _T("Just test (SIGNONE)"), + _T("Hangup (SIGHUP)"), + _T("Interrupt (SIGINT)"), + _T("Quit (SIGQUIT)"), + _T("Illegal instruction (SIGILL)"), + _T("Trap (SIGTRAP)"), + _T("Abort (SIGABRT)"), + _T("Emulated trap (SIGEMT)"), + _T("FP exception (SIGFPE)"), + _T("Kill (SIGKILL)"), + _T("Bus (SIGBUS)"), + _T("Segment violation (SIGSEGV)"), + _T("System (SIGSYS)"), + _T("Broken pipe (SIGPIPE)"), + _T("Alarm (SIGALRM)"), + _T("Terminate (SIGTERM)"), + }; + + int sig = wxGetSingleChoiceIndex(_T("How to kill the process?"), + _T("Exec question"), + WXSIZEOF(signalNames), signalNames, + this); + switch ( sig ) + { + default: + wxFAIL_MSG( _T("unexpected return value") ); + // fall through + + case -1: + // cancelled + return; + + case wxSIGNONE: + case wxSIGHUP: + case wxSIGINT: + case wxSIGQUIT: + case wxSIGILL: + case wxSIGTRAP: + case wxSIGABRT: + case wxSIGEMT: + case wxSIGFPE: + case wxSIGKILL: + case wxSIGBUS: + case wxSIGSEGV: + case wxSIGSYS: + case wxSIGPIPE: + case wxSIGALRM: + case wxSIGTERM: + break; + } + + if ( sig == 0 ) + { + if ( wxProcess::Exists(pid) ) + wxLogStatus(_T("Process %d is running."), pid); + else + wxLogStatus(_T("No process with pid = %d."), pid); + } + else // not SIGNONE + { + wxKillError rc = wxProcess::Kill(pid, (wxSignal)sig); + if ( rc == wxKILL_OK ) + { + wxLogStatus(_T("Process %d killed with signal %d."), pid, sig); + } + else + { + static const wxChar *errorText[] = + { + _T(""), // no error + _T("signal not supported"), + _T("permission denied"), + _T("no such process"), + _T("unspecified error"), + }; + + wxLogStatus(_T("Failed to kill process %d with signal %d: %s"), + pid, sig, errorText[rc]); + } + } +} + +// ---------------------------------------------------------------------------- +// event handlers: exec menu +// ---------------------------------------------------------------------------- + +void MyFrame::DoAsyncExec(const wxString& cmd) +{ + wxProcess *process = new MyProcess(this, cmd); + m_pidLast = wxExecute(cmd, FALSE /* async */, process); + if ( !m_pidLast ) + { + wxLogError(_T("Execution of '%s' failed."), cmd.c_str()); + + delete process; + } + else + { + wxLogStatus(_T("Process %ld (%s) launched."), m_pidLast, cmd.c_str()); + + m_cmdLast = cmd; + } +} + void MyFrame::OnSyncExec(wxCommandEvent& WXUNUSED(event)) { wxString cmd = wxGetTextFromUser(_T("Enter the command: "), @@ -350,20 +517,7 @@ void MyFrame::OnAsyncExec(wxCommandEvent& WXUNUSED(event)) if ( !cmd ) return; - wxProcess *process = new MyProcess(this, cmd); - long pid = wxExecute(cmd, FALSE /* async */, process); - if ( !pid ) - { - wxLogError(_T("Execution of '%s' failed."), cmd.c_str()); - - delete process; - } - else - { - wxLogStatus(_T("Process %ld (%s) launched."), pid, cmd.c_str()); - - m_cmdLast = cmd; - } + DoAsyncExec(cmd); } void MyFrame::OnShell(wxCommandEvent& WXUNUSED(event)) @@ -474,48 +628,127 @@ void MyFrame::OnExecWithPipe(wxCommandEvent& WXUNUSED(event)) m_cmdLast = cmd; } -void MyFrame::OnDDEExec(wxCommandEvent& WXUNUSED(event)) +void MyFrame::OnFileExec(wxCommandEvent& event) { + static wxString s_filename; + + wxString filename = wxLoadFileSelector(_T("file"), _T(""), s_filename); + if ( !filename ) + return; + + s_filename = filename; + + wxString ext = filename.AfterFirst(_T('.')); + wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(ext); + if ( !ft ) + { + wxLogError(_T("Impossible to determine the file type for extension '%s'"), + ext.c_str()); + return; + } + + wxString cmd; + bool ok = ft->GetOpenCommand(&cmd, + wxFileType::MessageParameters(filename, _T(""))); + delete ft; + if ( !ok ) + { + wxLogError(_T("Impossible to find out how to open files of extension '%s'"), + ext.c_str()); + return; + } + + DoAsyncExec(cmd); +} + +// ---------------------------------------------------------------------------- +// DDE stuff +// ---------------------------------------------------------------------------- + #ifdef __WINDOWS__ + +bool MyFrame::GetDDEServer() +{ wxString server = wxGetTextFromUser(_T("Server to connect to:"), - DIALOG_TITLE, _T("IExplore")); + DIALOG_TITLE, m_server); if ( !server ) - return; + return FALSE; - wxString topic = wxGetTextFromUser(_T("DDE topic:"), - DIALOG_TITLE, _T("WWW_OpenURL")); + m_server = server; + + wxString topic = wxGetTextFromUser(_T("DDE topic:"), DIALOG_TITLE, m_topic); if ( !topic ) - return; + return FALSE; - wxString cmd = wxGetTextFromUser(_T("DDE command:"), - DIALOG_TITLE, - _T("\"file:F:\\wxWindows\\samples\\" - "image\\horse.gif\",,-1,,,,,")); + m_topic = topic; + + wxString cmd = wxGetTextFromUser(_T("DDE command:"), DIALOG_TITLE, m_cmdDde); if ( !cmd ) + return FALSE; + + m_cmdDde = cmd; + + return TRUE; +} + +void MyFrame::OnDDEExec(wxCommandEvent& WXUNUSED(event)) +{ + if ( !GetDDEServer() ) return; wxDDEClient client; - wxConnectionBase *conn = client.MakeConnection("", server, topic); + wxConnectionBase *conn = client.MakeConnection("", m_server, m_topic); if ( !conn ) { wxLogError(_T("Failed to connect to the DDE server '%s'."), - server.c_str()); + m_server.c_str()); } else { - if ( !conn->Execute(cmd) ) + if ( !conn->Execute(m_cmdDde) ) { wxLogError(_T("Failed to execute command '%s' via DDE."), - cmd.c_str()); + m_cmdDde.c_str()); } else { wxLogStatus(_T("Successfully executed DDE command")); } } -#endif // __WINDOWS__ } +void MyFrame::OnDDERequest(wxCommandEvent& WXUNUSED(event)) +{ + if ( !GetDDEServer() ) + return; + + wxDDEClient client; + wxConnectionBase *conn = client.MakeConnection("", m_server, m_topic); + if ( !conn ) + { + wxLogError(_T("Failed to connect to the DDE server '%s'."), + m_server.c_str()); + } + else + { + if ( !conn->Request(m_cmdDde) ) + { + wxLogError(_T("Failed to send request '%s' via DDE."), + m_cmdDde.c_str()); + } + else + { + wxLogStatus(_T("Successfully sent DDE request.")); + } + } +} + +#endif // __WINDOWS__ + +// ---------------------------------------------------------------------------- +// various helpers +// ---------------------------------------------------------------------------- + // input polling void MyFrame::OnIdle(wxIdleEvent& event) {