Commit cd762252 authored by Brad King's avatar Brad King 💬
Browse files

ENH: Adding vtkWin32ProcessOutputWindow class and supporting...

ENH: Adding vtkWin32ProcessOutputWindow class and supporting vtkWin32OutputWindowProcess executable.  These can be used to have VTK output window messages go to a separate process.  This way users can always seen and interact with message no matter what happens to the original process.
parent cbf34313
......@@ -5,6 +5,13 @@ SET(KIT_PYTHON_LIBS)
SET(KIT_JAVA_LIBS)
SET(KIT_LIBS)
IF(WIN32)
IF (NOT VTK_USE_X)
ADD_EXECUTABLE(vtkWin32OutputWindowProcess WIN32
vtkWin32OutputWindowProcess.c)
ENDIF (NOT VTK_USE_X)
ENDIF(WIN32)
IF (APPLE)
SET(KIT_LIBS ${KIT_LIBS} "-framework AppKit")
ENDIF (APPLE)
......@@ -214,7 +221,8 @@ vtkXMLFileOutputWindow.cxx
IF (WIN32)
IF (NOT VTK_USE_X)
SET(Kit_SRCS ${Kit_SRCS} vtkWin32OutputWindow.cxx)
SET(Kit_SRCS ${Kit_SRCS} vtkWin32OutputWindow.cxx
vtkWin32ProcessOutputWindow.cxx)
ENDIF (NOT VTK_USE_X)
ENDIF (WIN32)
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkWin32OutputWindowProcess.c
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include <windows.h>
#include <tchar.h>
static HWND MainWindow = 0;
static HWND EditWindow = 0;
static LPCTSTR MainWindowClass = _T("vtkOutputWindowProcess");
static LPCTSTR EditWindowClass = _T("EDIT");
static LONG MainWindowStyle = (WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW);
static LONG EditWindowStyle = (ES_MULTILINE | ES_READONLY | WS_CHILD |
ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_VISIBLE |
WS_VSCROLL | WS_HSCROLL | WS_MAXIMIZE);
static LRESULT APIENTRY MainWindowProc(HWND hWnd, UINT m, WPARAM w, LPARAM l)
{
switch (m)
{
case WM_SIZE:
MoveWindow(EditWindow, 0, 0, LOWORD(l), HIWORD(l), TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, m, w, l);
}
static void RegisterWindowClass()
{
WNDCLASS wndClass;
if(!GetClassInfo(GetModuleHandle(0), MainWindowClass, &wndClass))
{
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = MainWindowProc;
wndClass.cbClsExtra = 0;
wndClass.hInstance = GetModuleHandle(0);
wndClass.hIcon = LoadIcon(0, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(0, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.lpszMenuName = 0;
wndClass.lpszClassName = MainWindowClass;
wndClass.cbWndExtra = 0;
RegisterClass(&wndClass);
}
}
static DWORD WINAPI ReadThreadProc(LPVOID p)
{
char buffer[1024];
DWORD nRead = 0;
while(ReadFile(GetStdHandle(STD_INPUT_HANDLE), buffer, 1024, &nRead, 0))
{
buffer[nRead] = 0;
SendMessage(EditWindow, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
SendMessage(EditWindow, EM_REPLACESEL, (WPARAM)0, (LPARAM)buffer);
}
return (DWORD)p;
}
void MainEventLoop()
{
BOOL b;
MSG msg;
while((b = GetMessage(&msg, 0, 0, 0)) != 0 && b != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev,
PSTR szCmdLine, int iCmdShow)
{
(void)hInst; (void)hPrev; (void)szCmdLine; (void)iCmdShow;
/* Create a simple GUI. */
RegisterWindowClass();
MainWindow = CreateWindow(MainWindowClass, MainWindowClass, MainWindowStyle,
0,0,512,512, 0, 0, GetModuleHandle(0), 0);
EditWindow = CreateWindow(EditWindowClass, "", EditWindowStyle,
0,0,512,512, MainWindow, 0, GetModuleHandle(0), 0);
ShowWindow(MainWindow, SW_SHOW);
UpdateWindow(MainWindow);
/* Create a thread to read from standard input and write to the window. */
{DWORD threadId; CreateThread(0, 1024, ReadThreadProc, 0, 0, &threadId);}
/* Run the event loop until the window is closed. */
MainEventLoop();
return 0;
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkWin32ProcessOutputWindow.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkWin32ProcessOutputWindow.h"
#include "vtkObjectFactory.h"
vtkCxxRevisionMacro(vtkWin32ProcessOutputWindow, "1.1");
vtkStandardNewMacro(vtkWin32ProcessOutputWindow);
//----------------------------------------------------------------------------
vtkWin32ProcessOutputWindow::vtkWin32ProcessOutputWindow()
{
this->OutputPipe = 0;
this->Executable = 0;
this->Broken = 0;
}
//----------------------------------------------------------------------------
vtkWin32ProcessOutputWindow::~vtkWin32ProcessOutputWindow()
{
this->SetExecutable(0);
if(this->OutputPipe)
{
CloseHandle(this->OutputPipe);
}
}
//----------------------------------------------------------------------------
void vtkWin32ProcessOutputWindow::DisplayText(const char* text)
{
// Display the text if the pipe has not been broken.
if(!this->Broken && this->Executable && text)
{
const char* begin = text;
while(const char* end = strchr(begin, '\n'))
{
this->Write(begin, end-begin);
this->Write("\r\n", 2);
begin = end+1;
}
this->Write(begin, strlen(begin));
}
}
//----------------------------------------------------------------------------
int vtkWin32ProcessOutputWindow::Initialize()
{
// Create a process and a pipe connected to its stdin.
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags |= STARTF_USESHOWWINDOW;
si.dwFlags |= STARTF_USESTDHANDLES;
si.wShowWindow = SW_SHOWDEFAULT;
// Create a pipe with an inherited read end.
if(!CreatePipe(&si.hStdInput, &this->OutputPipe, 0, 0) ||
!DuplicateHandle(GetCurrentProcess(), si.hStdInput,
GetCurrentProcess(), &si.hStdInput,
0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
{
return 0;
}
// Create the child process.
if(!CreateProcess(0, this->Executable, 0, 0, TRUE,
NORMAL_PRIORITY_CLASS, 0, 0, &si, &pi))
{
CloseHandle(si.hStdInput);
return 0;
}
// We only need to keep the pipe write end. Close all other handles.
CloseHandle(si.hStdInput);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return 1;
}
//----------------------------------------------------------------------------
void vtkWin32ProcessOutputWindow::Write(const char* data, int length)
{
if(data && length)
{
// Initialize the output pipe the first time.
if(this->Broken || !this->OutputPipe && !this->Initialize())
{
this->Broken = 1;
return;
}
// Write the data to the pipe. If it breaks, close the pipe.
DWORD nWritten;
if(!WriteFile(this->OutputPipe, data, length, &nWritten, 0))
{
this->Broken = 1;
CloseHandle(this->OutputPipe);
this->OutputPipe = 0;
}
}
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkWin32ProcessOutputWindow.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// .NAME vtkWin32ProcessOutputWindow - Win32-specific output window class
// .SECTION Description
// vtkWin32ProcessOutputWindow executes a process and sends messages
// to its standard input pipe. This is useful to have a separate
// process display VTK errors so that if a VTK application crashes,
// the error messages are still available.
#ifndef __vtkWin32ProcessOutputWindow_h
#define __vtkWin32ProcessOutputWindow_h
#include "vtkOutputWindow.h"
class VTK_COMMON_EXPORT vtkWin32ProcessOutputWindow : public vtkOutputWindow
{
public:
vtkTypeRevisionMacro(vtkWin32ProcessOutputWindow,vtkOutputWindow);
static vtkWin32ProcessOutputWindow* New();
// Description:
// Send text to the output window process.
virtual void DisplayText(const char*);
// Description:
// Get/Set the executable that is executed and given messages.
vtkSetStringMacro(Executable);
vtkGetStringMacro(Executable);
protected:
vtkWin32ProcessOutputWindow();
~vtkWin32ProcessOutputWindow();
int Initialize();
void Write(const char* data, int length);
// The write end of the pipe to the child process.
HANDLE OutputPipe;
// The executable to run.
char* Executable;
// Whether the pipe has been broken.
int Broken;
private:
vtkWin32ProcessOutputWindow(const vtkWin32ProcessOutputWindow&); // Not implemented.
void operator=(const vtkWin32ProcessOutputWindow&); // Not implemented.
};
#endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment