X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/33ac7e6f01acbac1cff0ad400d8ea7f0bfd0a62f..29149a64916d6fdc53e445adca9ef83bc58fb6c3:/src/msw/utils.cpp diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index e32d27860f..dea7aeb352 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -51,8 +51,6 @@ extern "C" { #include "wx/timer.h" -#include - #if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__) #include @@ -90,15 +88,11 @@ extern "C" { #endif #endif -#include -#include -#include #ifndef __WATCOMC__ #if !(defined(_MSC_VER) && (_MSC_VER > 800)) #include #endif #endif -#include //// BEGIN for console support: VC++ only #ifdef __VISUALC__ @@ -109,13 +103,7 @@ extern "C" { #include "wx/ioswrap.h" -#if wxUSE_IOSTREAMH -// N.B. BC++ doesn't have istream.h, ostream.h -# include -# include -#else -# include -#endif +#include "wx/ioswrap.h" /* Need to undef new if including crtdbg.h */ # ifdef new @@ -463,6 +451,16 @@ bool wxDirExists(const wxString& dir) bool wxGetEnv(const wxString& var, wxString *value) { +#ifdef __WIN16__ + const wxChar* ret = wxGetenv(var); + if (ret) + { + *value = ret; + return TRUE; + } + else + return FALSE; +#else // first get the size of the buffer DWORD dwRet = ::GetEnvironmentVariable(var, NULL, 0); if ( !dwRet ) @@ -478,6 +476,7 @@ bool wxGetEnv(const wxString& var, wxString *value) } return TRUE; +#endif } bool wxSetEnv(const wxString& var, const wxChar *value) @@ -502,11 +501,204 @@ bool wxSetEnv(const wxString& var, const wxChar *value) // process management // ---------------------------------------------------------------------------- -int wxKill(long WXUNUSED(pid), int WXUNUSED(sig)) +#ifdef __WIN32__ + +// structure used to pass parameters from wxKill() to wxEnumFindByPidProc() +struct wxFindByPidParams { - // TODO use SendMessage(WM_QUIT) and TerminateProcess() if needed + wxFindByPidParams() { hwnd = 0; pid = 0; } + + // the HWND used to return the result + HWND hwnd; - return 0; + // the PID we're looking from + DWORD pid; +}; + +// wxKill helper: EnumWindows() callback which is used to find the first (top +// level) window belonging to the given process +BOOL CALLBACK wxEnumFindByPidProc(HWND hwnd, LPARAM lParam) +{ + DWORD pid; + (void)::GetWindowThreadProcessId(hwnd, &pid); + + wxFindByPidParams *params = (wxFindByPidParams *)lParam; + if ( pid == params->pid ) + { + // remember the window we found + params->hwnd = hwnd; + + // return FALSE to stop the enumeration + return FALSE; + } + + // continue enumeration + return TRUE; +} + +#endif // __WIN32__ + +int wxKill(long pid, wxSignal sig, wxKillError *krc) +{ +#ifdef __WIN32__ + // get the process handle to operate on + HANDLE hProcess = ::OpenProcess(SYNCHRONIZE | + PROCESS_TERMINATE | + PROCESS_QUERY_INFORMATION, + FALSE, // not inheritable + (DWORD)pid); + if ( hProcess == NULL ) + { + if ( krc ) + { + if ( ::GetLastError() == ERROR_ACCESS_DENIED ) + { + *krc = wxKILL_ACCESS_DENIED; + } + else + { + *krc = wxKILL_NO_PROCESS; + } + } + + return -1; + } + + bool ok = TRUE; + switch ( sig ) + { + case wxSIGKILL: + // kill the process forcefully returning -1 as error code + if ( !::TerminateProcess(hProcess, (UINT)-1) ) + { + wxLogSysError(_("Failed to kill process %d"), pid); + + if ( krc ) + { + // this is not supposed to happen if we could open the + // process + *krc = wxKILL_ERROR; + } + + ok = FALSE; + } + break; + + case wxSIGNONE: + // do nothing, we just want to test for process existence + break; + + default: + // any other signal means "terminate" + { + wxFindByPidParams params; + params.pid = (DWORD)pid; + + // EnumWindows() has nice semantics: it returns 0 if it found + // something or if an error occured and non zero if it + // enumerated all the window + if ( !::EnumWindows(wxEnumFindByPidProc, (LPARAM)¶ms) ) + { + // did we find any window? + if ( params.hwnd ) + { + // tell the app to close + // + // NB: this is the harshest way, the app won't have + // opportunity to save any files, for example, but + // this is probably what we want here. If not we + // can also use SendMesageTimeout(WM_CLOSE) + if ( !::PostMessage(params.hwnd, WM_QUIT, 0, 0) ) + { + wxLogLastError(_T("PostMessage(WM_QUIT)")); + } + } + else // it was an error then + { + wxLogLastError(_T("EnumWindows")); + + ok = FALSE; + } + } + else // no windows for this PID + { + if ( krc ) + { + *krc = wxKILL_ERROR; + } + + ok = FALSE; + } + } + } + + // the return code + DWORD rc; + + if ( ok ) + { + // as we wait for a short time, we can use just WaitForSingleObject() + // and not MsgWaitForMultipleObjects() + switch ( ::WaitForSingleObject(hProcess, 500 /* msec */) ) + { + case WAIT_OBJECT_0: + // process terminated + if ( !::GetExitCodeProcess(hProcess, &rc) ) + { + wxLogLastError(_T("GetExitCodeProcess")); + } + break; + + default: + wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") ); + // fall through + + case WAIT_FAILED: + wxLogLastError(_T("WaitForSingleObject")); + // fall through + + case WAIT_TIMEOUT: + if ( krc ) + { + *krc = wxKILL_ERROR; + } + + rc = STILL_ACTIVE; + break; + } + } + else // !ok + { + // just to suppress the warnings about uninitialized variable + rc = 0; + } + + ::CloseHandle(hProcess); + + // the return code is the same as from Unix kill(): 0 if killed + // successfully or -1 on error + if ( sig == wxSIGNONE ) + { + if ( ok && rc == STILL_ACTIVE ) + { + // there is such process => success + return 0; + } + } + else // not SIGNONE + { + if ( ok && rc != STILL_ACTIVE ) + { + // killed => success + return 0; + } + } +#else // Win15 + wxFAIL_MSG( _T("not implemented") ); +#endif // Win32/Win16 + + // error + return -1; } // Execute a program in an Interactive Shell @@ -658,10 +850,12 @@ int wxGetOsVersion(int *majorVsn, int *minorVsn) #if wxUSE_GUI +#if wxUSE_TIMER + // Sleep for nSecs seconds. Attempt a Windows implementation using timers. static bool gs_inTimer = FALSE; -class wxSleepTimer: public wxTimer +class wxSleepTimer : public wxTimer { public: virtual void Notify() @@ -677,7 +871,7 @@ void wxUsleep(unsigned long milliseconds) { #ifdef __WIN32__ ::Sleep(milliseconds); -#else +#else // !Win32 if (gs_inTimer) return; @@ -691,7 +885,7 @@ void wxUsleep(unsigned long milliseconds) } delete wxTheSleepTimer; wxTheSleepTimer = NULL; -#endif +#endif // Win32/!Win32 } void wxSleep(int nSecs) @@ -717,6 +911,8 @@ void wxFlushEvents() // wxYield(); } +#endif // wxUSE_TIMER + #elif defined(__WIN32__) // wxUSE_GUI void wxUsleep(unsigned long milliseconds) @@ -1034,14 +1230,20 @@ void wxDisplaySizeMM(int *width, int *height) void wxClientDisplayRect(int *x, int *y, int *width, int *height) { +#ifdef __WIN16__ + *x = 0; *y = 0; + wxDisplaySize(width, height); +#else // Determine the desktop dimensions minus the taskbar and any other // special decorations... RECT r; + SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); if (x) *x = r.left; if (y) *y = r.top; if (width) *width = r.right - r.left; if (height) *height = r.bottom - r.top; +#endif } @@ -1113,6 +1315,44 @@ WXWORD WXDLLEXPORT wxGetWindowId(WXHWND hWnd) #endif // wxUSE_GUI +#if wxUSE_GUI + +// ---------------------------------------------------------------------------- +// Metafile helpers +// ---------------------------------------------------------------------------- + +extern void PixelToHIMETRIC(LONG *x, LONG *y) +{ + ScreenHDC hdcRef; + + int iWidthMM = GetDeviceCaps(hdcRef, HORZSIZE), + iHeightMM = GetDeviceCaps(hdcRef, VERTSIZE), + iWidthPels = GetDeviceCaps(hdcRef, HORZRES), + iHeightPels = GetDeviceCaps(hdcRef, VERTRES); + + *x *= (iWidthMM * 100); + *x /= iWidthPels; + *y *= (iHeightMM * 100); + *y /= iHeightPels; +} + +extern void HIMETRICToPixel(LONG *x, LONG *y) +{ + ScreenHDC hdcRef; + + int iWidthMM = GetDeviceCaps(hdcRef, HORZSIZE), + iHeightMM = GetDeviceCaps(hdcRef, VERTSIZE), + iWidthPels = GetDeviceCaps(hdcRef, HORZRES), + iHeightPels = GetDeviceCaps(hdcRef, VERTRES); + + *x *= iWidthPels; + *x /= (iWidthMM * 100); + *y *= iHeightPels; + *y /= (iHeightMM * 100); +} + +#endif // wxUSE_GUI + #if 0 //------------------------------------------------------------------------ // wild character routines