1 | #ifndef __cxxtest__Win32Gui_h__ |
---|
2 | #define __cxxtest__Win32Gui_h__ |
---|
3 | |
---|
4 | // |
---|
5 | // The Win32Gui displays a simple progress bar using the Win32 API. |
---|
6 | // |
---|
7 | // It accepts the following command line options: |
---|
8 | // -minimized Start minimized, pop up on error |
---|
9 | // -keep Don't close the window at the end |
---|
10 | // -title TITLE Set the window caption |
---|
11 | // |
---|
12 | // If both -minimized and -keep are specified, GUI will only keep the |
---|
13 | // window if it's in focus. |
---|
14 | // |
---|
15 | // N.B. If you're wondering why this class doesn't use any standard |
---|
16 | // library or STL (<string> would have been nice) it's because it only |
---|
17 | // uses "straight" Win32 API. |
---|
18 | // |
---|
19 | |
---|
20 | #include <cxxtest/Gui.h> |
---|
21 | |
---|
22 | #include <windows.h> |
---|
23 | #include <commctrl.h> |
---|
24 | |
---|
25 | namespace CxxTest |
---|
26 | { |
---|
27 | class Win32Gui : public GuiListener |
---|
28 | { |
---|
29 | public: |
---|
30 | void enterGui( int &argc, char **argv ) |
---|
31 | { |
---|
32 | parseCommandLine( argc, argv ); |
---|
33 | } |
---|
34 | |
---|
35 | void enterWorld( const WorldDescription &wd ) |
---|
36 | { |
---|
37 | getTotalTests( wd ); |
---|
38 | _testsDone = 0; |
---|
39 | startGuiThread(); |
---|
40 | } |
---|
41 | |
---|
42 | void guiEnterSuite( const char *suiteName ) |
---|
43 | { |
---|
44 | showSuiteName( suiteName ); |
---|
45 | reset( _suiteStart ); |
---|
46 | } |
---|
47 | |
---|
48 | void guiEnterTest( const char *suiteName, const char *testName ) |
---|
49 | { |
---|
50 | ++ _testsDone; |
---|
51 | setTestCaption( suiteName, testName ); |
---|
52 | showTestName( testName ); |
---|
53 | showTestsDone(); |
---|
54 | progressBarMessage( PBM_STEPIT ); |
---|
55 | reset( _testStart ); |
---|
56 | } |
---|
57 | |
---|
58 | void yellowBar() |
---|
59 | { |
---|
60 | setColor( 255, 255, 0 ); |
---|
61 | setIcon( IDI_WARNING ); |
---|
62 | getTotalTests(); |
---|
63 | } |
---|
64 | |
---|
65 | void redBar() |
---|
66 | { |
---|
67 | if ( _startMinimized ) |
---|
68 | showMainWindow( SW_SHOWNORMAL ); |
---|
69 | setColor( 255, 0, 0 ); |
---|
70 | setIcon( IDI_ERROR ); |
---|
71 | getTotalTests(); |
---|
72 | } |
---|
73 | |
---|
74 | void leaveGui() |
---|
75 | { |
---|
76 | if ( keep() ) |
---|
77 | { |
---|
78 | showSummary(); |
---|
79 | WaitForSingleObject( _gui, INFINITE ); |
---|
80 | } |
---|
81 | DestroyWindow( _mainWindow ); |
---|
82 | } |
---|
83 | |
---|
84 | private: |
---|
85 | const char *_title; |
---|
86 | bool _startMinimized, _keep; |
---|
87 | HANDLE _gui; |
---|
88 | WNDCLASSEX _windowClass; |
---|
89 | HWND _mainWindow, _progressBar, _statusBar; |
---|
90 | HANDLE _canStartTests; |
---|
91 | unsigned _numTotalTests, _testsDone; |
---|
92 | char _strTotalTests[WorldDescription::MAX_STRLEN_TOTAL_TESTS]; |
---|
93 | enum { |
---|
94 | STATUS_SUITE_NAME, STATUS_SUITE_TIME, |
---|
95 | STATUS_TEST_NAME, STATUS_TEST_TIME, |
---|
96 | STATUS_TESTS_DONE, STATUS_WORLD_TIME, |
---|
97 | STATUS_TOTAL_PARTS |
---|
98 | }; |
---|
99 | int _statusWidths[STATUS_TOTAL_PARTS]; |
---|
100 | unsigned _statusOffsets[STATUS_TOTAL_PARTS]; |
---|
101 | unsigned _statusTotal; |
---|
102 | char _statusTestsDone[sizeof("1000000000 of (100%)") + WorldDescription::MAX_STRLEN_TOTAL_TESTS]; |
---|
103 | DWORD _worldStart, _suiteStart, _testStart; |
---|
104 | char _timeString[sizeof("00:00:00")]; |
---|
105 | |
---|
106 | void parseCommandLine( int argc, char **argv ) |
---|
107 | { |
---|
108 | _startMinimized = _keep = false; |
---|
109 | _title = argv[0]; |
---|
110 | |
---|
111 | for ( int i = 1; i < argc; ++ i ) |
---|
112 | { |
---|
113 | if ( !lstrcmpA( argv[i], "-minimized" ) ) |
---|
114 | _startMinimized = true; |
---|
115 | else if ( !lstrcmpA( argv[i], "-keep" ) ) |
---|
116 | _keep = true; |
---|
117 | else if ( !lstrcmpA( argv[i], "-title" ) && (i + 1 < argc) ) |
---|
118 | _title = argv[++i]; |
---|
119 | } |
---|
120 | } |
---|
121 | |
---|
122 | void getTotalTests() |
---|
123 | { |
---|
124 | getTotalTests( tracker().world() ); |
---|
125 | } |
---|
126 | |
---|
127 | void getTotalTests( const WorldDescription &wd ) |
---|
128 | { |
---|
129 | _numTotalTests = wd.numTotalTests(); |
---|
130 | wd.strTotalTests( _strTotalTests ); |
---|
131 | } |
---|
132 | |
---|
133 | void startGuiThread() |
---|
134 | { |
---|
135 | _canStartTests = CreateEvent( NULL, TRUE, FALSE, NULL ); |
---|
136 | DWORD threadId; |
---|
137 | _gui = CreateThread( NULL, 0, &(Win32Gui::guiThread), (LPVOID)this, 0, &threadId ); |
---|
138 | WaitForSingleObject( _canStartTests, INFINITE ); |
---|
139 | } |
---|
140 | |
---|
141 | static DWORD WINAPI guiThread( LPVOID parameter ) |
---|
142 | { |
---|
143 | ((Win32Gui *)parameter)->gui(); |
---|
144 | return 0; |
---|
145 | } |
---|
146 | |
---|
147 | void gui() |
---|
148 | { |
---|
149 | registerWindowClass(); |
---|
150 | createMainWindow(); |
---|
151 | initCommonControls(); |
---|
152 | createProgressBar(); |
---|
153 | createStatusBar(); |
---|
154 | centerMainWindow(); |
---|
155 | showMainWindow(); |
---|
156 | startTimer(); |
---|
157 | startTests(); |
---|
158 | |
---|
159 | messageLoop(); |
---|
160 | } |
---|
161 | |
---|
162 | void registerWindowClass() |
---|
163 | { |
---|
164 | _windowClass.cbSize = sizeof(_windowClass); |
---|
165 | _windowClass.style = CS_HREDRAW | CS_VREDRAW; |
---|
166 | _windowClass.lpfnWndProc = &(Win32Gui::windowProcedure); |
---|
167 | _windowClass.cbClsExtra = 0; |
---|
168 | _windowClass.cbWndExtra = sizeof(LONG); |
---|
169 | _windowClass.hInstance = (HINSTANCE)NULL; |
---|
170 | _windowClass.hIcon = (HICON)NULL; |
---|
171 | _windowClass.hCursor = (HCURSOR)NULL; |
---|
172 | _windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); |
---|
173 | _windowClass.lpszMenuName = NULL; |
---|
174 | _windowClass.lpszClassName = TEXT("CxxTest Window Class"); |
---|
175 | _windowClass.hIconSm = (HICON)NULL; |
---|
176 | |
---|
177 | RegisterClassEx( &_windowClass ); |
---|
178 | } |
---|
179 | |
---|
180 | void createMainWindow() |
---|
181 | { |
---|
182 | _mainWindow = createWindow( _windowClass.lpszClassName, WS_OVERLAPPEDWINDOW ); |
---|
183 | } |
---|
184 | |
---|
185 | void initCommonControls() |
---|
186 | { |
---|
187 | HMODULE dll = LoadLibraryA( "comctl32.dll" ); |
---|
188 | if ( !dll ) |
---|
189 | return; |
---|
190 | |
---|
191 | typedef void (WINAPI *FUNC)( void ); |
---|
192 | FUNC func = (FUNC)GetProcAddress( dll, "InitCommonControls" ); |
---|
193 | if ( !func ) |
---|
194 | return; |
---|
195 | |
---|
196 | func(); |
---|
197 | } |
---|
198 | |
---|
199 | void createProgressBar() |
---|
200 | { |
---|
201 | _progressBar = createWindow( PROGRESS_CLASS, WS_CHILD | WS_VISIBLE | PBS_SMOOTH, _mainWindow ); |
---|
202 | |
---|
203 | #ifdef PBM_SETRANGE32 |
---|
204 | progressBarMessage( PBM_SETRANGE32, 0, _numTotalTests ); |
---|
205 | #else // No PBM_SETRANGE32, use PBM_SETRANGE |
---|
206 | progressBarMessage( PBM_SETRANGE, 0, MAKELPARAM( 0, (WORD)_numTotalTests ) ); |
---|
207 | #endif // PBM_SETRANGE32 |
---|
208 | progressBarMessage( PBM_SETPOS, 0 ); |
---|
209 | progressBarMessage( PBM_SETSTEP, 1 ); |
---|
210 | greenBar(); |
---|
211 | UpdateWindow( _progressBar ); |
---|
212 | } |
---|
213 | |
---|
214 | void createStatusBar() |
---|
215 | { |
---|
216 | _statusBar = createWindow( STATUSCLASSNAME, WS_CHILD | WS_VISIBLE, _mainWindow ); |
---|
217 | setRatios( 4, 1, 3, 1, 3, 1 ); |
---|
218 | } |
---|
219 | |
---|
220 | void setRatios( unsigned suiteNameRatio, unsigned suiteTimeRatio, |
---|
221 | unsigned testNameRatio, unsigned testTimeRatio, |
---|
222 | unsigned testsDoneRatio, unsigned worldTimeRatio ) |
---|
223 | { |
---|
224 | _statusTotal = 0; |
---|
225 | _statusOffsets[STATUS_SUITE_NAME] = (_statusTotal += suiteNameRatio); |
---|
226 | _statusOffsets[STATUS_SUITE_TIME] = (_statusTotal += suiteTimeRatio); |
---|
227 | _statusOffsets[STATUS_TEST_NAME] = (_statusTotal += testNameRatio); |
---|
228 | _statusOffsets[STATUS_TEST_TIME] = (_statusTotal += testTimeRatio); |
---|
229 | _statusOffsets[STATUS_TESTS_DONE] = (_statusTotal += testsDoneRatio); |
---|
230 | _statusOffsets[STATUS_WORLD_TIME] = (_statusTotal += worldTimeRatio); |
---|
231 | } |
---|
232 | |
---|
233 | HWND createWindow( LPCTSTR className, DWORD style, HWND parent = (HWND)NULL ) |
---|
234 | { |
---|
235 | return CreateWindow( className, NULL, style, 0, 0, 0, 0, parent, |
---|
236 | (HMENU)NULL, (HINSTANCE)NULL, (LPVOID)this ); |
---|
237 | } |
---|
238 | |
---|
239 | void progressBarMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 ) |
---|
240 | { |
---|
241 | SendMessage( _progressBar, message, wParam, lParam ); |
---|
242 | } |
---|
243 | |
---|
244 | void centerMainWindow() |
---|
245 | { |
---|
246 | RECT screen; |
---|
247 | getScreenArea( screen ); |
---|
248 | |
---|
249 | LONG screenWidth = screen.right - screen.left; |
---|
250 | LONG screenHeight = screen.bottom - screen.top; |
---|
251 | |
---|
252 | LONG xCenter = (screen.right + screen.left) / 2; |
---|
253 | LONG yCenter = (screen.bottom + screen.top) / 2; |
---|
254 | |
---|
255 | LONG windowWidth = (screenWidth * 4) / 5; |
---|
256 | LONG windowHeight = screenHeight / 10; |
---|
257 | LONG minimumHeight = 2 * (GetSystemMetrics( SM_CYCAPTION ) + GetSystemMetrics( SM_CYFRAME )); |
---|
258 | if ( windowHeight < minimumHeight ) |
---|
259 | windowHeight = minimumHeight; |
---|
260 | |
---|
261 | SetWindowPos( _mainWindow, HWND_TOP, |
---|
262 | xCenter - (windowWidth / 2), yCenter - (windowHeight / 2), |
---|
263 | windowWidth, windowHeight, 0 ); |
---|
264 | } |
---|
265 | |
---|
266 | void getScreenArea( RECT &area ) |
---|
267 | { |
---|
268 | if ( !getScreenAreaWithoutTaskbar( area ) ) |
---|
269 | getWholeScreenArea( area ); |
---|
270 | } |
---|
271 | |
---|
272 | bool getScreenAreaWithoutTaskbar( RECT &area ) |
---|
273 | { |
---|
274 | return (SystemParametersInfo( SPI_GETWORKAREA, sizeof(RECT), &area, 0 ) != 0); |
---|
275 | } |
---|
276 | |
---|
277 | void getWholeScreenArea( RECT &area ) |
---|
278 | { |
---|
279 | area.left = area.top = 0; |
---|
280 | area.right = GetSystemMetrics( SM_CXSCREEN ); |
---|
281 | area.bottom = GetSystemMetrics( SM_CYSCREEN ); |
---|
282 | } |
---|
283 | |
---|
284 | void showMainWindow() |
---|
285 | { |
---|
286 | showMainWindow( _startMinimized ? SW_MINIMIZE : SW_SHOWNORMAL ); |
---|
287 | UpdateWindow( _mainWindow ); |
---|
288 | } |
---|
289 | |
---|
290 | void showMainWindow( int mode ) |
---|
291 | { |
---|
292 | ShowWindow( _mainWindow, mode ); |
---|
293 | } |
---|
294 | |
---|
295 | enum { TIMER_ID = 1, TIMER_DELAY = 1000 }; |
---|
296 | |
---|
297 | void startTimer() |
---|
298 | { |
---|
299 | reset( _worldStart ); |
---|
300 | reset( _suiteStart ); |
---|
301 | reset( _testStart ); |
---|
302 | SetTimer( _mainWindow, TIMER_ID, TIMER_DELAY, 0 ); |
---|
303 | } |
---|
304 | |
---|
305 | void reset( DWORD &tick ) |
---|
306 | { |
---|
307 | tick = GetTickCount(); |
---|
308 | } |
---|
309 | |
---|
310 | void startTests() |
---|
311 | { |
---|
312 | SetEvent( _canStartTests ); |
---|
313 | } |
---|
314 | |
---|
315 | void messageLoop() |
---|
316 | { |
---|
317 | MSG message; |
---|
318 | while ( BOOL haveMessage = GetMessage( &message, NULL, 0, 0 ) ) |
---|
319 | if ( haveMessage != -1 ) |
---|
320 | DispatchMessage( &message ); |
---|
321 | } |
---|
322 | |
---|
323 | static LRESULT CALLBACK windowProcedure( HWND window, UINT message, WPARAM wParam, LPARAM lParam ) |
---|
324 | { |
---|
325 | if ( message == WM_CREATE ) |
---|
326 | setUp( window, (LPCREATESTRUCT)lParam ); |
---|
327 | |
---|
328 | Win32Gui *that = (Win32Gui *)GetWindowLong( window, GWL_USERDATA ); |
---|
329 | return that->handle( window, message, wParam, lParam ); |
---|
330 | } |
---|
331 | |
---|
332 | static void setUp( HWND window, LPCREATESTRUCT create ) |
---|
333 | { |
---|
334 | SetWindowLong( window, GWL_USERDATA, (LONG)create->lpCreateParams ); |
---|
335 | } |
---|
336 | |
---|
337 | LRESULT handle( HWND window, UINT message, WPARAM wParam, LPARAM lParam ) |
---|
338 | { |
---|
339 | switch ( message ) |
---|
340 | { |
---|
341 | case WM_SIZE: resizeControls(); break; |
---|
342 | |
---|
343 | case WM_TIMER: updateTime(); break; |
---|
344 | |
---|
345 | case WM_CLOSE: |
---|
346 | case WM_DESTROY: |
---|
347 | case WM_QUIT: |
---|
348 | ExitProcess( 0 ); |
---|
349 | |
---|
350 | default: return DefWindowProc( window, message, wParam, lParam ); |
---|
351 | } |
---|
352 | return 0; |
---|
353 | } |
---|
354 | |
---|
355 | void resizeControls() |
---|
356 | { |
---|
357 | RECT r; |
---|
358 | GetClientRect( _mainWindow, &r ); |
---|
359 | LONG width = r.right - r.left; |
---|
360 | LONG height = r.bottom - r.top; |
---|
361 | |
---|
362 | GetClientRect( _statusBar, &r ); |
---|
363 | LONG statusHeight = r.bottom - r.top; |
---|
364 | LONG resizeGripWidth = statusHeight; |
---|
365 | LONG progressHeight = height - statusHeight; |
---|
366 | |
---|
367 | SetWindowPos( _progressBar, HWND_TOP, 0, 0, width, progressHeight, 0 ); |
---|
368 | SetWindowPos( _statusBar, HWND_TOP, 0, progressHeight, width, statusHeight, 0 ); |
---|
369 | setStatusParts( width - resizeGripWidth ); |
---|
370 | } |
---|
371 | |
---|
372 | void setStatusParts( LONG width ) |
---|
373 | { |
---|
374 | for ( unsigned i = 0; i < STATUS_TOTAL_PARTS; ++ i ) |
---|
375 | _statusWidths[i] = (width * _statusOffsets[i]) / _statusTotal; |
---|
376 | |
---|
377 | statusBarMessage( SB_SETPARTS, STATUS_TOTAL_PARTS, _statusWidths ); |
---|
378 | } |
---|
379 | |
---|
380 | void statusBarMessage( UINT message, WPARAM wParam = 0, const void *lParam = 0 ) |
---|
381 | { |
---|
382 | SendMessage( _statusBar, message, wParam, (LPARAM)lParam ); |
---|
383 | } |
---|
384 | |
---|
385 | void greenBar() |
---|
386 | { |
---|
387 | setColor( 0, 255, 0 ); |
---|
388 | setIcon( IDI_INFORMATION ); |
---|
389 | } |
---|
390 | |
---|
391 | #ifdef PBM_SETBARCOLOR |
---|
392 | void setColor( BYTE red, BYTE green, BYTE blue ) |
---|
393 | { |
---|
394 | progressBarMessage( PBM_SETBARCOLOR, 0, RGB( red, green, blue ) ); |
---|
395 | } |
---|
396 | #else // !PBM_SETBARCOLOR |
---|
397 | void setColor( BYTE, BYTE, BYTE ) |
---|
398 | { |
---|
399 | } |
---|
400 | #endif // PBM_SETBARCOLOR |
---|
401 | |
---|
402 | void setIcon( LPCTSTR icon ) |
---|
403 | { |
---|
404 | SendMessage( _mainWindow, WM_SETICON, ICON_BIG, (LPARAM)loadStandardIcon( icon ) ); |
---|
405 | } |
---|
406 | |
---|
407 | HICON loadStandardIcon( LPCTSTR icon ) |
---|
408 | { |
---|
409 | return LoadIcon( (HINSTANCE)NULL, icon ); |
---|
410 | } |
---|
411 | |
---|
412 | void setTestCaption( const char *suiteName, const char *testName ) |
---|
413 | { |
---|
414 | setCaption( suiteName, "::", testName, "()" ); |
---|
415 | } |
---|
416 | |
---|
417 | void setCaption( const char *a = "", const char *b = "", const char *c = "", const char *d = "" ) |
---|
418 | { |
---|
419 | unsigned length = lstrlenA( _title ) + sizeof( " - " ) + |
---|
420 | lstrlenA( a ) + lstrlenA( b ) + lstrlenA( c ) + lstrlenA( d ); |
---|
421 | char *name = allocate( length ); |
---|
422 | lstrcpyA( name, _title ); |
---|
423 | lstrcatA( name, " - " ); |
---|
424 | lstrcatA( name, a ); |
---|
425 | lstrcatA( name, b ); |
---|
426 | lstrcatA( name, c ); |
---|
427 | lstrcatA( name, d ); |
---|
428 | SetWindowTextA( _mainWindow, name ); |
---|
429 | deallocate( name ); |
---|
430 | } |
---|
431 | |
---|
432 | void showSuiteName( const char *suiteName ) |
---|
433 | { |
---|
434 | setStatusPart( STATUS_SUITE_NAME, suiteName ); |
---|
435 | } |
---|
436 | |
---|
437 | void showTestName( const char *testName ) |
---|
438 | { |
---|
439 | setStatusPart( STATUS_TEST_NAME, testName ); |
---|
440 | } |
---|
441 | |
---|
442 | void showTestsDone() |
---|
443 | { |
---|
444 | wsprintfA( _statusTestsDone, "%u of %s (%u%%)", |
---|
445 | _testsDone, _strTotalTests, |
---|
446 | (_testsDone * 100) / _numTotalTests ); |
---|
447 | setStatusPart( STATUS_TESTS_DONE, _statusTestsDone ); |
---|
448 | } |
---|
449 | |
---|
450 | void updateTime() |
---|
451 | { |
---|
452 | setStatusTime( STATUS_WORLD_TIME, _worldStart ); |
---|
453 | setStatusTime( STATUS_SUITE_TIME, _suiteStart ); |
---|
454 | setStatusTime( STATUS_TEST_TIME, _testStart ); |
---|
455 | } |
---|
456 | |
---|
457 | void setStatusTime( unsigned part, DWORD start ) |
---|
458 | { |
---|
459 | unsigned total = (GetTickCount() - start) / 1000; |
---|
460 | unsigned hours = total / 3600; |
---|
461 | unsigned minutes = (total / 60) % 60; |
---|
462 | unsigned seconds = total % 60; |
---|
463 | |
---|
464 | if ( hours ) |
---|
465 | wsprintfA( _timeString, "%u:%02u:%02u", hours, minutes, seconds ); |
---|
466 | else |
---|
467 | wsprintfA( _timeString, "%02u:%02u", minutes, seconds ); |
---|
468 | |
---|
469 | setStatusPart( part, _timeString ); |
---|
470 | } |
---|
471 | |
---|
472 | bool keep() |
---|
473 | { |
---|
474 | if ( !_keep ) |
---|
475 | return false; |
---|
476 | if ( !_startMinimized ) |
---|
477 | return true; |
---|
478 | return (_mainWindow == GetForegroundWindow()); |
---|
479 | } |
---|
480 | |
---|
481 | void showSummary() |
---|
482 | { |
---|
483 | stopTimer(); |
---|
484 | setSummaryStatusBar(); |
---|
485 | setSummaryCaption(); |
---|
486 | } |
---|
487 | |
---|
488 | void setStatusPart( unsigned part, const char *text ) |
---|
489 | { |
---|
490 | statusBarMessage( SB_SETTEXTA, part, text ); |
---|
491 | } |
---|
492 | |
---|
493 | void stopTimer() |
---|
494 | { |
---|
495 | KillTimer( _mainWindow, TIMER_ID ); |
---|
496 | setStatusTime( STATUS_WORLD_TIME, _worldStart ); |
---|
497 | } |
---|
498 | |
---|
499 | void setSummaryStatusBar() |
---|
500 | { |
---|
501 | setRatios( 0, 0, 0, 0, 1, 1 ); |
---|
502 | resizeControls(); |
---|
503 | |
---|
504 | const char *tests = (_numTotalTests == 1) ? "test" : "tests"; |
---|
505 | if ( tracker().failedTests() ) |
---|
506 | wsprintfA( _statusTestsDone, "Failed %u of %s %s", |
---|
507 | tracker().failedTests(), _strTotalTests, tests ); |
---|
508 | else |
---|
509 | wsprintfA( _statusTestsDone, "%s %s passed", _strTotalTests, tests ); |
---|
510 | |
---|
511 | setStatusPart( STATUS_TESTS_DONE, _statusTestsDone ); |
---|
512 | } |
---|
513 | |
---|
514 | void setSummaryCaption() |
---|
515 | { |
---|
516 | setCaption( _statusTestsDone ); |
---|
517 | } |
---|
518 | |
---|
519 | char *allocate( unsigned length ) |
---|
520 | { |
---|
521 | return (char *)HeapAlloc( GetProcessHeap(), 0, length ); |
---|
522 | } |
---|
523 | |
---|
524 | void deallocate( char *data ) |
---|
525 | { |
---|
526 | HeapFree( GetProcessHeap(), 0, data ); |
---|
527 | } |
---|
528 | }; |
---|
529 | }; |
---|
530 | |
---|
531 | #endif // __cxxtest__Win32Gui_h__ |
---|