1 /*=========================================================================
2 *
3 * Copyright Insight Software Consortium
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18 /*=========================================================================
19 *
20 * Portions of this file are subject to the VTK Toolkit Version 3 copyright.
21 *
22 * Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
23 *
24 * For complete copyright, license and disclaimer of warranty information
25 * please refer to the NOTICE file at the top of the ITK source tree.
26 *
27 *=========================================================================*/
28 #include "itkWin32OutputWindow.h"
29
30 namespace itk
31 {
32 /** */
33 HWND Win32OutputWindow:: m_OutputWindow = 0;
34
35 Win32OutputWindow
~Win32OutputWindow()36 ::~Win32OutputWindow()
37 {
38 if ( Win32OutputWindow::m_OutputWindow )
39 {
40 DestroyWindow(Win32OutputWindow::m_OutputWindow);
41 Win32OutputWindow::m_OutputWindow = nullptr;
42 }
43 }
44
45 /** */
46 LRESULT APIENTRY
47 Win32OutputWindow
WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)48 ::WndProc(HWND hWnd, UINT message,
49 WPARAM wParam,
50 LPARAM lParam)
51 {
52 switch ( message )
53 {
54 case WM_SIZE:
55 {
56 /** width of client area */
57 int w = LOWORD(lParam);
58
59 /** height of client area */
60 int h = HIWORD(lParam);
61
62 MoveWindow(Win32OutputWindow::m_OutputWindow,
63 0, 0, w, h, true);
64 }
65 break;
66 case WM_DESTROY:
67 Win32OutputWindow::m_OutputWindow = nullptr;
68 Object::GlobalWarningDisplayOff();
69 break;
70 case WM_CLOSE:
71 if ( Win32OutputWindow::m_OutputWindow )
72 {
73 DestroyWindow(Win32OutputWindow::m_OutputWindow);
74 Win32OutputWindow::m_OutputWindow = nullptr;
75 }
76 break;
77 case WM_CREATE:
78 break;
79 }
80 return DefWindowProc(hWnd, message, wParam, lParam);
81 }
82
83 /** Display text in the window, and translate the \n to \r\n. */
84 void
85 Win32OutputWindow
DisplayText(const char * text)86 ::DisplayText(const char *text)
87 {
88 if ( !text )
89 {
90 return;
91 }
92
93 if ( this->GetPromptUser() )
94 {
95 this->PromptText(text);
96 return;
97 }
98
99 /** Create a buffer big enough to hold the entire text */
100 char *buffer = new char[strlen(text) + 1];
101
102 /** Start at the beginning */
103 const char *NewLinePos = text;
104 while ( NewLinePos )
105 {
106 /** Find the next new line in text */
107 NewLinePos = strchr(text, '\n');
108 /** if no new line is found then just add the text */
109 if ( NewLinePos == 0 )
110 {
111 Win32OutputWindow::AddText(text);
112 }
113 /** if a new line is found copy it to the buffer
114 * and add the buffer with a control new line */
115 else
116 {
117 int len = NewLinePos - text;
118 strncpy(buffer, text, len);
119 buffer[len] = 0;
120 text = NewLinePos + 1;
121 Win32OutputWindow::AddText(buffer);
122 Win32OutputWindow::AddText("\r\n");
123 }
124 }
125 delete[] buffer;
126 }
127
128 /** Add some text to the EDIT control. */
129 void
130 Win32OutputWindow
AddText(const char * text)131 ::AddText(const char *text)
132 {
133 if ( !Initialize() || ( strlen(text) == 0 ) )
134 {
135 return;
136 }
137
138 /** move to the end of the text area */
139 SendMessage(Win32OutputWindow::m_OutputWindow, EM_SETSEL,
140 (WPARAM)-1, (LPARAM)-1);
141
142 /** Append the text to the control */
143 SendMessage(Win32OutputWindow::m_OutputWindow, EM_REPLACESEL,
144 0, (LPARAM)text);
145 }
146
147 /** initialize the output window with an EDIT control and
148 * a container window. */
149 int
150 Win32OutputWindow
Initialize()151 ::Initialize()
152 {
153 /** check to see if it is already initialized */
154 if ( Win32OutputWindow::m_OutputWindow )
155 {
156 return 1;
157 }
158 /** Initialized the output window */
159
160 WNDCLASS wndClass;
161 /** has the class been registered ? */
162 if ( !GetClassInfo(GetModuleHandle(nullptr), "OutputWindow", &wndClass) )
163 {
164 wndClass.style = CS_HREDRAW | CS_VREDRAW;
165 wndClass.lpfnWndProc = Win32OutputWindow::WndProc;
166 wndClass.cbClsExtra = 0;
167 wndClass.hInstance = GetModuleHandle(nullptr);
168 wndClass.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
169 wndClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
170 wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
171 wndClass.lpszMenuName = nullptr;
172 wndClass.lpszClassName = "OutputWindow";
173 /** doesn't use these extra 4 bytes, but app writers may want them,
174 * so we provide them. */
175 wndClass.cbWndExtra = 4;
176 RegisterClass(&wndClass);
177 }
178
179 /** create parent container window */
180 HWND win = CreateWindow(
181 "OutputWindow", "OutputWindow",
182 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
183 0, 0, 1024, 768,
184 nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
185
186 /** Now create child window with text display box */
187 CREATESTRUCT lpParam;
188 lpParam.hInstance = GetModuleHandle(nullptr);
189 lpParam.hMenu = nullptr;
190 lpParam.hwndParent = win;
191 lpParam.cx = 1024;
192 lpParam.cy = 768;
193 lpParam.x = 0;
194 lpParam.y = 0;
195 lpParam.style = ES_MULTILINE | ES_READONLY | WS_CHILD
196 | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_VISIBLE | WS_MAXIMIZE
197 | WS_VSCROLL | WS_HSCROLL;
198
199 lpParam.lpszName = "Output Control";
200 lpParam.lpszClass = "EDIT"; // use the RICHEDIT control widget
201 lpParam.dwExStyle = 0;
202
203 /**Create the EDIT window as a child of win */
204 Win32OutputWindow::m_OutputWindow = CreateWindow(
205 lpParam.lpszClass, // pointer to registered class name
206 "", // pointer to window name
207 lpParam.style, // window style
208 lpParam.x, // horizontal position of window
209 lpParam.y, // vertical position of window
210 lpParam.cx, // window width
211 lpParam.cy, // window height
212 lpParam.hwndParent, // handle to parent or owner window
213 nullptr, // handle to menu or child-window identifier
214 lpParam.hInstance, // handle to application instance
215 &lpParam // pointer to window-creation data
216 );
217 constexpr int maxsize = 5242880;
218
219 SendMessage(Win32OutputWindow::m_OutputWindow,
220 EM_LIMITTEXT, maxsize, 0L);
221
222 /** show the top level container window */
223 ShowWindow(win, SW_SHOW);
224 return 1;
225 }
226
227 /** Prompt some text */
228 void
229 Win32OutputWindow
PromptText(const char * text)230 ::PromptText(const char *text)
231 {
232 std::ostringstream msg;
233
234 msg << text << "\nPress Cancel to suppress any further messages.";
235 if ( MessageBox(nullptr, msg.str().c_str(), "Error",
236 MB_ICONERROR | MB_OKCANCEL) == IDCANCEL )
237 {
238 Object::GlobalWarningDisplayOff();
239 }
240 }
241 } // end namespace itk
242