/*========================================================================= Program: Visualization Toolkit Module: vtkWin32OpenGLRenderWindow.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 "vtkWin32OpenGLRenderWindow.h" #include "vtkIdList.h" #include "vtkCommand.h" #include "vtkObjectFactory.h" #include "vtkOpenGLRenderer.h" #include "vtkOpenGLRenderWindow.h" #include "vtkOpenGLError.h" #include "vtkRendererCollection.h" #include "vtkTypeTraits.h" #include "vtkWin32RenderWindowInteractor.h" #include #include #include "vtkOpenGL.h" #include "vtkOpenGLError.h" #include "vtkgl.h" // Mouse wheel support // In an ideal world we would just have to include , but it is not // always available with all compilers/headers #ifndef WM_MOUSEWHEEL # define WM_MOUSEWHEEL 0x020A #endif //WM_MOUSEWHEEL vtkStandardNewMacro(vtkWin32OpenGLRenderWindow); #define VTK_MAX_LIGHTS 8 vtkWin32OpenGLRenderWindow::vtkWin32OpenGLRenderWindow() { this->ApplicationInstance = NULL; this->Palette = NULL; this->ContextId = 0; this->WindowId = 0; this->ParentId = 0; this->NextWindowId = 0; this->DeviceContext = (HDC)0; this->MFChandledWindow = FALSE; this->StereoType = VTK_STEREO_CRYSTAL_EYES; this->CursorHidden = 0; this->Capabilities = 0; this->ScreenDeviceContext = (HDC)0; this->MemoryHdc = (HDC)0; this->CreatingOffScreenWindow = 0; this->WindowIdReferenceCount = 0; this->ScreenMapped = this->Mapped; this->ScreenWindowSize[0] = this->Size[0]; this->ScreenWindowSize[1] = this->Size[1]; this->ScreenDeviceContext = this->DeviceContext; this->ScreenDoubleBuffer = this->DoubleBuffer; this->ScreenContextId = this->ContextId; } vtkWin32OpenGLRenderWindow::~vtkWin32OpenGLRenderWindow() { this->Finalize(); vtkRenderer *ren; vtkCollectionSimpleIterator rit; this->Renderers->InitTraversal(rit); while ((ren = this->Renderers->GetNextRenderer(rit))) { ren->SetRenderWindow(NULL); } delete[] this->Capabilities; } void vtkWin32OpenGLRenderWindow::Clean() { GLuint id; /* finish OpenGL rendering */ if (this->OwnContext && this->ContextId) { this->MakeCurrent(); vtkOpenGLClearErrorMacro(); /* first delete all the old lights */ for (short cur_light = GL_LIGHT0; cur_light < GL_LIGHT0+VTK_MAX_LIGHTS; cur_light++) { glDisable((GLenum)cur_light); } /* now delete all textures */ glDisable(GL_TEXTURE_2D); for (int i = 1; i < this->TextureResourceIds->GetNumberOfIds(); i++) { id = (GLuint)this->TextureResourceIds->GetId(i); #ifdef GL_VERSION_1_1 if (glIsTexture(id)) { glDeleteTextures(1, &id); } #else if (glIsList(id)) { glDeleteLists(id,1); } #endif } vtkOpenGLCheckErrorMacro("failed in Clean"); this->CleanUpRenderers(); // Note: wglMakeCurrent(NULL,NULL) is valid according to the documentation // and works with nVidia and ATI but not with Intel. Passing an existing // device context works in any case. // see VTK Bug 7119. if (wglMakeCurrent(this->DeviceContext,NULL)!=TRUE) { vtkErrorMacro("wglMakeCurrent failed in Clean(), error: " << GetLastError()); } if (wglDeleteContext(this->ContextId) != TRUE) { vtkErrorMacro("wglDeleteContext failed in Clean(), error: " << GetLastError()); } } this->ContextId = NULL; if (this->Palette) { SelectPalette(this->DeviceContext, this->OldPalette, FALSE); // SVA delete the old palette DeleteObject(this->Palette); this->Palette = NULL; } } void vtkWin32OpenGLRenderWindow::CleanUpRenderers() { // tell each of the renderers that this render window/graphics context // is being removed (the RendererCollection is removed by vtkRenderWindow's // destructor) vtkRenderer *ren; vtkCollectionSimpleIterator rsit; for (this->Renderers->InitTraversal(rsit); (ren = this->Renderers->GetNextRenderer(rsit));) { ren->SetRenderWindow(NULL); ren->SetRenderWindow(this); } } LRESULT APIENTRY vtkWin32OpenGLRenderWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT res; vtkWin32OpenGLRenderWindow *me = (vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(hWnd, sizeof(vtkLONG)); if (me && me->GetReferenceCount()>0) { me->Register(me); res = me->MessageProc(hWnd, message, wParam, lParam); me->UnRegister(me); } else { res = DefWindowProc(hWnd, message, wParam, lParam); } return res; } void vtkWin32OpenGLRenderWindow::SetWindowName(const char * _arg) { vtkWindow::SetWindowName(_arg); if (this->WindowId) { #ifdef UNICODE wchar_t *wname = new wchar_t [mbstowcs(NULL, this->WindowName, 32000)+1]; mbstowcs(wname, this->WindowName, 32000); SetWindowText(this->WindowId, wname); delete [] wname; #else SetWindowText(this->WindowId, this->WindowName); #endif } } int vtkWin32OpenGLRenderWindow::GetEventPending() { MSG msg; if (PeekMessage(&msg, this->WindowId, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) { if (msg.message == WM_MOUSEMOVE) { PeekMessage(&msg, this->WindowId, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE); } if ((msg.message == WM_LBUTTONDOWN) || (msg.message == WM_RBUTTONDOWN) || (msg.message == WM_MBUTTONDOWN) || (msg.message == WM_MOUSEWHEEL)) { return 1; } } return 0; } // ---------------------------------------------------------------------------- bool vtkWin32OpenGLRenderWindow::InitializeFromCurrentContext() { HGLRC currentContext = wglGetCurrentContext(); if (currentContext != NULL) { this->SetWindowId(WindowFromDC(wglGetCurrentDC())); this->SetDeviceContext(wglGetCurrentDC()); this->SetContextId(currentContext); this->OpenGLInit(); this->OwnContext = 0; return true; } return false; } // ---------------------------------------------------------------------------- void vtkWin32OpenGLRenderWindow::MakeCurrent() { // Try to avoid doing anything (for performance). HGLRC current = wglGetCurrentContext(); if (this->ContextId != current) { if (this->IsPicking && current) { vtkErrorMacro("Attempting to call MakeCurrent for a different window" " than the one doing the picking, this can causes crashes" " and/or bad pick results"); } else { if (wglMakeCurrent(this->DeviceContext, this->ContextId) != TRUE) { LPVOID lpMsgBuf; ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); if (lpMsgBuf) { #ifdef UNICODE wchar_t *wmsg = new wchar_t [mbstowcs(NULL, (const char*)lpMsgBuf, 32000)+1]; wchar_t *wtemp = new wchar_t [mbstowcs(NULL, "wglMakeCurrent failed in MakeCurrent(), error: ", 32000)+1]; mbstowcs(wmsg, (const char*)lpMsgBuf, 32000); mbstowcs(wtemp, "wglMakeCurrent failed in MakeCurrent(), error: ", 32000); vtkErrorMacro(<< wcscat(wtemp, wmsg)); delete [] wmsg; delete [] wtemp; #else vtkErrorMacro("wglMakeCurrent failed in MakeCurrent(), error: " << (LPCTSTR)lpMsgBuf); #endif ::LocalFree(lpMsgBuf); } } } } } // ---------------------------------------------------------------------------- // Description: // Tells if this window is the current OpenGL context for the calling thread. bool vtkWin32OpenGLRenderWindow::IsCurrent() { return this->ContextId != 0 && this->ContextId == wglGetCurrentContext(); } // ---------------------------------------------------------------------------- void AdjustWindowRectForBorders(HWND hwnd, DWORD style, const int x, const int y, const int width, const int height, RECT &r) { if (!style && hwnd) { style = GetWindowLong(hwnd, GWL_STYLE); } r.left = x; r.top = y; r.right = r.left + width; r.bottom = r.top + height; BOOL result = AdjustWindowRect(&r, style, FALSE); if (!result) { vtkGenericWarningMacro("AdjustWindowRect failed, error: " << GetLastError()); } } // ---------------------------------------------------------------------------- void vtkWin32OpenGLRenderWindow::SetSize(int x, int y) { static int resizing = 0; if ((this->Size[0] != x) || (this->Size[1] != y)) { this->Superclass::SetSize(x, y); if (this->Interactor) { this->Interactor->SetSize(x, y); } if (this->OffScreenRendering) { if (!this->CreatingOffScreenWindow) { if (!resizing) { resizing = 1; this->CleanUpOffScreenRendering(); this->CreateOffScreenWindow(x,y); resizing = 0; } } } else if (this->Mapped) { if (!resizing) { resizing = 1; if (this->ParentId) { SetWindowExtEx(this->DeviceContext, x, y, NULL); SetViewportExtEx(this->DeviceContext, x, y, NULL); SetWindowPos(this->WindowId, HWND_TOP, 0, 0, x, y, SWP_NOMOVE | SWP_NOZORDER); } else { RECT r; AdjustWindowRectForBorders(this->WindowId, 0, 0, 0, x, y, r); SetWindowPos(this->WindowId, HWND_TOP, 0, 0, r.right - r.left, r.bottom - r.top, SWP_NOMOVE | SWP_NOZORDER); } resizing = 0; } } } } void vtkWin32OpenGLRenderWindow::SetPosition(int x, int y) { static int resizing = 0; if ((this->Position[0] != x) || (this->Position[1] != y)) { this->Modified(); this->Position[0] = x; this->Position[1] = y; if (this->Mapped) { if (!resizing) { resizing = 1; SetWindowPos(this->WindowId, HWND_TOP, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); resizing = 0; } } } } // End the rendering process and display the image. void vtkWin32OpenGLRenderWindow::Frame(void) { this->MakeCurrent(); if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers) { // If this check is not enforced, we crash in offscreen rendering if (this->DeviceContext) { // use global scope to get Win32 API SwapBuffers and not be // confused with this->SwapBuffers ::SwapBuffers(this->DeviceContext); vtkDebugMacro(<< " SwapBuffers\n"); } } else { glFlush(); } } int vtkWin32OpenGLRenderWindow::SupportsOpenGL() { MakeCurrent(); if (!this->DeviceContext) { return 0; } int pixelFormat = GetPixelFormat(this->DeviceContext); PIXELFORMATDESCRIPTOR pfd; DescribePixelFormat(this->DeviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); return (pfd.dwFlags & PFD_SUPPORT_OPENGL) ? 1 : 0; } int vtkWin32OpenGLRenderWindow::IsDirect() { MakeCurrent(); if (!this->DeviceContext) { return 0; } int pixelFormat = GetPixelFormat(this->DeviceContext); PIXELFORMATDESCRIPTOR pfd; DescribePixelFormat(this->DeviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); return (pfd.dwFlags & PFD_GENERIC_FORMAT) ? 0 : 1; } const char* vtkWin32OpenGLRenderWindow::ReportCapabilities() { MakeCurrent(); if (!this->DeviceContext) { return "no device context"; } int pixelFormat = GetPixelFormat(this->DeviceContext); PIXELFORMATDESCRIPTOR pfd; DescribePixelFormat(this->DeviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); const char *glVendor = (const char*)glGetString(GL_VENDOR); const char *glRenderer = (const char*)glGetString(GL_RENDERER); const char *glVersion = (const char*)glGetString(GL_VERSION); const char *glExtensions = (const char*)glGetString(GL_EXTENSIONS); std::ostringstream strm; strm << "OpenGL vendor string: " << glVendor << endl; strm << "OpenGL renderer string: " << glRenderer << endl; strm << "OpenGL version string: " << glVersion << endl; strm << "OpenGL extensions: " << glExtensions << endl; strm << "PixelFormat Descriptor:" << endl; strm << "depth: " << static_cast(pfd.cDepthBits) << endl; if (pfd.cColorBits <= 8) { strm << "class: PseudoColor" << endl; } else { strm << "class: TrueColor" << endl; } strm << "buffer size: " << static_cast(pfd.cColorBits) << endl; strm << "level: " << static_cast(pfd.bReserved) << endl; if (pfd.iPixelType == PFD_TYPE_RGBA) { strm << "renderType: rgba" << endl; } else { strm <<"renderType: ci" << endl; } if (pfd.dwFlags & PFD_DOUBLEBUFFER) { strm << "double buffer: True" << endl; } else { strm << "double buffer: False" << endl; } if (pfd.dwFlags & PFD_STEREO) { strm << "stereo: True" << endl; } else { strm << "stereo: False" << endl; } if (pfd.dwFlags & PFD_GENERIC_FORMAT) { strm << "hardware acceleration: False" << endl; } else { strm << "hardware acceleration: True" << endl; } strm << "rgba: redSize=" << static_cast(pfd.cRedBits) << " greenSize=" << static_cast(pfd.cGreenBits) << "blueSize=" << static_cast(pfd.cBlueBits) << "alphaSize=" << static_cast(pfd.cAlphaBits) << endl; strm << "aux buffers: " << static_cast(pfd.cAuxBuffers)<< endl; strm << "depth size: " << static_cast(pfd.cDepthBits) << endl; strm << "stencil size: " << static_cast(pfd.cStencilBits) << endl; strm << "accum: redSize=" << static_cast(pfd.cAccumRedBits) << " greenSize=" << static_cast(pfd.cAccumGreenBits) << "blueSize=" << static_cast(pfd.cAccumBlueBits) << "alphaSize=" << static_cast(pfd.cAccumAlphaBits) << endl; delete[] this->Capabilities; size_t len = strm.str().length() + 1; this->Capabilities = new char[len]; strncpy(this->Capabilities, strm.str().c_str(), len); return this->Capabilities; } typedef bool (APIENTRY *wglChoosePixelFormatARBType)(HDC, const int*, const float*, unsigned int, int*, unsigned int*); bool WGLisExtensionSupported(const char *extension) { const size_t extlen = strlen(extension); const char *supported = NULL; // Try To Use wglGetExtensionStringARB On Current DC, If Possible PROC wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB"); if (wglGetExtString) { supported = ((char*(__stdcall*)(HDC))wglGetExtString)(wglGetCurrentDC()); } // If That Failed, Try Standard Opengl Extensions String if (supported == NULL) { supported = (char*)glGetString(GL_EXTENSIONS); } // If That Failed Too, Must Be No Extensions Supported if (supported == NULL) { return false; } // Begin Examination At Start Of String, Increment By 1 On False Match for (const char* p = supported; ; p++) { // Advance p Up To The Next Possible Match p = strstr(p, extension); if (p == NULL) { return false; // No Match } // Make Sure That Match Is At The Start Of The String Or That // The Previous Char Is A Space, Or Else We Could Accidentally // Match "wglFunkywglExtension" With "wglExtension" // Also, Make Sure That The Following Character Is Space Or NULL // Or Else "wglExtensionTwo" Might Match "wglExtension" if ((p==supported || p[-1]==' ') && (p[extlen]=='\0' || p[extlen]==' ')) { return true; // Match } } } void vtkWin32OpenGLRenderWindow::SetupPixelFormat(HDC hDC, DWORD dwFlags, int debug, int bpp, int zbpp) { // Create a dummy window, needed for calling wglGetProcAddress. #ifdef UNICODE HWND tempId = CreateWindow(L"vtkOpenGL", 0, 0, 0, 0, 1, 1, 0, 0, this->ApplicationInstance, 0); #else HWND tempId = CreateWindow("vtkOpenGL", 0, 0, 0, 0, 1, 1, 0, 0, this->ApplicationInstance, 0); #endif HDC tempDC = GetDC(tempId); PIXELFORMATDESCRIPTOR tempPfd; memset(&tempPfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); tempPfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); tempPfd.nVersion = 1; tempPfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; tempPfd.iPixelType = PFD_TYPE_RGBA; int tempPixelFormat = ChoosePixelFormat(tempDC, &tempPfd); SetPixelFormat(tempDC, tempPixelFormat, &tempPfd); HGLRC tempContext = wglCreateContext(tempDC); wglMakeCurrent(tempDC, tempContext); // First we try to use the newer wglChoosePixelFormatARB which enables // features like multisamples. int pixelFormat = 0; wglChoosePixelFormatARBType wglChoosePixelFormatARB = reinterpret_cast(wglGetProcAddress("wglChoosePixelFormatARB")); if ((dwFlags & PFD_DRAW_TO_WINDOW) && wglChoosePixelFormatARB) { int attrib[] = { vtkwgl::ACCELERATION_ARB, vtkwgl::FULL_ACCELERATION_ARB, vtkwgl::SUPPORT_OPENGL_ARB, TRUE, vtkwgl::DRAW_TO_WINDOW_ARB, TRUE, vtkwgl::DOUBLE_BUFFER_ARB, TRUE, vtkwgl::COLOR_BITS_ARB, bpp/4*3, vtkwgl::DEPTH_BITS_ARB, zbpp/4*3, vtkwgl::PIXEL_TYPE_ARB, vtkwgl::TYPE_RGBA_ARB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; unsigned int n = 14; if (this->AlphaBitPlanes) { attrib[n] = vtkwgl::ALPHA_BITS_ARB; attrib[n+1] = bpp/4; n += 2; } if (this->StencilCapable) { attrib[n] = vtkwgl::STENCIL_BITS_ARB; attrib[n+1] = 8; n += 2; } if (dwFlags & PFD_STEREO) { attrib[n] = vtkwgl::STEREO_ARB; attrib[n+1] = TRUE; n += 2; } unsigned int multiSampleAttributeIndex = 0; if (this->MultiSamples > 1 && WGLisExtensionSupported("WGL_ARB_multisample")) { attrib[n] = vtkwgl::SAMPLE_BUFFERS_ARB; attrib[n+1] = 1; attrib[n+2] = vtkwgl::SAMPLES_ARB; attrib[n+3] = this->MultiSamples; multiSampleAttributeIndex = n+3; n += 4; } unsigned int numFormats; if (!wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats)) { // If the requested number of multisamples does not work, try // scaling down the number of multisamples a few times. if (multiSampleAttributeIndex) { attrib[multiSampleAttributeIndex] /= 2; if (!wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats)) { attrib[multiSampleAttributeIndex] /= 2; wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats); } } } PIXELFORMATDESCRIPTOR pfd; DescribePixelFormat(hDC, pixelFormat, sizeof(pfd), &pfd); if (!SetPixelFormat(hDC, pixelFormat, &pfd)) { pixelFormat = 0; } } // Delete the dummy window wglMakeCurrent(tempDC, 0); wglDeleteContext(tempContext); ReleaseDC(tempId, tempDC); ::DestroyWindow(tempId); // windows api // If we got a valid pixel format in the process, we are done. // Otherwise, we use the old approach of using ChoosePixelFormat. if (pixelFormat) { return; } BYTE bpp_byte = static_cast(bpp); BYTE zbpp_byte = static_cast(zbpp); PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), /* size */ 1, /* version */ dwFlags , /* support double-buffering */ PFD_TYPE_RGBA, /* color type */ bpp_byte, /* preferred color depth */ 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ static_cast(this->AlphaBitPlanes ? bpp/4 : 0), /* no alpha buffer */ 0, /* alpha bits (ignored) */ 0, /* no accumulation buffer */ 0, 0, 0, 0, /* accum bits (ignored) */ zbpp_byte, /* depth buffer */ static_cast(this->StencilCapable), /* stencil buffer */ 0, /* no auxiliary buffers */ PFD_MAIN_PLANE, /* main layer */ 0, /* reserved */ 0, 0, 0, /* no layer, visible, damage masks */ }; // Only try to set pixel format if we do not currently have one int currentPixelFormat = GetPixelFormat(hDC); // if there is a current pixel format, then make sure it // supports OpenGL if (currentPixelFormat != 0) { DescribePixelFormat(hDC, currentPixelFormat, sizeof(pfd), &pfd); if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL)) { #ifdef UNICODE MessageBox(WindowFromDC(hDC), L"Invalid pixel format, no OpenGL support", L"Error", MB_ICONERROR | MB_OK); #else MessageBox(WindowFromDC(hDC), "Invalid pixel format, no OpenGL support", "Error", MB_ICONERROR | MB_OK); #endif if (this->HasObserver(vtkCommand::ExitEvent)) { this->InvokeEvent(vtkCommand::ExitEvent, NULL); return; } else { exit(1); } } } else { // hDC has no current PixelFormat, so pixelFormat = ChoosePixelFormat(hDC, &pfd); if (pixelFormat == 0) { #ifdef UNICODE MessageBox(WindowFromDC(hDC), L"ChoosePixelFormat failed.", L"Error", MB_ICONERROR | MB_OK); #else MessageBox(WindowFromDC(hDC), "ChoosePixelFormat failed.", "Error", MB_ICONERROR | MB_OK); #endif if (this->HasObserver(vtkCommand::ExitEvent)) { this->InvokeEvent(vtkCommand::ExitEvent, NULL); return; } else { exit(1); } } DescribePixelFormat(hDC, pixelFormat, sizeof(pfd), &pfd); if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) { // int err = GetLastError(); #ifdef UNICODE MessageBox(WindowFromDC(hDC), L"SetPixelFormat failed.", L"Error", MB_ICONERROR | MB_OK); #else MessageBox(WindowFromDC(hDC), "SetPixelFormat failed.", "Error", MB_ICONERROR | MB_OK); #endif if (this->HasObserver(vtkCommand::ExitEvent)) { this->InvokeEvent(vtkCommand::ExitEvent, NULL); return; } else { exit(1); } } } if (debug && (dwFlags & PFD_STEREO) && !(pfd.dwFlags & PFD_STEREO)) { vtkGenericWarningMacro("No Stereo Available!"); this->StereoCapableWindow = 0; } } void vtkWin32OpenGLRenderWindow::SetupPalette(HDC hDC) { int pixelFormat = GetPixelFormat(hDC); PIXELFORMATDESCRIPTOR pfd; DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); int paletteSize; if (pfd.dwFlags & PFD_NEED_PALETTE) { paletteSize = 1 << pfd.cColorBits; } else { return; } LOGPALETTE* pPal = (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY)); pPal->palVersion = 0x300; pPal->palNumEntries = paletteSize; // build a simple RGB color palette int redMask = (1 << pfd.cRedBits) - 1; int greenMask = (1 << pfd.cGreenBits) - 1; int blueMask = (1 << pfd.cBlueBits) - 1; for (int i = 0; i < paletteSize; ++i) { pPal->palPalEntry[i].peRed = (((i >> pfd.cRedShift) & redMask) * 255) / redMask; pPal->palPalEntry[i].peGreen = (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask; pPal->palPalEntry[i].peBlue = (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask; pPal->palPalEntry[i].peFlags = 0; } this->Palette = CreatePalette(pPal); free(pPal); if (this->Palette) { this->OldPalette = SelectPalette(hDC, this->Palette, FALSE); RealizePalette(hDC); } } LRESULT vtkWin32OpenGLRenderWindow::MessageProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: { // nothing to be done here, opengl is initialized after the call to // create now return 0; } case WM_DESTROY: this->Clean(); if (this->DeviceContext) { ReleaseDC(this->WindowId, this->DeviceContext); this->DeviceContext = NULL; this->WindowId = NULL; } return 0; case WM_SIZE: // track window size changes if (this->ContextId) { this->SetSize((int)LOWORD(lParam),(int)HIWORD(lParam)); return 0; } case WM_PALETTECHANGED: // realize palette if this is *not* the current window if (this->ContextId && this->Palette && (HWND) wParam != hWnd) { SelectPalette(this->DeviceContext, this->OldPalette, FALSE); UnrealizeObject(this->Palette); this->OldPalette = SelectPalette(this->DeviceContext, this->Palette, FALSE); RealizePalette(this->DeviceContext); this->Render(); } break; case WM_QUERYNEWPALETTE: // realize palette if this is the current window if (this->ContextId && this->Palette) { SelectPalette(this->DeviceContext, this->OldPalette, FALSE); UnrealizeObject(this->Palette); this->OldPalette = SelectPalette(this->DeviceContext, this->Palette, FALSE); RealizePalette(this->DeviceContext); this->Render(); return TRUE; } break; case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hWnd, &ps); if (this->ContextId) { this->Render(); } EndPaint(hWnd, &ps); return 0; } break; case WM_ERASEBKGND: return TRUE; case WM_SETCURSOR: if (HTCLIENT == LOWORD(lParam)) { this->SetCurrentCursor(this->GetCurrentCursor()); return TRUE; } break; default: this->InvokeEvent(vtkCommand::RenderWindowMessageEvent, &message); break; } return DefWindowProc(hWnd, message, wParam, lParam); } void vtkWin32OpenGLRenderWindow::InitializeApplication() { // get the application instance if we don't have one already if (!this->ApplicationInstance) { // if we have a parent window get the app instance from it if (this->ParentId) { this->ApplicationInstance = (HINSTANCE)vtkGetWindowLong(this->ParentId, vtkGWL_HINSTANCE); } else { this->ApplicationInstance = GetModuleHandle(NULL); } } } void vtkWin32OpenGLRenderWindow::CreateAWindow() { WNDCLASS wndClass; // has the class been registered ? #ifdef UNICODE if (!GetClassInfo(this->ApplicationInstance, L"vtkOpenGL", &wndClass)) #else if (!GetClassInfo(this->ApplicationInstance, "vtkOpenGL", &wndClass)) #endif { wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; wndClass.lpfnWndProc = vtkWin32OpenGLRenderWindow::WndProc; wndClass.cbClsExtra = 0; wndClass.hInstance = this->ApplicationInstance; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wndClass.lpszMenuName = NULL; #ifdef UNICODE wndClass.lpszClassName = L"vtkOpenGL"; #else wndClass.lpszClassName = "vtkOpenGL"; #endif // vtk doesn't use the first extra vtkLONG's worth of bytes, // but app writers may want them, so we provide them. VTK // does use the second vtkLONG's worth of bytes of extra space. wndClass.cbWndExtra = 2 * sizeof(vtkLONG); RegisterClass(&wndClass); } if (this->WindowIdReferenceCount == 0) { if (!this->WindowId) { this->DeviceContext = 0; // Check if the user has changed the window name // ("Visualization toolkit - OpenGL" is vtkOpenGLRenderWindow's default) if (!strcmp(this->GetWindowName(), "Visualization Toolkit - OpenGL")) { static int count = 1; std::stringstream windowName; windowName << "Visualization Toolkit - Win32OpenGL #" << count++; this->SetWindowName(windowName.str().c_str()); } #ifdef UNICODE wchar_t *wname = new wchar_t [mbstowcs(NULL, this->WindowName, 32000)+1]; mbstowcs(wname, this->WindowName, 32000); #endif int x = ((this->Position[0] >= 0) ? this->Position[0] : 5); int y = ((this->Position[1] >= 0) ? this->Position[1] : 5); int height = ((this->Size[1] > 0) ? this->Size[1] : 300); int width = ((this->Size[0] > 0) ? this->Size[0] : 300); /* create window */ if (this->ParentId) { #ifdef UNICODE this->WindowId = CreateWindow( L"vtkOpenGL", wname, WS_CHILD | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/, x, y, width, height, this->ParentId, NULL, this->ApplicationInstance, NULL); #else this->WindowId = CreateWindow( "vtkOpenGL", this->WindowName, WS_CHILD | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/, x, y, width, height, this->ParentId, NULL, this->ApplicationInstance, NULL); #endif } else { DWORD style = WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/; if (this->Borders) { style |= WS_OVERLAPPEDWINDOW; } else { style |= WS_POPUP; } RECT r; AdjustWindowRectForBorders(0, style, x, y, width, height, r); #ifdef UNICODE this->WindowId = CreateWindow( L"vtkOpenGL", wname, style, x, y, r.right-r.left, r.bottom-r.top, NULL, NULL, this->ApplicationInstance, NULL); #else this->WindowId = CreateWindow( "vtkOpenGL", this->WindowName, style, x, y, r.right-r.left, r.bottom-r.top, NULL, NULL, this->ApplicationInstance, NULL); #endif } #ifdef UNICODE delete [] wname; #endif if (!this->WindowId) { vtkErrorMacro("Could not create window, error: " << GetLastError()); return; } // extract the create info // display window if (!this->OffScreenRendering) { ShowWindow(this->WindowId, SW_SHOW); } //UpdateWindow(this->WindowId); this->OwnWindow = 1; vtkSetWindowLong(this->WindowId, sizeof(vtkLONG), (intptr_t)this); } if (!this->DeviceContext) { this->DeviceContext = GetDC(this->WindowId); } DWORD flags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; if (this->StereoCapableWindow) { flags |= PFD_STEREO; } this->SetupPixelFormat(this->DeviceContext, flags, this->GetDebug(), 32, 32); this->SetupPalette(this->DeviceContext); this->ContextId = wglCreateContext(this->DeviceContext); if (this->ContextId == NULL) { vtkErrorMacro("wglCreateContext failed in CreateAWindow(), error: " << GetLastError()); } this->MakeCurrent(); // wipe out any existing display lists vtkRenderer* ren; vtkCollectionSimpleIterator rsit; for (this->Renderers->InitTraversal(rsit); (ren = this->Renderers->GetNextRenderer(rsit));) { ren->SetRenderWindow(0); ren->SetRenderWindow(this); } this->OpenGLInit(); this->Mapped = 1; this->WindowIdReferenceCount = 1; } else { ++this->WindowIdReferenceCount; } } // Initialize the window for rendering. void vtkWin32OpenGLRenderWindow::WindowInitialize() { // create our own window if not already set this->OwnWindow = 0; if (!this->MFChandledWindow) { this->InitializeApplication(); this->CreateAWindow(); } else { this->MakeCurrent(); this->OpenGLInit(); } } // Initialize the rendering window. void vtkWin32OpenGLRenderWindow::Initialize (void) { // make sure we haven't already been initialized if (!this->OffScreenRendering && !this->ContextId) { this->WindowInitialize(); } else { if (this->OffScreenRendering && !(this->ContextId || this->OffScreenUseFrameBuffer)) { this->InitializeApplication(); int width = ((this->Size[0] > 0) ? this->Size[0] : 300); int height = ((this->Size[1] > 0) ? this->Size[1] : 300); this->CreateOffScreenWindow(width,height); } } } void vtkWin32OpenGLRenderWindow::Finalize(void) { if (this->CursorHidden) { this->ShowCursor(); } if (this->OffScreenRendering) { this->CleanUpOffScreenRendering(); } this->DestroyWindow(); } void vtkWin32OpenGLRenderWindow::DestroyWindow() { if (this->WindowIdReferenceCount > 0) { --this->WindowIdReferenceCount; if (this->WindowIdReferenceCount == 0) { this->Clean(); if (this->WindowId) { ReleaseDC(this->WindowId, this->DeviceContext); // can't set WindowId=NULL, needed for DestroyWindow this->DeviceContext = NULL; // clear the extra data before calling destroy vtkSetWindowLong(this->WindowId, sizeof(vtkLONG), (vtkLONG)0); if (this->OwnWindow) { ::DestroyWindow(this->WindowId); // windows api this->WindowId = 0; } } } } } // Get the current size of the window. int *vtkWin32OpenGLRenderWindow::GetSize(void) { // if we aren't mapped then just return the ivar if (this->Mapped) { RECT rect; // Find the current window size if (GetClientRect(this->WindowId, &rect)) { this->Size[0] = rect.right; this->Size[1] = rect.bottom; } else { this->Size[0] = 0; this->Size[1] = 0; } } return this->vtkOpenGLRenderWindow::GetSize(); } // Get the size of the whole screen. int *vtkWin32OpenGLRenderWindow::GetScreenSize(void) { if (this->OffScreenRendering) { return this->Size; } HDC hDC = ::GetDC(NULL); if (hDC) { // This technique yields the screen size of the primary monitor // only in a multi-monitor configuration... this->Size[0] = ::GetDeviceCaps(hDC, HORZRES); this->Size[1] = ::GetDeviceCaps(hDC, VERTRES); ::ReleaseDC(NULL, hDC); } else { // This technique gets the "work area" (the whole screen except // for the bit covered by the Windows task bar) -- use it as a // fallback if there's an error calling GetDC. RECT rect; SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); this->Size[0] = rect.right - rect.left; this->Size[1] = rect.bottom - rect.top; } return this->Size; } // Get the position in screen coordinates of the window. int *vtkWin32OpenGLRenderWindow::GetPosition(void) { return this->Position; } // Change the window to fill the entire screen. void vtkWin32OpenGLRenderWindow::SetFullScreen(int arg) { if (this->FullScreen == arg) { return; } if (!this->Mapped) { this->PrefFullScreen(); return; } // set the mode this->FullScreen = arg; if (this->FullScreen <= 0) { this->Position[0] = this->OldScreen[0]; this->Position[1] = this->OldScreen[1]; this->Size[0] = this->OldScreen[2]; this->Size[1] = this->OldScreen[3]; this->Borders = this->OldScreen[4]; } else { // if window already up get its values if (this->WindowId) { int *temp = this->GetPosition(); this->OldScreen[0] = temp[0]; this->OldScreen[1] = temp[1]; this->OldScreen[4] = this->Borders; this->PrefFullScreen(); } } // remap the window this->WindowRemap(); this->Modified(); } // // Set the variable that indicates that we want a stereo capable window // be created. This method can only be called before a window is realized. void vtkWin32OpenGLRenderWindow::SetStereoCapableWindow(int capable) { if (this->ContextId == 0) { vtkRenderWindow::SetStereoCapableWindow(capable); } else { vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed " << "before the window is realized, i.e. before a render."); } } // Set the preferred window size to full screen. void vtkWin32OpenGLRenderWindow::PrefFullScreen() { int *size = this->GetScreenSize(); // don't show borders this->Borders = 0; RECT r; AdjustWindowRectForBorders(this->WindowId, 0, 0, 0, size[0], size[1], r); // use full screen this->Position[0] = 0; this->Position[1] = 0; this->Size[0] = r.right - r.left; this->Size[1] = r.bottom - r.top; } // Remap the window. void vtkWin32OpenGLRenderWindow::WindowRemap() { // close everything down this->Finalize(); // set the default windowid this->WindowId = this->NextWindowId; this->NextWindowId = 0; // and set it up! this->Initialize(); } void vtkWin32OpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "ContextId: " << this->ContextId << "\n"; os << indent << "Next Window Id: " << this->NextWindowId << "\n"; os << indent << "Window Id: " << this->WindowId << "\n"; } // Get the window id. HWND vtkWin32OpenGLRenderWindow::GetWindowId() { vtkDebugMacro(<< "Returning WindowId of " << this->WindowId << "\n"); return this->WindowId; } // Set the window id to a pre-existing window. void vtkWin32OpenGLRenderWindow::SetWindowId(HWND arg) { vtkDebugMacro(<< "Setting WindowId to " << arg << "\n"); if (arg != this->WindowId) { this->WindowId = arg; if (this->ContextId) { wglDeleteContext(this->ContextId); } this->ContextId = 0; this->DeviceContext = 0; } } // Set this RenderWindow's X window id to a pre-existing window. void vtkWin32OpenGLRenderWindow::SetWindowInfo(char *info) { size_t tmp; sscanf(info, vtkTypeTraits::ParseFormat(), &tmp); this->WindowId = reinterpret_cast(tmp); vtkDebugMacro(<< "Setting WindowId to " << this->WindowId << "\n"); } void vtkWin32OpenGLRenderWindow::SetNextWindowInfo(char *info) { size_t tmp; sscanf(info, vtkTypeTraits::ParseFormat(), &tmp); this->SetNextWindowId(reinterpret_cast(tmp)); } void vtkWin32OpenGLRenderWindow::SetDisplayId(void * arg) { this->DeviceContext = (HDC)arg; } void vtkWin32OpenGLRenderWindow::SetContextId(HGLRC arg) { this->ContextId = arg; } void vtkWin32OpenGLRenderWindow::SetDeviceContext(HDC arg) { this->DeviceContext = arg; this->MFChandledWindow = TRUE; } // Sets the HWND id of the window that WILL BE created. void vtkWin32OpenGLRenderWindow::SetParentInfo(char *info) { size_t tmp; sscanf(info, vtkTypeTraits::ParseFormat(), &tmp); this->ParentId = reinterpret_cast(tmp); vtkDebugMacro(<< "Setting ParentId to " << this->ParentId << "\n"); } // Set the window id to a pre-existing window. void vtkWin32OpenGLRenderWindow::SetParentId(HWND arg) { vtkDebugMacro(<< "Setting ParentId to " << arg << "\n"); this->ParentId = arg; } // Set the window id of the new window once a WindowRemap is done. void vtkWin32OpenGLRenderWindow::SetNextWindowId(HWND arg) { vtkDebugMacro(<< "Setting NextWindowId to " << arg << "\n"); this->NextWindowId = arg; } void vtkWin32OpenGLRenderWindow::SetNextWindowId(void *arg) { this->SetNextWindowId((HWND)arg); } // Begin the rendering process. void vtkWin32OpenGLRenderWindow::Start(void) { // if the renderer has not been initialized, do so now if (!this->ContextId) { this->Initialize(); } // set the current window this->MakeCurrent(); } void vtkWin32OpenGLRenderWindow::SetOffScreenRendering(int offscreen) { if (offscreen == this->OffScreenRendering) { return; } this->vtkRenderWindow::SetOffScreenRendering(offscreen); if (offscreen) { int size[2]; size[0] = (this->Size[0] > 0) ? this->Size[0] : 300; size[1] = (this->Size[1] > 0) ? this->Size[1] : 300; this->SaveScreenRendering(); this->CreateOffScreenWindow(size[0], size[1]); } else { this->CleanUpOffScreenRendering(); if (!this->WindowId) { this->WindowInitialize(); this->OpenGLInit(); if (this->Interactor) { this->Interactor->ReInitialize(); } this->DoubleBuffer = 1; } else { this->ResumeScreenRendering(); } } } void vtkWin32OpenGLRenderWindow::SaveScreenRendering() { this->ScreenMapped = this->Mapped; this->ScreenWindowSize[0] = this->Size[0]; this->ScreenWindowSize[1] = this->Size[1]; this->ScreenDeviceContext = this->DeviceContext; this->ScreenDoubleBuffer = this->DoubleBuffer; this->ScreenContextId = this->ContextId; } void vtkWin32OpenGLRenderWindow::CreateOffScreenWindow(int width, int height) { int status = this->CreatingOffScreenWindow; this->CreatingOffScreenWindow = 1; if (!this->CreateHardwareOffScreenWindow(width, height)) { #ifdef UNICODE HDC dc = CreateDC(L"DISPLAY", 0, 0, 0); #else HDC dc = CreateDC("DISPLAY", 0, 0, 0); #endif this->CreateOffScreenDC(width, height, dc); DeleteDC(dc); } else { this->Mapped = 0; } this->CreatingOffScreenWindow = status; } void vtkWin32OpenGLRenderWindow::CreateOffScreenDC(int xsize, int ysize, HDC aHdc) { int dataWidth = ((xsize * 3 + 3) / 4) * 4; this->MemoryDataHeader.bmiHeader.biSize = 40; this->MemoryDataHeader.bmiHeader.biWidth = xsize; this->MemoryDataHeader.bmiHeader.biHeight = ysize; this->MemoryDataHeader.bmiHeader.biPlanes = 1; this->MemoryDataHeader.bmiHeader.biBitCount = 24; this->MemoryDataHeader.bmiHeader.biCompression = BI_RGB; this->MemoryDataHeader.bmiHeader.biClrUsed = 0; this->MemoryDataHeader.bmiHeader.biClrImportant = 0; this->MemoryDataHeader.bmiHeader.biSizeImage = dataWidth * ysize; this->MemoryDataHeader.bmiHeader.biXPelsPerMeter = 10000; this->MemoryDataHeader.bmiHeader.biYPelsPerMeter = 10000; HBITMAP dib = CreateDIBSection(aHdc, &this->MemoryDataHeader, DIB_RGB_COLORS, (void **)(&(this->MemoryData)), NULL, 0); SIZE oldSize; SetBitmapDimensionEx(dib, xsize, ysize, &oldSize); // try using a DIBsection this->CreateOffScreenDC(dib, aHdc); } void vtkWin32OpenGLRenderWindow::CreateOffScreenDC(HBITMAP hbmp, HDC aHdc) { BITMAP bm; GetObject(hbmp, sizeof(BITMAP), &bm); // Renderers will need to redraw anything cached in display lists this->CleanUpRenderers(); this->MemoryBuffer = hbmp; // Create a compatible device context this->MemoryHdc = (HDC)CreateCompatibleDC(aHdc); // Put the bitmap into the device context SelectObject(this->MemoryHdc, this->MemoryBuffer); // adjust settings for renderwindow this->Mapped = 0; this->Size[0] = bm.bmWidth; this->Size[1] = bm.bmHeight; this->DeviceContext = this->MemoryHdc; this->DoubleBuffer = 0; this->SetupPixelFormat(this->DeviceContext, PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI | PFD_DRAW_TO_BITMAP, this->GetDebug(), 24, 32); this->SetupPalette(this->DeviceContext); this->ContextId = wglCreateContext(this->DeviceContext); if (this->ContextId == NULL) { vtkErrorMacro("wglCreateContext failed in CreateOffScreenDC(), error: " << GetLastError()); } this->MakeCurrent(); this->OpenGLInit(); } void vtkWin32OpenGLRenderWindow::SetupMemoryRendering(int xsize, int ysize, HDC aHdc) { // save the current state this->ScreenMapped = this->Mapped; this->ScreenWindowSize[0] = this->Size[0]; this->ScreenWindowSize[1] = this->Size[1]; this->ScreenDeviceContext = this->DeviceContext; this->ScreenDoubleBuffer = this->DoubleBuffer; this->ScreenContextId = this->ContextId; this->CreateOffScreenDC(xsize, ysize, aHdc); } void vtkWin32OpenGLRenderWindow::SetupMemoryRendering(HBITMAP hbmp) { #ifdef UNICODE HDC dc = CreateDC(L"DISPLAY", 0, 0, 0); #else HDC dc = CreateDC("DISPLAY", 0, 0, 0); #endif // save the current state this->ScreenMapped = this->Mapped; this->ScreenWindowSize[0] = this->Size[0]; this->ScreenWindowSize[1] = this->Size[1]; this->ScreenDeviceContext = this->DeviceContext; this->ScreenDoubleBuffer = this->DoubleBuffer; this->ScreenContextId = this->ContextId; this->CreateOffScreenDC(hbmp, dc); DeleteDC(dc); } HDC vtkWin32OpenGLRenderWindow::GetMemoryDC() { return this->MemoryHdc; } void vtkWin32OpenGLRenderWindow::CleanUpOffScreenRendering(void) { if (this->OffScreenUseFrameBuffer) { this->DestroyHardwareOffScreenWindow(); } else { if (!this->MemoryHdc) { return; } GdiFlush(); // we need to release resources this->CleanUpRenderers(); DeleteDC(this->MemoryHdc); this->MemoryHdc = (HDC)0; DeleteObject(this->MemoryBuffer); if (wglDeleteContext(this->ContextId) != TRUE) { vtkErrorMacro("wglDeleteContext failed in CleanUpOffScreenRendering(), error: " << GetLastError()); } this->ContextId = 0; } } void vtkWin32OpenGLRenderWindow::ResumeScreenRendering(void) { // release OpenGL graphics resources before switch back to on-screen. if (this->ContextId!=0) { this->MakeCurrent(); this->CleanUpRenderers(); } if (this->MemoryBuffer) { DeleteObject(this->MemoryBuffer); this->MemoryBuffer = 0; } if (this->MemoryHdc) { DeleteDC(this->MemoryHdc); this->MemoryHdc = 0; } if (this->ContextId && wglDeleteContext(this->ContextId) != TRUE) { vtkErrorMacro("wglDeleteContext failed in CleanUpOffScreenRendering(), error: " << GetLastError()); } this->Mapped = this->ScreenMapped; this->Size[0] = this->ScreenWindowSize[0]; this->Size[1] = this->ScreenWindowSize[1]; this->DeviceContext = this->ScreenDeviceContext; this->DoubleBuffer = this->ScreenDoubleBuffer; this->ContextId = this->ScreenContextId; this->MakeCurrent(); } //---------------------------------------------------------------------------- void vtkWin32OpenGLRenderWindow::HideCursor() { if (this->CursorHidden) { return; } this->CursorHidden = 1; ::ShowCursor(0); } //---------------------------------------------------------------------------- void vtkWin32OpenGLRenderWindow::ShowCursor() { if (!this->CursorHidden) { return; } this->CursorHidden = 0; ::ShowCursor(1); } //---------------------------------------------------------------------------- void vtkWin32OpenGLRenderWindow::SetCursorPosition(int x, int y) { int *size = this->GetSize(); POINT point; point.x = x; point.y = size[1] - y - 1; if (ClientToScreen(this->WindowId, &point)) { SetCursorPos(point.x, point.y); } } //---------------------------------------------------------------------------- void vtkWin32OpenGLRenderWindow::SetCurrentCursor(int shape) { if (this->InvokeEvent(vtkCommand::CursorChangedEvent, &shape)) { return; } this->Superclass::SetCurrentCursor(shape); LPCTSTR cursorName = 0; switch (shape) { case VTK_CURSOR_DEFAULT: case VTK_CURSOR_ARROW: cursorName = IDC_ARROW; break; case VTK_CURSOR_SIZENE: case VTK_CURSOR_SIZESW: cursorName = IDC_SIZENESW; break; case VTK_CURSOR_SIZENW: case VTK_CURSOR_SIZESE: cursorName = IDC_SIZENWSE; break; case VTK_CURSOR_SIZENS: cursorName = IDC_SIZENS; break; case VTK_CURSOR_SIZEWE: cursorName = IDC_SIZEWE; break; case VTK_CURSOR_SIZEALL: cursorName = IDC_SIZEALL; break; case VTK_CURSOR_HAND: #if (WINVER >= 0x0500) cursorName = IDC_HAND; #else cursorName = IDC_ARROW; #endif break; case VTK_CURSOR_CROSSHAIR: cursorName = IDC_CROSS; break; } if (cursorName) { HANDLE cursor = LoadImage(0, cursorName, IMAGE_CURSOR, 0, 0, LR_SHARED | LR_DEFAULTSIZE); SetCursor((HCURSOR)cursor); } } //---------------------------------------------------------------------------- bool vtkWin32OpenGLRenderWindow::DetectDPI() { this->SetDPI(GetDeviceCaps(this->DeviceContext, LOGPIXELSY)); return true; }