スポンサーリンク

VTK9.3をMFCの上に張り付ける

ビルド

VTKをMFCのウィンドウに張り付ける。VTKのビルド時にMFCサポートを入れておく必要がある。

VTKのビルド時、VTK_MODULE_ENABLE_VTK_GUISupportMFCを設定しておく必要がある。

ビルド時 VTK_MODULE_ENABLE_VTK_GUISupportMFC を YES に設定

VTK_MODULE_ENABLE_VTK_GUISupportMFCをYESに設定。

この設定をすると、vtkMFCWindow.hなどが使用できるようになる。

文字セットをマルチバイト文字セットを使用する に設定

MFCを使用するプロジェクトの設定を「マルチバイト文字セットを使用する」に変更する。

経験上、プロジェクト設定がUnicodeだとデバッグモードでウィンドウを作成できない(例外発生)。

この設定をしないと特にデバッグモードでvtkMFCWindow内でCWnd::Createのあたりで落ちる。

vtkMFCWindow::vtkMFCWindow(CWnd* pcWnd)
{
  this->pvtkWin32OpenGLRW = nullptr;

  // create self as a child of passed in parent
  DWORD style = WS_VISIBLE | WS_CLIPSIBLINGS;
  if (pcWnd)
    style |= WS_CHILD;
  BOOL bCreated =
    CWnd::Create(nullptr, _T("VTK-MFC Window"), style, CRect(0, 0, 1, 1), pcWnd, (UINT)IDC_STATIC);

  SUCCEEDED(bCreated);

  // create a default vtk window
  vtkWin32OpenGLRenderWindow* win = vtkWin32OpenGLRenderWindow::New();
  this->SetRenderWindow(win);
  win->Delete();
}

サンプルコード

ChildView.h

#pragma once

///////////////////////////////
// VTKに必要
#include <vtkMFCWindow.h>               // vtkMFCWindowを使うために必要
#include <vtkWin32OpenGLRenderWindow.h> // vtkMFCWindowを使うために必要
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkConeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkCamera.h>

/*
* 以下をはじめとする、wgl系のリンクエラーが出たら、opengl32.libをリンクする
1>vtkRenderingOpenGL2-9.3.lib(vtkWin32OpenGLRenderWindow.obj) : error LNK2001: 外部シンボル __imp_wglCreateContext は未解決です
*/
#pragma comment(lib,"opengl32.lib")

/*
以下のエラーが出たら、Psapi.libをリンクする
vtksys-9.3.lib(SystemInformation.obj) : error LNK2001: 外部シンボル GetProcessMemoryInfo は未解決です
*/
#pragma comment(lib, "Psapi.lib")

/*
以下のエラーが出たら、Dbghelp.libをリンクする
vtksys-9.3.lib(SystemInformation.obj) : error LNK2001: 外部シンボル __imp_SymGetLineFromAddr64 は未解決です
vtksys-9.3.lib(SystemInformation.obj) : error LNK2001: 外部シンボル __imp_SymInitialize は未解決です
vtksys-9.3.lib(SystemInformation.obj) : error LNK2001: 外部シンボル __imp_SymFromAddr は未解決です
*/
#pragma comment(lib, "Dbghelp.lib")


class CChildView : public CWnd
{
  
  vtkMFCWindow* m_vtkMFCWindow;

  /* 略 */

protected:
  afx_msg void OnPaint();
  DECLARE_MESSAGE_MAP()
public:
  afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
  afx_msg void OnSize(UINT nType, int cx, int cy);
  afx_msg void OnDestroy();
};

ChildView.cpp

#include "pch.h"
#include "framework.h"
#include "MFCApplication4-with-vtk.h"
#include "ChildView.h"



// trackball 対応
#include <vtkInteractorStyleImage.h>
#include <vtkWin32RenderWindowInteractor.h> //win32api対応

// vtkWin32RenderWindowInteractor.h 内でincludeされている
//#include <vtkRenderWindowInteractor.h>

#include <cstdio>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CChildView

CChildView::CChildView()
{
  m_vtkMFCWindow = nullptr;

}

CChildView::~CChildView()
{
}


BEGIN_MESSAGE_MAP(CChildView, CWnd)
  ON_WM_PAINT()
  ON_WM_CREATE()
  ON_WM_SIZE()
  ON_WM_DESTROY()
END_MESSAGE_MAP()



// CChildView メッセージ ハンドラー

BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) 
{
  if (!CWnd::PreCreateWindow(cs))
    return FALSE;

  cs.dwExStyle |= WS_EX_CLIENTEDGE;
  cs.style &= ~WS_BORDER;
  cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, 
    ::LoadCursor(nullptr, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), nullptr);


  return TRUE;
}

void CChildView::OnPaint() 
{
  CPaintDC dc(this); // 描画のデバイス コンテキスト
  
  // 初回起動時のウィンドウサイズ指定
  static bool firsttime = true;
  if (m_vtkMFCWindow && firsttime) {
    firsttime = false;

    // ウィンドウの現在のサイズを取得
    CRect rect;
    GetClientRect(&rect);

    // VTKのウィンドウサイズを変更
    m_vtkMFCWindow->GetRenderWindow()->SetSize(rect.right, rect.bottom);

  }

  if (m_vtkMFCWindow) {

    m_vtkMFCWindow->DrawDC(&dc);// 描画
    // こちらでもいい。
    //m_vtkMFCWindow->GetRenderWindow()->Render();

  }
}


int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  if (CWnd::OnCreate(lpCreateStruct) == -1)
    return -1;
 
  // VTKのMFC用ウィンドウ作成
  m_vtkMFCWindow = new vtkMFCWindow(this);
  m_vtkMFCWindow->SetParent(this);

  // レンダラーの作成
  vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
  m_vtkMFCWindow->GetRenderWindow()->AddRenderer(renderer);

  // オブジェクトを作成・登録
  vtkSmartPointer<vtkConeSource> coneSource;
  coneSource = vtkSmartPointer<vtkConeSource>::New();
  vtkSmartPointer<vtkPolyDataMapper> mapper;
  mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  mapper->SetInputConnection(coneSource->GetOutputPort());
  vtkSmartPointer<vtkActor> actor;
  actor = vtkSmartPointer<vtkActor>::New();
  actor->SetMapper(mapper);
  renderer->AddActor(actor);


  vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  m_vtkMFCWindow->GetRenderWindow()->SetInteractor(interactor);

  auto iren = vtkSmartPointer<vtkWin32RenderWindowInteractor>::New();
  vtkSmartPointer<vtkInteractorStyleTrackballCamera> style =
    vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
  iren->SetInteractorStyle(style);
  iren->SetRenderWindow(m_vtkMFCWindow->GetRenderWindow());

return 0; } void CChildView::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy);
  // ウィンドウサイズの変更に合わせて
  // VTKの表示範囲を変更
  RECT rect;
  m_vtkMFCWindow->MoveWindow(0, 0, cx,cy);
}


void CChildView::OnDestroy()
{
  CWnd::OnDestroy();

  // これをしないとアプリケーション終了しようとしても
  // なぜか終了しないことがある
  PostQuitMessage(0);
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: