1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkWin32RenderWindowInteractor.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 #include <stdio.h>
16 #include <cstdlib>
17 #include <string.h>
18 #include <math.h>
19
20
21 #ifndef _WIN32_WINNT
22 #define _WIN32_WINNT 0x0501 // for trackmouseevent support, 0x0501 means target Windows XP or later
23 #endif
24
25 #include "vtkWin32OpenGLRenderWindow.h"
26
27 // Mouse wheel support
28 // In an ideal world we would just have to include <zmouse.h>, but it is not
29 // always available with all compilers/headers
30 #ifndef WM_MOUSEWHEEL
31 # define WM_MOUSEWHEEL 0x020A
32 #endif //WM_MOUSEWHEEL
33 #ifndef GET_WHEEL_DELTA_WPARAM
34 # define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
35 #endif //GET_WHEEL_DELTA_WPARAM
36
37 // MSVC does the right thing without the forward declaration when it
38 // sees it in the friend decl in vtkWin32RenderWindowInteractor, but
39 // GCC needs to see the declaration beforehand. It has to do with the
40 // CALLBACK attribute.
41 VTKRENDERINGOPENGL_EXPORT LRESULT CALLBACK vtkHandleMessage(HWND,UINT,WPARAM,LPARAM);
42 VTKRENDERINGOPENGL_EXPORT LRESULT CALLBACK vtkHandleMessage2(HWND,UINT,WPARAM,LPARAM,class vtkWin32RenderWindowInteractor*);
43
44 #include "vtkWin32RenderWindowInteractor.h"
45 #include "vtkActor.h"
46 #include "vtkOpenGL.h"
47 #include "vtkObjectFactory.h"
48 #include "vtkCommand.h"
49
50 #ifdef VTK_USE_TDX
51 #include "vtkTDxWinDevice.h"
52 #endif
53
54 vtkStandardNewMacro(vtkWin32RenderWindowInteractor);
55
56 void (*vtkWin32RenderWindowInteractor::ClassExitMethod)(void *) = (void (*)(void *))NULL;
57 void *vtkWin32RenderWindowInteractor::ClassExitMethodArg = (void *)NULL;
58 void (*vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete)(void *) = (void (*)(void *))NULL;
59
60 //----------------------------------------------------------------------------
61 // Construct object so that light follows camera motion.
vtkWin32RenderWindowInteractor()62 vtkWin32RenderWindowInteractor::vtkWin32RenderWindowInteractor()
63 {
64 this->WindowId = 0;
65 this->InstallMessageProc = 1;
66 this->MouseInWindow = 0;
67 this->StartedMessageLoop = 0;
68
69 #ifdef VTK_USE_TDX
70 this->Device=vtkTDxWinDevice::New();
71 #endif
72 }
73
74 //----------------------------------------------------------------------------
~vtkWin32RenderWindowInteractor()75 vtkWin32RenderWindowInteractor::~vtkWin32RenderWindowInteractor()
76 {
77 vtkWin32OpenGLRenderWindow *tmp;
78
79 // we need to release any hold we have on a windows event loop
80 if (this->WindowId && this->Enabled && this->InstallMessageProc)
81 {
82 vtkWin32OpenGLRenderWindow *ren;
83 ren = static_cast<vtkWin32OpenGLRenderWindow *>(this->RenderWindow);
84 tmp = (vtkWin32OpenGLRenderWindow *)(vtkGetWindowLong(this->WindowId,sizeof(vtkLONG)));
85 // watch for odd conditions
86 if ((tmp != ren) && (ren != NULL))
87 {
88 // OK someone else has a hold on our event handler
89 // so lets have them handle this stuff
90 // well send a USER message to the other
91 // event handler so that it can properly
92 // call this event handler if required
93 CallWindowProc(this->OldProc,this->WindowId,WM_USER+14,28,(intptr_t)this->OldProc);
94 }
95 else
96 {
97 vtkSetWindowLong(this->WindowId,vtkGWL_WNDPROC,(intptr_t)this->OldProc);
98 }
99 this->Enabled = 0;
100 }
101 #ifdef VTK_USE_TDX
102 this->Device->Delete();
103 #endif
104 }
105
106 //----------------------------------------------------------------------------
StartEventLoop()107 void vtkWin32RenderWindowInteractor::StartEventLoop()
108 {
109 // No need to do anything if this is a 'mapped' interactor
110 if (!this->Enabled || !this->InstallMessageProc)
111 {
112 return;
113 }
114
115 this->StartedMessageLoop = 1;
116
117 MSG msg;
118 while (GetMessage(&msg, NULL, 0, 0))
119 {
120 TranslateMessage(&msg);
121 DispatchMessage(&msg);
122 }
123 }
124
125 //----------------------------------------------------------------------------
126 // Begin processing keyboard strokes.
Initialize()127 void vtkWin32RenderWindowInteractor::Initialize()
128 {
129 vtkWin32OpenGLRenderWindow *ren;
130 int *size;
131
132 // make sure we have a RenderWindow and camera
133 if ( ! this->RenderWindow)
134 {
135 vtkErrorMacro(<<"No renderer defined!");
136 return;
137 }
138 if (this->Initialized)
139 {
140 return;
141 }
142 this->Initialized = 1;
143 // get the info we need from the RenderingWindow
144 ren = (vtkWin32OpenGLRenderWindow *)(this->RenderWindow);
145 ren->Start();
146 size = ren->GetSize();
147 ren->GetPosition();
148 this->WindowId = ren->GetWindowId();
149 this->Enable();
150 this->Size[0] = size[0];
151 this->Size[1] = size[1];
152 }
153
154 //----------------------------------------------------------------------------
Enable()155 void vtkWin32RenderWindowInteractor::Enable()
156 {
157 vtkWin32OpenGLRenderWindow *ren;
158 vtkWin32OpenGLRenderWindow *tmp;
159 if (this->Enabled)
160 {
161 return;
162 }
163 if (this->InstallMessageProc)
164 {
165 // add our callback
166 ren = (vtkWin32OpenGLRenderWindow *)(this->RenderWindow);
167 this->OldProc = (WNDPROC)vtkGetWindowLong(this->WindowId,vtkGWL_WNDPROC);
168 tmp=(vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(this->WindowId,sizeof(vtkLONG));
169 // watch for odd conditions
170 if (tmp != ren)
171 {
172 // OK someone else has a hold on our event handler
173 // so lets have them handle this stuff
174 // well send a USER message to the other
175 // event handler so that it can properly
176 // call this event handler if required
177 CallWindowProc(this->OldProc,this->WindowId,WM_USER+12,24,(intptr_t)vtkHandleMessage);
178 }
179 else
180 {
181 vtkSetWindowLong(this->WindowId,vtkGWL_WNDPROC,(intptr_t)vtkHandleMessage);
182 }
183
184 #ifdef VTK_USE_TDX
185 if(this->UseTDx)
186 {
187 this->Device->SetInteractor(this);
188 this->Device->Initialize();
189 this->Device->StartListening();
190 }
191 #endif
192
193 // in case the size of the window has changed while we were away
194 int *size;
195 size = ren->GetSize();
196 this->Size[0] = size[0];
197 this->Size[1] = size[1];
198 }
199 this->Enabled = 1;
200 this->Modified();
201 }
202
203
204 //----------------------------------------------------------------------------
Disable()205 void vtkWin32RenderWindowInteractor::Disable()
206 {
207 vtkWin32OpenGLRenderWindow *tmp;
208 if (!this->Enabled)
209 {
210 return;
211 }
212
213 if (this->InstallMessageProc && this->Enabled && this->WindowId)
214 {
215 // we need to release any hold we have on a windows event loop
216 vtkWin32OpenGLRenderWindow *ren;
217 ren = (vtkWin32OpenGLRenderWindow *)(this->RenderWindow);
218 tmp = (vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(this->WindowId,sizeof(vtkLONG));
219 // watch for odd conditions
220 if ((tmp != ren) && (ren != NULL))
221 {
222 // OK someone else has a hold on our event handler
223 // so lets have them handle this stuff
224 // well send a USER message to the other
225 // event handler so that it can properly
226 // call this event handler if required
227 CallWindowProc(this->OldProc,this->WindowId,WM_USER+14,28,(intptr_t)this->OldProc);
228 }
229 else
230 {
231 vtkSetWindowLong(this->WindowId,vtkGWL_WNDPROC,(intptr_t)this->OldProc);
232 }
233 #ifdef VTK_USE_TDX
234 if(this->Device->GetInitialized())
235 {
236 this->Device->Close();
237 }
238 #endif
239 }
240 this->Enabled = 0;
241 this->Modified();
242 }
243
244 //----------------------------------------------------------------------------
TerminateApp(void)245 void vtkWin32RenderWindowInteractor::TerminateApp(void)
246 {
247 // Only post a quit message if Start was called...
248 //
249 if (this->StartedMessageLoop)
250 {
251 PostQuitMessage(0);
252 }
253 }
254
255 //----------------------------------------------------------------------------
InternalCreateTimer(int timerId,int vtkNotUsed (timerType),unsigned long duration)256 int vtkWin32RenderWindowInteractor::InternalCreateTimer(int timerId, int vtkNotUsed(timerType),
257 unsigned long duration)
258 {
259 // Win32 always creates repeating timers
260 SetTimer(this->WindowId,timerId,duration,NULL);
261 return timerId;
262 }
263
264 //----------------------------------------------------------------------------
InternalDestroyTimer(int platformTimerId)265 int vtkWin32RenderWindowInteractor::InternalDestroyTimer(int platformTimerId)
266 {
267 return KillTimer(this->WindowId,platformTimerId);
268 }
269
270 //-------------------------------------------------------------
271 // Virtual Key Code to Unix KeySym Conversion
272 //-------------------------------------------------------------
273
274 // this ascii code to keysym table is meant to mimic Tk
275
276 static const char *AsciiToKeySymTable[] = {
277 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
278 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
279 "space", "exclam", "quotedbl", "numbersign",
280 "dollar", "percent", "ampersand", "quoteright",
281 "parenleft", "parenright", "asterisk", "plus",
282 "comma", "minus", "period", "slash",
283 "0", "1", "2", "3", "4", "5", "6", "7",
284 "8", "9", "colon", "semicolon", "less", "equal", "greater", "question",
285 "at", "A", "B", "C", "D", "E", "F", "G",
286 "H", "I", "J", "K", "L", "M", "N", "O",
287 "P", "Q", "R", "S", "T", "U", "V", "W",
288 "X", "Y", "Z", "bracketleft",
289 "backslash", "bracketright", "asciicircum", "underscore",
290 "quoteleft", "a", "b", "c", "d", "e", "f", "g",
291 "h", "i", "j", "k", "l", "m", "n", "o",
292 "p", "q", "r", "s", "t", "u", "v", "w",
293 "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Delete",
294 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
295 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
296 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
298 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
299 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
300 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
302
303 // this virtual key code to keysym table is meant to mimic Tk
304
305 static const char *VKeyCodeToKeySymTable[] = {
306 0, 0, 0, "Cancel", 0, 0, 0, 0,
307 "BackSpace", "Tab", 0, 0, "Clear", "Return", 0, 0,
308 "Shift_L", "Control_L", "Alt_L", "Pause", "Caps_Lock", 0,0,0,
309 0, 0, 0, "Escape", 0, 0, 0, 0,
310 "space", "Prior", "Next", "End", "Home", "Left", "Up", "Right",
311 "Down", "Select", 0, "Execute", "Snapshot", "Insert", "Delete", "Help",
312 "0", "1", "2", "3", "4", "5", "6", "7",
313 "8", "9", 0, 0, 0, 0, 0, 0,
314 0, "a", "b", "c", "d", "e", "f", "g",
315 "h", "i", "j", "k", "l", "m", "n", "o",
316 "p", "q", "r", "s", "t", "u", "v", "w",
317 "x", "y", "z", "Win_L", "Win_R", "App", 0, 0,
318 "KP_0", "KP_1", "KP_2", "KP_3", "KP_4", "KP_5", "KP_6", "KP_7",
319 "KP_8", "KP_9", "asterisk", "plus", "bar", "minus", "period", "slash",
320 "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
321 "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16",
322 "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24",
323 0, 0, 0, 0, 0, 0, 0, 0,
324 "Num_Lock", "Scroll_Lock", 0, 0, 0, 0, 0, 0,
325 0, 0, 0, 0, 0, 0, 0, 0,
326 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
327 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
328 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
329 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
330 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
331 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
332
333 //-------------------------------------------------------------
334 // Event loop handlers
335 //-------------------------------------------------------------
OnMouseMove(HWND hWnd,UINT nFlags,int X,int Y)336 void vtkWin32RenderWindowInteractor::OnMouseMove(HWND hWnd, UINT nFlags,
337 int X, int Y)
338 {
339 if (!this->Enabled)
340 {
341 return;
342 }
343
344 this->SetEventInformationFlipY(X,
345 Y,
346 nFlags & MK_CONTROL,
347 nFlags & MK_SHIFT);
348 this->SetAltKey(GetKeyState(VK_MENU) & (~1));
349 if (!this->MouseInWindow &&
350 (X >= 0 && X < this->Size[0] && Y >= 0 && Y < this->Size[1]))
351 {
352 this->InvokeEvent(vtkCommand::EnterEvent, NULL);
353 this->MouseInWindow = 1;
354 // request WM_MOUSELEAVE generation
355 TRACKMOUSEEVENT tme;
356 tme.cbSize = sizeof(TRACKMOUSEEVENT);
357 tme.dwFlags = TME_LEAVE;
358 tme.hwndTrack = hWnd;
359 TrackMouseEvent(&tme);
360 }
361
362 this->InvokeEvent(vtkCommand::MouseMoveEvent, NULL);
363 }
364
365 //----------------------------------------------------------------------------
OnNCMouseMove(HWND,UINT nFlags,int X,int Y)366 void vtkWin32RenderWindowInteractor::OnNCMouseMove(HWND, UINT nFlags,
367 int X, int Y)
368 {
369 if (!this->Enabled)
370 {
371 return;
372 }
373
374 int *pos = this->RenderWindow->GetPosition();
375 if (this->MouseInWindow)
376 {
377 this->SetEventInformationFlipY(X - pos[0],
378 Y - pos[1],
379 nFlags & MK_CONTROL,
380 nFlags & MK_SHIFT);
381 this->SetAltKey(GetKeyState(VK_MENU) & (~1));
382 this->InvokeEvent(vtkCommand::LeaveEvent, NULL);
383 this->MouseInWindow = 0;
384 }
385 }
386
387 //----------------------------------------------------------------------------
OnMouseWheelForward(HWND,UINT nFlags,int X,int Y)388 void vtkWin32RenderWindowInteractor::OnMouseWheelForward(HWND,UINT nFlags,
389 int X, int Y)
390 {
391 if (!this->Enabled)
392 {
393 return;
394 }
395 this->SetEventInformationFlipY(X,
396 Y,
397 nFlags & MK_CONTROL,
398 nFlags & MK_SHIFT);
399 this->SetAltKey(GetKeyState(VK_MENU) & (~1));
400 this->InvokeEvent(vtkCommand::MouseWheelForwardEvent,NULL);
401 }
402
403 //----------------------------------------------------------------------------
OnMouseWheelBackward(HWND,UINT nFlags,int X,int Y)404 void vtkWin32RenderWindowInteractor::OnMouseWheelBackward(HWND,UINT nFlags,
405 int X, int Y)
406 {
407 if (!this->Enabled)
408 {
409 return;
410 }
411 this->SetEventInformationFlipY(X,
412 Y,
413 nFlags & MK_CONTROL,
414 nFlags & MK_SHIFT);
415 this->SetAltKey(GetKeyState(VK_MENU) & (~1));
416 this->InvokeEvent(vtkCommand::MouseWheelBackwardEvent,NULL);
417 }
418
419 //----------------------------------------------------------------------------
OnLButtonDown(HWND wnd,UINT nFlags,int X,int Y,int repeat)420 void vtkWin32RenderWindowInteractor::OnLButtonDown(HWND wnd,UINT nFlags,
421 int X, int Y, int repeat)
422 {
423 if (!this->Enabled)
424 {
425 return;
426 }
427 SetFocus(wnd);
428 SetCapture(wnd);
429 this->SetEventInformationFlipY(X,
430 Y,
431 nFlags & MK_CONTROL,
432 nFlags & MK_SHIFT,
433 0, repeat);
434 this->SetAltKey(GetKeyState(VK_MENU) & (~1));
435 this->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL);
436 }
437
438 //----------------------------------------------------------------------------
OnLButtonUp(HWND,UINT nFlags,int X,int Y)439 void vtkWin32RenderWindowInteractor::OnLButtonUp(HWND,UINT nFlags,
440 int X, int Y)
441 {
442 if (!this->Enabled)
443 {
444 return;
445 }
446 this->SetEventInformationFlipY(X,
447 Y,
448 nFlags & MK_CONTROL,
449 nFlags & MK_SHIFT);
450 this->SetAltKey(GetKeyState(VK_MENU) & (~1));
451 this->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,NULL);
452 ReleaseCapture( );
453 }
454
455 //----------------------------------------------------------------------------
OnMButtonDown(HWND wnd,UINT nFlags,int X,int Y,int repeat)456 void vtkWin32RenderWindowInteractor::OnMButtonDown(HWND wnd,UINT nFlags,
457 int X, int Y, int repeat)
458 {
459 if (!this->Enabled)
460 {
461 return;
462 }
463 SetFocus(wnd);
464 SetCapture(wnd);
465 this->SetEventInformationFlipY(X,
466 Y,
467 nFlags & MK_CONTROL,
468 nFlags & MK_SHIFT,
469 0, repeat);
470 this->SetAltKey(GetKeyState(VK_MENU) & (~1));
471 this->InvokeEvent(vtkCommand::MiddleButtonPressEvent,NULL);
472 }
473
474 //----------------------------------------------------------------------------
OnMButtonUp(HWND,UINT nFlags,int X,int Y)475 void vtkWin32RenderWindowInteractor::OnMButtonUp(HWND,UINT nFlags,
476 int X, int Y)
477 {
478 if (!this->Enabled)
479 {
480 return;
481 }
482 this->SetEventInformationFlipY(X,
483 Y,
484 nFlags & MK_CONTROL,
485 nFlags & MK_SHIFT);
486 this->SetAltKey(GetKeyState(VK_MENU) & (~1));
487 this->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent,NULL);
488 ReleaseCapture( );
489 }
490
491 //----------------------------------------------------------------------------
OnRButtonDown(HWND wnd,UINT nFlags,int X,int Y,int repeat)492 void vtkWin32RenderWindowInteractor::OnRButtonDown(HWND wnd,UINT nFlags,
493 int X, int Y, int repeat)
494 {
495 if (!this->Enabled)
496 {
497 return;
498 }
499 SetFocus(wnd);
500 SetCapture(wnd);
501 this->SetEventInformationFlipY(X,
502 Y,
503 nFlags & MK_CONTROL,
504 nFlags & MK_SHIFT,
505 0, repeat);
506 this->SetAltKey(GetKeyState(VK_MENU) & (~1));
507 this->InvokeEvent(vtkCommand::RightButtonPressEvent,NULL);
508 }
509
510 //----------------------------------------------------------------------------
OnRButtonUp(HWND,UINT nFlags,int X,int Y)511 void vtkWin32RenderWindowInteractor::OnRButtonUp(HWND,UINT nFlags,
512 int X, int Y)
513 {
514 if (!this->Enabled)
515 {
516 return;
517 }
518 this->SetEventInformationFlipY(X,
519 Y,
520 nFlags & MK_CONTROL,
521 nFlags & MK_SHIFT);
522 this->SetAltKey(GetKeyState(VK_MENU) & (~1));
523 this->InvokeEvent(vtkCommand::RightButtonReleaseEvent,NULL);
524 ReleaseCapture( );
525 }
526
527 //----------------------------------------------------------------------------
OnSize(HWND,UINT,int X,int Y)528 void vtkWin32RenderWindowInteractor::OnSize(HWND,UINT, int X, int Y) {
529 this->UpdateSize(X,Y);
530 if (this->Enabled)
531 {
532 this->InvokeEvent(vtkCommand::ConfigureEvent,NULL);
533 }
534 }
535
536 //----------------------------------------------------------------------------
OnTimer(HWND,UINT timerId)537 void vtkWin32RenderWindowInteractor::OnTimer(HWND,UINT timerId)
538 {
539 if (!this->Enabled)
540 {
541 return;
542 }
543 int tid = static_cast<int>(timerId);
544 this->InvokeEvent(vtkCommand::TimerEvent,(void*)&tid);
545
546 // Here we deal with one-shot versus repeating timers
547 if ( this->IsOneShotTimer(tid) )
548 {
549 KillTimer(this->WindowId,tid); //'cause windows timers are always repeating
550 }
551 }
552
553 //----------------------------------------------------------------------------
OnKeyDown(HWND,UINT vCode,UINT nRepCnt,UINT nFlags)554 void vtkWin32RenderWindowInteractor::OnKeyDown(HWND, UINT vCode, UINT nRepCnt, UINT nFlags)
555 {
556 if (!this->Enabled)
557 {
558 return;
559 }
560 int ctrl = GetKeyState(VK_CONTROL) & (~1);
561 int shift = GetKeyState(VK_SHIFT) & (~1);
562 int alt = GetKeyState(VK_MENU) & (~1);
563 WORD nChar = 0;
564 {
565 #ifndef _WIN32_WCE
566 BYTE keyState[256];
567 GetKeyboardState(keyState);
568 if (ToAscii(vCode,nFlags & 0xff,keyState,&nChar,0) == 0)
569 {
570 nChar = 0;
571 }
572 #endif
573 }
574 const char *keysym = AsciiToKeySymTable[(unsigned char)nChar];
575 if (keysym == 0)
576 {
577 keysym = VKeyCodeToKeySymTable[(unsigned char)vCode];
578 }
579 if (keysym == 0)
580 {
581 keysym = "None";
582 }
583 this->SetKeyEventInformation(ctrl,
584 shift,
585 nChar,
586 nRepCnt,
587 keysym);
588 this->SetAltKey(alt);
589 this->InvokeEvent(vtkCommand::KeyPressEvent, NULL);
590 }
591
592 //----------------------------------------------------------------------------
OnKeyUp(HWND,UINT vCode,UINT nRepCnt,UINT nFlags)593 void vtkWin32RenderWindowInteractor::OnKeyUp(HWND, UINT vCode, UINT nRepCnt, UINT nFlags)
594 {
595 if (!this->Enabled)
596 {
597 return;
598 }
599 int ctrl = GetKeyState(VK_CONTROL) & (~1);
600 int shift = GetKeyState(VK_SHIFT) & (~1);
601 int alt = GetKeyState(VK_MENU) & (~1);
602 WORD nChar = 0;
603 {
604 BYTE keyState[256];
605 #ifndef _WIN32_WCE
606 GetKeyboardState(keyState);
607 if (ToAscii(vCode,nFlags & 0xff,keyState,&nChar,0) == 0)
608 {
609 nChar = 0;
610 }
611 #endif
612 }
613 const char *keysym = AsciiToKeySymTable[(unsigned char)nChar];
614 if (keysym == 0)
615 {
616 keysym = VKeyCodeToKeySymTable[(unsigned char)vCode];
617 }
618 if (keysym == 0)
619 {
620 keysym = "None";
621 }
622 this->SetKeyEventInformation(ctrl,
623 shift,
624 nChar,
625 nRepCnt,
626 keysym);
627 this->SetAltKey(alt);
628 this->InvokeEvent(vtkCommand::KeyReleaseEvent, NULL);
629 }
630
631 //----------------------------------------------------------------------------
OnChar(HWND,UINT nChar,UINT nRepCnt,UINT)632 void vtkWin32RenderWindowInteractor::OnChar(HWND,UINT nChar,
633 UINT nRepCnt, UINT)
634 {
635 if (!this->Enabled)
636 {
637 return;
638 }
639 int ctrl = GetKeyState(VK_CONTROL) & (~1);
640 int shift = GetKeyState(VK_SHIFT) & (~1);
641 int alt = GetKeyState(VK_MENU) & (~1);
642 this->SetKeyEventInformation(ctrl,
643 shift,
644 nChar,
645 nRepCnt);
646 this->SetAltKey(alt);
647 this->InvokeEvent(vtkCommand::CharEvent, NULL);
648 }
649
650 //----------------------------------------------------------------------------
OnFocus(HWND,UINT)651 void vtkWin32RenderWindowInteractor::OnFocus(HWND,UINT)
652 {
653 if (!this->Enabled)
654 {
655 return;
656 }
657
658 #ifdef VTK_USE_TDX
659 if(this->Device->GetInitialized() && !this->Device->GetIsListening())
660 {
661 this->Device->StartListening();
662 }
663 #endif
664 }
665
666 //----------------------------------------------------------------------------
OnKillFocus(HWND,UINT)667 void vtkWin32RenderWindowInteractor::OnKillFocus(HWND,UINT)
668 {
669 if (!this->Enabled)
670 {
671 return;
672 }
673 #ifdef VTK_USE_TDX
674 if(this->Device->GetInitialized() && this->Device->GetIsListening())
675 {
676 this->Device->StopListening();
677 }
678 #endif
679 }
680
681 //----------------------------------------------------------------------------
682 // This is only called when InstallMessageProc is true
vtkHandleMessage(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)683 LRESULT CALLBACK vtkHandleMessage(HWND hWnd,UINT uMsg, WPARAM wParam,
684 LPARAM lParam)
685 {
686 LRESULT res = 0;
687 vtkWin32OpenGLRenderWindow *ren;
688 vtkWin32RenderWindowInteractor *me = 0;
689
690 ren = (vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(hWnd,sizeof(vtkLONG));
691
692 if (ren)
693 {
694 me = (vtkWin32RenderWindowInteractor *)ren->GetInteractor();
695 }
696
697 if (me && me->GetReferenceCount()>0)
698 {
699 me->Register(me);
700 res = vtkHandleMessage2(hWnd,uMsg,wParam,lParam,me);
701 me->UnRegister(me);
702 }
703
704 return res;
705 }
706
707 #ifndef MAKEPOINTS
708 #define MAKEPOINTS(l) (*((POINTS FAR *) & (l)))
709 #endif
710
711 //----------------------------------------------------------------------------
vtkHandleMessage2(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam,vtkWin32RenderWindowInteractor * me)712 LRESULT CALLBACK vtkHandleMessage2(HWND hWnd,UINT uMsg, WPARAM wParam,
713 LPARAM lParam,
714 vtkWin32RenderWindowInteractor *me)
715 {
716 if ((uMsg == WM_USER+13)&&(wParam == 26))
717 {
718 // someone is telling us to set our OldProc
719 me->OldProc = (WNDPROC)lParam;
720 return 1;
721 }
722
723 switch (uMsg)
724 {
725 case WM_PAINT:
726 me->Render();
727 return CallWindowProc(me->OldProc,hWnd,uMsg,wParam,lParam);
728
729 case WM_SIZE:
730 me->OnSize(hWnd,wParam,LOWORD(lParam),HIWORD(lParam));
731 return CallWindowProc(me->OldProc,hWnd,uMsg,wParam,lParam);
732
733 case WM_LBUTTONDBLCLK:
734 me->OnLButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 1);
735 break;
736
737 case WM_LBUTTONDOWN:
738 me->OnLButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 0);
739 break;
740
741 case WM_LBUTTONUP:
742 me->OnLButtonUp(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y);
743 break;
744
745 case WM_MBUTTONDBLCLK:
746 me->OnMButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 1);
747 break;
748
749 case WM_MBUTTONDOWN:
750 me->OnMButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 0);
751 break;
752
753 case WM_MBUTTONUP:
754 me->OnMButtonUp(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y);
755 break;
756
757 case WM_RBUTTONDBLCLK:
758 me->OnRButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 1);
759 break;
760
761 case WM_RBUTTONDOWN:
762 me->OnRButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 0);
763 break;
764
765 case WM_RBUTTONUP:
766 me->OnRButtonUp(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y);
767 break;
768
769 case WM_MOUSELEAVE:
770 me->InvokeEvent(vtkCommand::LeaveEvent, NULL);
771 me->MouseInWindow = 0;
772 break;
773
774 case WM_MOUSEMOVE:
775 me->OnMouseMove(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y);
776 break;
777
778 case WM_MOUSEWHEEL:
779 {
780 POINT pt;
781 pt.x = MAKEPOINTS(lParam).x;
782 pt.y = MAKEPOINTS(lParam).y;
783 ::ScreenToClient(hWnd, &pt);
784 if( GET_WHEEL_DELTA_WPARAM(wParam) > 0)
785 me->OnMouseWheelForward(hWnd,wParam,pt.x,pt.y);
786 else
787 me->OnMouseWheelBackward(hWnd,wParam,pt.x,pt.y);
788 }
789 break;
790
791 #ifdef WM_MCVMOUSEMOVE
792 case WM_NCMOUSEMOVE:
793 me->OnNCMouseMove(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y);
794 break;
795 #endif
796
797 case WM_CLOSE:
798 me->ExitCallback();
799 break;
800
801 case WM_CHAR:
802 me->OnChar(hWnd,wParam,LOWORD(lParam),HIWORD(lParam));
803 break;
804
805 case WM_KEYDOWN:
806 case WM_SYSKEYDOWN:
807 me->OnKeyDown(hWnd,wParam,LOWORD(lParam),HIWORD(lParam));
808 break;
809
810 case WM_KEYUP:
811 case WM_SYSKEYUP:
812 me->OnKeyUp(hWnd,wParam,LOWORD(lParam),HIWORD(lParam));
813 break;
814
815 case WM_TIMER:
816 me->OnTimer(hWnd,wParam);
817 break;
818
819 case WM_ACTIVATE:
820 if(wParam==WA_INACTIVE)
821 {
822 me->OnKillFocus(hWnd,wParam);
823 }
824 else
825 {
826 me->OnFocus(hWnd,wParam);
827 }
828 break;
829
830 case WM_SETFOCUS:
831 // occurs when SetFocus() is called on the current window
832 me->OnFocus(hWnd,wParam);
833 break;
834
835 case WM_KILLFOCUS:
836 // occurs when the focus was on the current window and SetFocus() is
837 // called on another window.
838 me->OnKillFocus(hWnd,wParam);
839 break;
840
841 default:
842 if (me)
843 {
844 return CallWindowProc(me->OldProc,hWnd,uMsg,wParam,lParam);
845 }
846 };
847
848 return 0;
849 }
850
851 //----------------------------------------------------------------------------
852 // Specify the default function to be called when an interactor needs to exit.
853 // This callback is overridden by an instance ExitMethod that is defined.
854 void
SetClassExitMethod(void (* f)(void *),void * arg)855 vtkWin32RenderWindowInteractor::SetClassExitMethod(void (*f)(void *),void *arg)
856 {
857 if ( f != vtkWin32RenderWindowInteractor::ClassExitMethod
858 || arg != vtkWin32RenderWindowInteractor::ClassExitMethodArg)
859 {
860 // delete the current arg if there is a delete method
861 if ((vtkWin32RenderWindowInteractor::ClassExitMethodArg)
862 && (vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete))
863 {
864 (*vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete)
865 (vtkWin32RenderWindowInteractor::ClassExitMethodArg);
866 }
867 vtkWin32RenderWindowInteractor::ClassExitMethod = f;
868 vtkWin32RenderWindowInteractor::ClassExitMethodArg = arg;
869
870 // no call to this->Modified() since this is a class member function
871 }
872 }
873
874 //----------------------------------------------------------------------------
875 // Set the arg delete method. This is used to free user memory.
876 void
SetClassExitMethodArgDelete(void (* f)(void *))877 vtkWin32RenderWindowInteractor::SetClassExitMethodArgDelete(void (*f)(void *))
878 {
879 if (f != vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete)
880 {
881 vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete = f;
882
883 // no call to this->Modified() since this is a class member function
884 }
885 }
886
887 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)888 void vtkWin32RenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent)
889 {
890 this->Superclass::PrintSelf(os,indent);
891 os << indent << "InstallMessageProc: " << this->InstallMessageProc << endl;
892 os << indent << "StartedMessageLoop: " << this->StartedMessageLoop << endl;
893 }
894
895 //----------------------------------------------------------------------------
ExitCallback()896 void vtkWin32RenderWindowInteractor::ExitCallback()
897 {
898 if (this->HasObserver(vtkCommand::ExitEvent))
899 {
900 this->InvokeEvent(vtkCommand::ExitEvent,NULL);
901 }
902 else if (this->ClassExitMethod)
903 {
904 (*this->ClassExitMethod)(this->ClassExitMethodArg);
905 }
906
907 this->TerminateApp();
908 }
909