From 0d7ea902499bf302628cc12aa4705fb162b6fefd Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 15 Jan 2000 22:36:52 +0000 Subject: [PATCH] 1. fixed small bug with toolbar size updates 2. fixed bug with showing message box from wxApp::OnInit() 3. fixed crash on DDE client disconnection 4. fixed wxExecute() which was broken since quite some time (hidden window creation problems) and in wxShell() git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5434 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/function.tex | 7 +- docs/latex/wx/tsamples.tex | 20 ++++-- src/common/wincmn.cpp | 8 ++- src/msw/dde.cpp | 2 +- src/msw/msgdlg.cpp | 136 +++++++++++++++++++------------------ src/msw/tbar95.cpp | 9 +-- src/msw/utils.cpp | 2 +- src/msw/utilsexc.cpp | 45 +++++++++--- 8 files changed, 137 insertions(+), 92 deletions(-) diff --git a/docs/latex/wx/function.tex b/docs/latex/wx/function.tex index 8e24cc3391..678a7ce63f 100644 --- a/docs/latex/wx/function.tex +++ b/docs/latex/wx/function.tex @@ -1249,7 +1249,7 @@ the process (which terminates by the moment the function returns) and will be $-1$ if the process couldn't be started and typically 0 if the process terminated successfully. Also, while waiting for the process to terminate, wxExecute will call \helpref{wxYield}{wxyield}. The caller -should ensure that this can cause no recursion, in the simples case by +should ensure that this can cause no recursion, in the simplest case by calling \helpref{wxEnableTopLevelWindows(FALSE)}{wxenabletoplevelwindows}. For asynchronous execution, however, the return value is the process id and @@ -1260,7 +1260,8 @@ parameter can not be non NULL for synchronous execution), \helpref{wxProcess::OnTerminate}{wxprocessonterminate} will be called when the process finishes. -See also \helpref{wxShell}{wxshell}, \helpref{wxProcess}{wxprocess}. +See also \helpref{wxShell}{wxshell}, \helpref{wxProcess}{wxprocess}, +\helpref{Exec sample}{sampleexec}. \wxheading{Include files} @@ -1652,7 +1653,7 @@ See also \helpref{wxGetDisplayName}{wxgetdisplayname}. Executes a command in an interactive shell window. If no command is specified, then just the shell is spawned. -See also \helpref{wxExecute}{wxexecute}. +See also \helpref{wxExecute}{wxexecute}, \helpref{Exec sample}{sampleexec}. \wxheading{Include files} diff --git a/docs/latex/wx/tsamples.tex b/docs/latex/wx/tsamples.tex index 886f5fc994..85f43f1693 100644 --- a/docs/latex/wx/tsamples.tex +++ b/docs/latex/wx/tsamples.tex @@ -69,6 +69,13 @@ a dialog or frame. This is most typically the case for any scripting languge that would work as a wrapper for wxWindows or programs where forms or similar datagrams can be created by the uses. +\subsection{Exec sample}\label{sampleexec} + +The exec sample demonstrates the \helpref{wxExecute}{wxexecute} and +\helpref{wxShell}{wxshell} functions. Both of them are used to execute the +external programs and the sample shows how to do this synchronously (waiting +until the program terminates) or asynchronously (notification will come later). + \subsection{Scroll subwindow sample}\label{samplescrollsub} This sample demonstrates the use of the \helpref{wxScrolledWindow}{wxscrolledwindow} @@ -105,9 +112,11 @@ The middle of the sample window is taken by the log window which shows what is going on (of course, this only works in debug builds) and may be helpful to see the sequence of steps of data transfer. -Finally, the last part is used for two things: you can drag text from it to -either one of the listboxes (only one will accept it) or another application -and, also, bitmap pasted from clipboard will be shown there. +Finally, the last part is used for dragging text from it to either one of the +listboxes (only one will accept it) or another application. The last +functionality available from the main frame is to paste a bitmap from the +clipboard (or, in the case of Windows version, also a metafile) - it will be +shown in a new frame. So far, everything we mentioned was implemented with minimal amount of code using standard wxWindows classes. The more advanced features are demonstrated @@ -118,12 +127,13 @@ private \helpref{wxDataFormat}{wxdataformat} which means that you may cut and paste it or drag and drop (between one and the same or different shapes) from one sample instance to another (or the same). However, chances are that no other program supports this format and so shapes can also be rendered as -bitmaps which allows them to be pasted/dropped in many other applications. +bitmaps which allows them to be pasted/dropped in many other applications +(and, under Windows, also as metafiles which are supported by most of Windows +programs as well - try Write/Wordpad, for example). Take a look at DnDShapeDataObject class to see how you may use \helpref{wxDataObject}{wxdataobject} to achieve this. - \subsection{HTML samples}\label{samplehtml} Eight HTML samples (you can find them in directory {\tt samples/html}) diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index d545072003..f097009630 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -1278,7 +1278,9 @@ void wxWindowBase::DoSetClientObject( wxClientData *data ) wxClientData *wxWindowBase::DoGetClientObject() const { - wxASSERT_MSG( m_clientDataType == ClientData_Object, + // it's not an error to call GetClientObject() on a window which doesn't + // have client data at all - NULL will be returned + wxASSERT_MSG( m_clientDataType != ClientData_Void, wxT("this window doesn't have object client data") ); return m_clientObject; @@ -1295,7 +1297,9 @@ void wxWindowBase::DoSetClientData( void *data ) void *wxWindowBase::DoGetClientData() const { - wxASSERT_MSG( m_clientDataType == ClientData_Void, + // it's not an error to call GetClientData() on a window which doesn't have + // client data at all - NULL will be returned + wxASSERT_MSG( m_clientDataType != ClientData_Object, wxT("this window doesn't have void client data") ); return m_clientData; diff --git a/src/msw/dde.cpp b/src/msw/dde.cpp index 8986ce0e56..275f56144f 100644 --- a/src/msw/dde.cpp +++ b/src/msw/dde.cpp @@ -175,7 +175,7 @@ static void DDEDeleteConnection(HCONV hConv) if (found) return; - node = wxDDEServerObjects.First(); + node = wxDDEClientObjects.First(); while (node && !found) { wxDDEClient *object = (wxDDEClient *)node->Data(); diff --git a/src/msw/msgdlg.cpp b/src/msw/msgdlg.cpp index 70a83e908b..13e93e18c1 100644 --- a/src/msw/msgdlg.cpp +++ b/src/msw/msgdlg.cpp @@ -6,7 +6,7 @@ // Created: 04/01/98 // RCS-ID: $Id$ // Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ @@ -21,26 +21,21 @@ #endif #ifndef WX_PRECOMP -#include -#include "wx/defs.h" -#include "wx/utils.h" -#include "wx/dialog.h" -#include "wx/msgdlg.h" + #include "wx/defs.h" + #include "wx/utils.h" + #include "wx/dialog.h" + #include "wx/msgdlg.h" #endif #include "wx/msw/private.h" -#include -#include -#include - -#define wxDIALOG_DEFAULT_X 300 -#define wxDIALOG_DEFAULT_Y 300 - IMPLEMENT_CLASS(wxMessageDialog, wxDialog) -wxMessageDialog::wxMessageDialog(wxWindow *parent, const wxString& message, const wxString& caption, - long style, const wxPoint& pos) +wxMessageDialog::wxMessageDialog(wxWindow *parent, + const wxString& message, + const wxString& caption, + long style, + const wxPoint& WXUNUSED(pos)) { m_caption = caption; m_message = message; @@ -48,60 +43,71 @@ wxMessageDialog::wxMessageDialog(wxWindow *parent, const wxString& message, cons m_parent = parent; } -int wxMessageDialog::ShowModal(void) +int wxMessageDialog::ShowModal() { - HWND hWnd = 0; - if (m_parent) hWnd = (HWND) m_parent->GetHWND(); - unsigned int msStyle = MB_OK; - if (m_dialogStyle & wxYES_NO) - { - if (m_dialogStyle & wxCANCEL) - msStyle = MB_YESNOCANCEL; - else - msStyle = MB_YESNO; + if ( !wxTheApp->GetTopWindow() ) + { + // when the message box is shown from wxApp::OnInit() (i.e. before the + // message loop is entered), this must be done or the next message box + // will never be shown - just try putting 2 calls to wxMessageBox() in + // OnInit() to see it + while ( wxTheApp->Pending() ) + wxTheApp->Dispatch(); + } - if (m_dialogStyle & wxNO_DEFAULT) - msStyle |= MB_DEFBUTTON2; - } + HWND hWnd = 0; + if (m_parent) hWnd = (HWND) m_parent->GetHWND(); + unsigned int msStyle = MB_OK; + if (m_dialogStyle & wxYES_NO) + { + if (m_dialogStyle & wxCANCEL) + msStyle = MB_YESNOCANCEL; + else + msStyle = MB_YESNO; - if (m_dialogStyle & wxOK) - { - if (m_dialogStyle & wxCANCEL) - msStyle = MB_OKCANCEL; - else - msStyle = MB_OK; - } - if (m_dialogStyle & wxICON_EXCLAMATION) - msStyle |= MB_ICONEXCLAMATION; - else if (m_dialogStyle & wxICON_HAND) - msStyle |= MB_ICONHAND; - else if (m_dialogStyle & wxICON_INFORMATION) - msStyle |= MB_ICONINFORMATION; - else if (m_dialogStyle & wxICON_QUESTION) - msStyle |= MB_ICONQUESTION; + if (m_dialogStyle & wxNO_DEFAULT) + msStyle |= MB_DEFBUTTON2; + } + + if (m_dialogStyle & wxOK) + { + if (m_dialogStyle & wxCANCEL) + msStyle = MB_OKCANCEL; + else + msStyle = MB_OK; + } + if (m_dialogStyle & wxICON_EXCLAMATION) + msStyle |= MB_ICONEXCLAMATION; + else if (m_dialogStyle & wxICON_HAND) + msStyle |= MB_ICONHAND; + else if (m_dialogStyle & wxICON_INFORMATION) + msStyle |= MB_ICONINFORMATION; + else if (m_dialogStyle & wxICON_QUESTION) + msStyle |= MB_ICONQUESTION; - if (hWnd) - msStyle |= MB_APPLMODAL; - else - msStyle |= MB_TASKMODAL; + if (hWnd) + msStyle |= MB_APPLMODAL; + else + msStyle |= MB_TASKMODAL; - int msAns = MessageBox(hWnd, (LPCTSTR)(const wxChar *)m_message, (LPCTSTR)(const wxChar *)m_caption, msStyle); - int ans = wxOK; - switch (msAns) - { - case IDCANCEL: - ans = wxID_CANCEL; - break; - case IDOK: - ans = wxID_OK; - break; - case IDYES: - ans = wxID_YES; - break; - case IDNO: - ans = wxID_NO; - break; - } - return ans; + int msAns = MessageBox(hWnd, (LPCTSTR)m_message.c_str(), + (LPCTSTR)m_caption.c_str(), msStyle); + int ans = wxOK; + switch (msAns) + { + case IDCANCEL: + ans = wxID_CANCEL; + break; + case IDOK: + ans = wxID_OK; + break; + case IDYES: + ans = wxID_YES; + break; + case IDNO: + ans = wxID_NO; + break; + } + return ans; } diff --git a/src/msw/tbar95.cpp b/src/msw/tbar95.cpp index c0f75fc522..daa5ab3100 100644 --- a/src/msw/tbar95.cpp +++ b/src/msw/tbar95.cpp @@ -568,7 +568,6 @@ bool wxToolBar::Realize() // the id is probably invalid? wxLogLastError("TB_SETBUTTONINFO"); } - } else #endif // comctl32.dll 4.71 @@ -581,7 +580,7 @@ bool wxToolBar::Realize() TBBUTTON tbb; wxZeroMemory(tbb); tbb.idCommand = 0; - tbb.fsState = TBSTATE_ENABLED; + tbb.fsState = TBSTATE_ENABLED | TBSTATE_HIDDEN; tbb.fsStyle = TBSTYLE_SEP; size_t nSeparators = size.x / widthSep; @@ -808,7 +807,10 @@ wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const void wxToolBar::UpdateSize() { - // we must refresh the frame after the toolbar size (possibly) changed + // the toolbar size changed + SendMessage(GetHwnd(), TB_AUTOSIZE, 0, 0); + + // we must also refresh the frame after the toolbar size (possibly) changed wxFrame *frame = wxDynamicCast(GetParent(), wxFrame); if ( frame ) { @@ -822,7 +824,6 @@ void wxToolBar::UpdateSize() (void)::SendMessage(GetHwndOf(frame), WM_SIZE, SIZE_RESTORED, MAKELPARAM(r.right - r.left, r.bottom - r.top)); } - } // ---------------------------------------------------------------------------- diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index d9996a0453..2f56096849 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -454,7 +454,7 @@ bool wxShell(const wxString& command) cmd.Printf(wxT("%s /c %s"), shell, command.c_str()); } - return wxExecute(cmd, FALSE) != 0; + return wxExecute(cmd, TRUE /* sync */) != 0; } // ---------------------------------------------------------------------------- diff --git a/src/msw/utilsexc.cpp b/src/msw/utilsexc.cpp index 6df190c161..5cbd5a4957 100644 --- a/src/msw/utilsexc.cpp +++ b/src/msw/utilsexc.cpp @@ -167,9 +167,13 @@ LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message, // asynchronous execution - we should do the clean up delete data; } - } - return 0; + return 0; + } + else + { + return DefWindowProc(hWnd, message, wParam, lParam); + } } #endif @@ -247,7 +251,8 @@ long wxExecute(const wxString& command, bool sync, wxProcess *handler) NULL, // security attributes: defaults for both NULL, // the process and its main thread FALSE, // don't inherit handles - CREATE_DEFAULT_ERROR_MODE, // flags + CREATE_DEFAULT_ERROR_MODE | + CREATE_SUSPENDED, // flags NULL, // environment (use the same) NULL, // current directory (use the same) &si, // startup info (unused here) @@ -259,10 +264,7 @@ long wxExecute(const wxString& command, bool sync, wxProcess *handler) return 0; } - // close unneeded handle - if ( !::CloseHandle(pi.hThread) ) - wxLogLastError("CloseHandle(hThread)"); - + // register the class for the hidden window used for the notifications if ( !gs_classForHiddenWindow ) { gs_classForHiddenWindow = _T("wxHiddenWindow"); @@ -276,15 +278,14 @@ long wxExecute(const wxString& command, bool sync, wxProcess *handler) if ( !::RegisterClass(&wndclass) ) { wxLogLastError("RegisterClass(hidden window)"); - - return FALSE; } } // create a hidden window to receive notification about process // termination HWND hwnd = ::CreateWindow(gs_classForHiddenWindow, NULL, - 0, 0, 0, 0, 0, NULL, + WS_OVERLAPPEDWINDOW, + 0, 0, 0, 0, NULL, (HMENU)NULL, wxGetInstance(), 0); wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") ); @@ -314,6 +315,18 @@ long wxExecute(const wxString& command, bool sync, wxProcess *handler) 0, &tid); + // resume process we created now - whether the thread creation succeeded or + // not + if ( ::ResumeThread(pi.hThread) == (DWORD)-1 ) + { + // ignore it - what can we do? + wxLogLastError("ResumeThread in wxExecute"); + } + + // close unneeded handle + if ( !::CloseHandle(pi.hThread) ) + wxLogLastError("CloseHandle(hThread)"); + if ( !hThread ) { wxLogLastError("CreateThread in wxExecute"); @@ -333,10 +346,20 @@ long wxExecute(const wxString& command, bool sync, wxProcess *handler) return pi.dwProcessId; } - // waiting until command executed + // waiting until command executed (disable everything while doing it) +#if wxUSE_GUI + wxBeginBusyCursor(); + wxEnableTopLevelWindows(FALSE); +#endif // wxUSE_GUI + while ( data->state ) wxYield(); +#if wxUSE_GUI + wxEnableTopLevelWindows(TRUE); + wxEndBusyCursor(); +#endif // wxUSE_GUI + DWORD dwExitCode = data->dwExitCode; delete data; -- 2.45.2