vtk中的win32窗口

        在用VS ide新建win32工程的选项中,一个叫“Win32控制台应用程序”,另一个叫“Win32应用程序”,其区别的细节这里跳过不讲,最显著的就是win32控制台没有GUI窗口,只弹出一个命令行黑框;而win32应用程序有GUI窗口,但没黑框。

        但是!如以下demo,vtk example中统统都有命令行黑窗口,又有GUI显示窗口。都是win32控制台工程,它的GUI显示窗口是从哪儿来的呢?

vtk中的win32窗口_第1张图片

int main(int , char *[])
{
    //↓↓↓↓↓↓↓↓↓↓
    double p0[3] = {0.0, 0.0, 0.0};
    double p1[3] = {1.0, 0.0, 0.0};
    double p2[3] = {1.0, 1.0, 0.0};
    double p3[3] = {0.0, 1.0, 0.0};

    // Add the points to a vtkPoints object
    vtkPoints *points =  vtkPoints::New();
    ... ... ... ...
    //↑↑↑↑↑以上都是数据结构,未见OPENGL相关绘制内容↑↑↑↑

    // Setup actor and mapper 
    // 反射机制 在win32下自动反射到vtkOpenGLPolyDataMapper,这里有传统的OPENGL代码
    vtkPolyDataMapper*mapper =     vtkPolyDataMapper::New();
    mapper->SetInput(polydata);

    vtkActor*actor =       vtkActor::New();
    actor->SetMapper(mapper);

    // Setup render window, renderer, and interactor
    vtkRenderer*renderer =
        vtkRenderer::New();
    vtkRenderWindow*renderWindow =
        vtkRenderWindow::New();
    renderWindow->SetWindowName("Quad");
    renderWindow->AddRenderer(renderer);
    vtkRenderWindowInteractor*renderWindowInteractor = 
        vtkRenderWindowInteractor::New();
    renderWindowInteractor->SetRenderWindow(renderWindow);

    renderer->AddActor(actor);
    renderWindow->Render();
    renderWindowInteractor->Start();

    return EXIT_SUCCESS;
}

        最初,我一直觉得理所当然,因为VTK的底层是OpenGL嘛,当然是OpenGL的窗口啦,那丑不拉几的样子,一看就是OpenGL的窗口,网上所有的OpenGL教程都长这个样子。随着慢慢对OpenGL的了解,发现我又一次被表象蒙蔽了,事实并不是看到的这样,只是长的像而已。。。凡是用到OpenGL显示的程序,都会绑定另外一个包含UI的框架,类似GLUT,Qt,MFC,FLTK,OpenGL自己是不能显示出来的!!!必须绑定一个UI!!!必须绑定一个UI!!!必须绑定一个UI!!!NND,鄙人愚笨,被忽悠这么多年,一直以为OpenGL自己就能绘制窗口。

        OpenGL只负责绘制场景,并不会负责窗口,窗口是另外一个框架的。想要在桌面上看到OpenGL场景,就必须与一个绘制UI的框架绑定!

        下面看看vtk example为什么能在Win32控制台应用程序下弹出窗口+命令行:

     找到类vtkWin32OpenGLRenderWindow,根据名字就可以知道这个类的功能:vtk + Win32 + OpenGL + RenderWindow,可以理解为vtk在win32下将OpenGL与RenderWindow绑定!

// Initialize the window for rendering.
void vtkWin32OpenGLRenderWindow::WindowInitialize (void)
{
  int x, y, width, height;
  GLenum type;
  static int count = 1;
  char *windowName;
  
  x = ((this->Position[0] >= 0) ? this->Position[0] : 5);
  y = ((this->Position[1] >= 0) ? this->Position[1] : 5);
  width = ((this->Size[0] > 0) ? this->Size[0] : 300);
  height = ((this->Size[1] > 0) ? this->Size[1] : 300);

  // create our own window if not already set
    if (!this->WindowId)
      {
      WNDCLASS wndClass;
      
      int len = strlen( "Visualization Toolkit - Win32OpenGL #") 
	+ (int)ceil( (double) log10( (double)(count+1) ) )
	+ 1; 
      windowName = new char [ len ];
      sprintf(windowName,"Visualization Toolkit - Win32OpenGL #%i",count++);
      this->SetWindowName(windowName);
      delete [] windowName;
      
      // has the class been registered ?
      if (!GetClassInfo(this->ApplicationInstance,"vtkOpenGL",&wndClass))
        {
        wndClass.style = CS_HREDRAW | CS_VREDRAW;
        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;
        wndClass.lpszClassName = "vtkOpenGL";
        // vtk doesn't use these extra 4 bytes, but app writers
        // may want them, so we provide them.
        wndClass.cbWndExtra = 4;
        RegisterClass(&wndClass);
        }
      
      // use real mutex
      vtkWin32OpenGLRenderWindow::WindowMutex->Lock();
      if (vtkWin32OpenGLRenderWindow::TempPointerToThis)
        {
        vtkErrorMacro("Two windows being created at the same time");
        }
      vtkWin32OpenGLRenderWindow::TempPointerToThis = this;
      /* create window */
      if (this->ParentId)
        {
        this->WindowId = CreateWindow(
          "vtkOpenGL", this->WindowName,
          WS_CHILD | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/,
          x, y, width, height,
          this->ParentId, NULL, this->ApplicationInstance, NULL);
        }
      else
        {
        this->WindowId = CreateWindow(
	  "vtkOpenGL", this->WindowName,
	  WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/,
	  x,y, width+2*GetSystemMetrics(SM_CXFRAME),
	  height+2*GetSystemMetrics(SM_CYFRAME) +GetSystemMetrics(SM_CYCAPTION),
	  NULL, NULL, this->ApplicationInstance, NULL);
        }
      vtkWin32OpenGLRenderWindow::TempPointerToThis = NULL;
      vtkWin32OpenGLRenderWindow::WindowMutex->Unlock();
      if (!this->WindowId)
        {
        vtkErrorMacro("Could not create window, error:  " << GetLastError());
        return;
        }
      // extract the create info
      
      /* display window */
      ShowWindow(this->WindowId, SW_SHOW);
      //UpdateWindow(this->WindowId);
      this->OwnWindow = 1;
      }
    else
      {
      SetWindowLong(this->WindowId,GWL_USERDATA,(LONG)this);
      this->DeviceContext = GetDC(this->WindowId);
      if (this->StereoCapableWindow)
	{
	this->SetupPixelFormat(this->DeviceContext, PFD_SUPPORT_OPENGL |
			       PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER |
			       PFD_STEREO, this->GetDebug(), 32, 32);
	}
      else
	{
	this->SetupPixelFormat(this->DeviceContext, PFD_SUPPORT_OPENGL |
			       PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER,
			       this->GetDebug(), 32, 32);
	}
      this->SetupPalette(this->DeviceContext);
      this->ContextId = wglCreateContext(this->DeviceContext);
      wglMakeCurrent(this->DeviceContext, this->ContextId);
      this->OpenGLInit();
      }
    this->Mapped = 1;
    }	
  else 
    {
    wglMakeCurrent(this->DeviceContext, this->ContextId); // hsr
    this->OpenGLInit();
    }

  // set the DPI
  this->SetDPI(GetDeviceCaps(this->DeviceContext, LOGPIXELSY));
}

        上面这段代码就是创建win32窗口的方法,能清晰的看到 

1、WNDCLASSCreateWindow,SetupPixelFormat,

窗口win32应用窗口的接口函数,也是常见的标准方法。

2、wglCreateContext,wglMakeCurrent。

调用windows系统中的gl接口。

3、OpenGLInit初始化函数

void vtkWin32OpenGLRenderWindow::OpenGLInit()
{
  glMatrixMode( GL_MODELVIEW );
  glDepthFunc( GL_LEQUAL );
  glEnable( GL_DEPTH_TEST );
  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
.......
}

        解释到这里,应该算比较清楚了,vtk在“Win32控制台应用程序”中,调用win32应用程序窗口窗口的接口,自己画了一个UI,然后把OpenGL绑上去。

vtk中的win32窗口_第2张图片

貌似有一段时间没写blog了~

看破游戏规则,回归核心价值。

“如果给我1个小时解答一道决定我生死的问题,我会花55分钟来弄清楚这道题到底是在问什么。”

                                                                                                                                    ---爱因斯坦?


你可能感兴趣的:(VTK源码解析)