Showing posts with label MFC. Show all posts
Showing posts with label MFC. Show all posts

2020/08/07

MFC 대화장자에 VTK 올리기

이전 글(VTK 9.0.1 컴파일하기)에서 만들어진 VTK 빌드 결과물을 가지고 MFC 대화상자에 VTK를 올려보았다.


Test를 위한 대화상자 생성

Visual Studio 2019버전으로 테스트를 위한 대화상자 기반의 프로젝트 TestVTK를 만들었다. 2019버전으로는 처음 프로젝트를 먄들어보았는데 이전 버전과 프로젝트를 만드는 방법이 다소 달라졌고 프로젝트 구성이 달라졌다. VTK를 64비트만 빌드하여 테스트 프로젝트도 64비트 구성만 하였다.


VTK Property 파일 생성 및 구성 설정

Property Manager 에서 새로운 Property Sheet를 VTK_v9.0.1.props 파일로 만들었다.


VTK 경로를 하나의 설정으로 통일하여 관리하기 위해 VTK 빌드 결과물 경로를 User Macro에 VTK_DIR 이름으로 추가한다.


VTK_DIR 매크로를 이용하여 Include 및 Library 경로에 VTK 경로를 설정한다.

VC++ Directories > Include Directories: $(VTK_DIR)\include\vtk-9.0

VC++ Directories > Library Directories: $(VTK_DIR)\lib

VTK 사용을위한 기본 헤더 파일 작성

VTK 사용에 필요한 내용을 하나의 헤더파일로 작성을하여 관리하기위해 VTK_Prep.h 파일을 만들었다. 이 파일에는 VTK 초기화 코드와 VTK 사용에 필요한 헤더파일의 include와 빌드 속성에따른 lib 파일의 링크를 추가하였다. 라이브러리 파일은 모든 lib 파일을 추가하였고 Debug또는 Release에따라 로드되도록 하였다.

#pragma once

#include <vtkAutoInit.h>
#define vtkRenderingCore_AUTOINIT 3(vtkRenderingOpenGL2, vtkInteractionStyle, vtkRenderingFreeType)
#define vtkRenderingContext2D_AUTOINIT 1(vtkRenderingContextOpenGL2)
#define vtkRenderingVolume_AUTOINIT 1(vtkRenderingVolumeOpenGL)

#include <vtkRenderWindow.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>

#include <vtkConeSource.h>

#include <vtkCamera.h>
#include <vtkLight.h>

#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>

#ifdef _DEBUG
#pragma comment(lib, "vtkChartsCore-9.0d.lib")
#pragma comment(lib, "vtkCommonColor-9.0d.lib")
#pragma comment(lib, "vtkCommonComputationalGeometry-9.0d.lib")
#pragma comment(lib, "vtkCommonCore-9.0d.lib")
#pragma comment(lib, "vtkCommonDataModel-9.0d.lib")
#pragma comment(lib, "vtkCommonExecutionModel-9.0d.lib")
#pragma comment(lib, "vtkCommonMath-9.0d.lib")
#pragma comment(lib, "vtkCommonMisc-9.0d.lib")
#pragma comment(lib, "vtkCommonSystem-9.0d.lib")
#pragma comment(lib, "vtkCommonTransforms-9.0d.lib")
#pragma comment(lib, "vtkDICOMParser-9.0d.lib")
#pragma comment(lib, "vtkDomainsChemistry-9.0d.lib")
#pragma comment(lib, "vtkdoubleconversion-9.0d.lib")
#pragma comment(lib, "vtkexodusII-9.0d.lib")
#pragma comment(lib, "vtkexpat-9.0d.lib")
#pragma comment(lib, "vtkFiltersAMR-9.0d.lib")
#pragma comment(lib, "vtkFiltersCore-9.0d.lib")
#pragma comment(lib, "vtkFiltersExtraction-9.0d.lib")
#pragma comment(lib, "vtkFiltersFlowPaths-9.0d.lib")
#pragma comment(lib, "vtkFiltersGeneral-9.0d.lib")
#pragma comment(lib, "vtkFiltersGeneric-9.0d.lib")
#pragma comment(lib, "vtkFiltersGeometry-9.0d.lib")
#pragma comment(lib, "vtkFiltersHybrid-9.0d.lib")
#pragma comment(lib, "vtkFiltersHyperTree-9.0d.lib")
#pragma comment(lib, "vtkFiltersImaging-9.0d.lib")
#pragma comment(lib, "vtkFiltersModeling-9.0d.lib")
#pragma comment(lib, "vtkFiltersParallel-9.0d.lib")
#pragma comment(lib, "vtkFiltersParallelImaging-9.0d.lib")
#pragma comment(lib, "vtkFiltersPoints-9.0d.lib")
#pragma comment(lib, "vtkFiltersProgrammable-9.0d.lib")
#pragma comment(lib, "vtkFiltersSelection-9.0d.lib")
#pragma comment(lib, "vtkFiltersSMP-9.0d.lib")
#pragma comment(lib, "vtkFiltersSources-9.0d.lib")
#pragma comment(lib, "vtkFiltersStatistics-9.0d.lib")
#pragma comment(lib, "vtkFiltersTexture-9.0d.lib")
#pragma comment(lib, "vtkFiltersTopology-9.0d.lib")
#pragma comment(lib, "vtkFiltersVerdict-9.0d.lib")
#pragma comment(lib, "vtkfreetype-9.0d.lib")
#pragma comment(lib, "vtkGeovisCore-9.0d.lib")
#pragma comment(lib, "vtkgl2ps-9.0d.lib")
#pragma comment(lib, "vtkglew-9.0d.lib")
#pragma comment(lib, "vtkhdf5-9.0d.lib")
#pragma comment(lib, "vtkhdf5_hl-9.0d.lib")
#pragma comment(lib, "vtkImagingColor-9.0d.lib")
#pragma comment(lib, "vtkImagingCore-9.0d.lib")
#pragma comment(lib, "vtkImagingFourier-9.0d.lib")
#pragma comment(lib, "vtkImagingGeneral-9.0d.lib")
#pragma comment(lib, "vtkImagingHybrid-9.0d.lib")
#pragma comment(lib, "vtkImagingMath-9.0d.lib")
#pragma comment(lib, "vtkImagingMorphological-9.0d.lib")
#pragma comment(lib, "vtkImagingSources-9.0d.lib")
#pragma comment(lib, "vtkImagingStatistics-9.0d.lib")
#pragma comment(lib, "vtkImagingStencil-9.0d.lib")
#pragma comment(lib, "vtkInfovisCore-9.0d.lib")
#pragma comment(lib, "vtkInfovisLayout-9.0d.lib")
#pragma comment(lib, "vtkInteractionImage-9.0d.lib")
#pragma comment(lib, "vtkInteractionStyle-9.0d.lib")
#pragma comment(lib, "vtkInteractionWidgets-9.0d.lib")
#pragma comment(lib, "vtkIOAMR-9.0d.lib")
#pragma comment(lib, "vtkIOAsynchronous-9.0d.lib")
#pragma comment(lib, "vtkIOCityGML-9.0d.lib")
#pragma comment(lib, "vtkIOCore-9.0d.lib")
#pragma comment(lib, "vtkIOEnSight-9.0d.lib")
#pragma comment(lib, "vtkIOExodus-9.0d.lib")
#pragma comment(lib, "vtkIOExport-9.0d.lib")
#pragma comment(lib, "vtkIOExportGL2PS-9.0d.lib")
#pragma comment(lib, "vtkIOExportPDF-9.0d.lib")
#pragma comment(lib, "vtkIOGeometry-9.0d.lib")
#pragma comment(lib, "vtkIOImage-9.0d.lib")
#pragma comment(lib, "vtkIOImport-9.0d.lib")
#pragma comment(lib, "vtkIOInfovis-9.0d.lib")
#pragma comment(lib, "vtkIOLegacy-9.0d.lib")
#pragma comment(lib, "vtkIOLSDyna-9.0d.lib")
#pragma comment(lib, "vtkIOMINC-9.0d.lib")
#pragma comment(lib, "vtkIOMotionFX-9.0d.lib")
#pragma comment(lib, "vtkIOMovie-9.0d.lib")
#pragma comment(lib, "vtkIONetCDF-9.0d.lib")
#pragma comment(lib, "vtkIOOggTheora-9.0d.lib")
#pragma comment(lib, "vtkIOParallel-9.0d.lib")
#pragma comment(lib, "vtkIOParallelXML-9.0d.lib")
#pragma comment(lib, "vtkIOPLY-9.0d.lib")
#pragma comment(lib, "vtkIOSegY-9.0d.lib")
#pragma comment(lib, "vtkIOSQL-9.0d.lib")
#pragma comment(lib, "vtkIOTecplotTable-9.0d.lib")
#pragma comment(lib, "vtkIOVeraOut-9.0d.lib")
#pragma comment(lib, "vtkIOVideo-9.0d.lib")
#pragma comment(lib, "vtkIOXML-9.0d.lib")
#pragma comment(lib, "vtkIOXMLParser-9.0d.lib")
#pragma comment(lib, "vtkjpeg-9.0d.lib")
#pragma comment(lib, "vtkjsoncpp-9.0d.lib")
#pragma comment(lib, "vtklibharu-9.0d.lib")
#pragma comment(lib, "vtklibproj-9.0d.lib")
#pragma comment(lib, "vtklibxml2-9.0d.lib")
#pragma comment(lib, "vtkloguru-9.0d.lib")
#pragma comment(lib, "vtklz4-9.0d.lib")
#pragma comment(lib, "vtklzma-9.0d.lib")
#pragma comment(lib, "vtkmetaio-9.0d.lib")
#pragma comment(lib, "vtknetcdf-9.0d.lib")
#pragma comment(lib, "vtkogg-9.0d.lib")
#pragma comment(lib, "vtkParallelCore-9.0d.lib")
#pragma comment(lib, "vtkParallelDIY-9.0d.lib")
#pragma comment(lib, "vtkpng-9.0d.lib")
#pragma comment(lib, "vtkpugixml-9.0d.lib")
#pragma comment(lib, "vtkRenderingAnnotation-9.0d.lib")
#pragma comment(lib, "vtkRenderingContext2D-9.0d.lib")
#pragma comment(lib, "vtkRenderingCore-9.0d.lib")
#pragma comment(lib, "vtkRenderingFreeType-9.0d.lib")
#pragma comment(lib, "vtkRenderingGL2PSOpenGL2-9.0d.lib")
#pragma comment(lib, "vtkRenderingImage-9.0d.lib")
#pragma comment(lib, "vtkRenderingLabel-9.0d.lib")
#pragma comment(lib, "vtkRenderingLOD-9.0d.lib")
#pragma comment(lib, "vtkRenderingOpenGL2-9.0d.lib")
#pragma comment(lib, "vtkRenderingSceneGraph-9.0d.lib")
#pragma comment(lib, "vtkRenderingUI-9.0d.lib")
#pragma comment(lib, "vtkRenderingVolume-9.0d.lib")
#pragma comment(lib, "vtkRenderingVolumeOpenGL2-9.0d.lib")
#pragma comment(lib, "vtkRenderingVtkJS-9.0d.lib")
#pragma comment(lib, "vtksqlite-9.0d.lib")
#pragma comment(lib, "vtksys-9.0d.lib")
#pragma comment(lib, "vtkTestingRendering-9.0d.lib")
#pragma comment(lib, "vtktheora-9.0d.lib")
#pragma comment(lib, "vtktiff-9.0d.lib")
#pragma comment(lib, "vtkverdict-9.0d.lib")
#pragma comment(lib, "vtkViewsContext2D-9.0d.lib")
#pragma comment(lib, "vtkViewsCore-9.0d.lib")
#pragma comment(lib, "vtkViewsInfovis-9.0d.lib")
#pragma comment(lib, "vtkWrappingTools-9.0d.lib")
#pragma comment(lib, "vtkzlib-9.0d.lib")
#else
#pragma comment(lib, "vtkChartsCore-9.0.lib")
#pragma comment(lib, "vtkCommonColor-9.0.lib")
#pragma comment(lib, "vtkCommonComputationalGeometry-9.0.lib")
#pragma comment(lib, "vtkCommonCore-9.0.lib")
#pragma comment(lib, "vtkCommonDataModel-9.0.lib")
#pragma comment(lib, "vtkCommonExecutionModel-9.0.lib")
#pragma comment(lib, "vtkCommonMath-9.0.lib")
#pragma comment(lib, "vtkCommonMisc-9.0.lib")
#pragma comment(lib, "vtkCommonSystem-9.0.lib")
#pragma comment(lib, "vtkCommonTransforms-9.0.lib")
#pragma comment(lib, "vtkDICOMParser-9.0.lib")
#pragma comment(lib, "vtkDomainsChemistry-9.0.lib")
#pragma comment(lib, "vtkdoubleconversion-9.0.lib")
#pragma comment(lib, "vtkexodusII-9.0.lib")
#pragma comment(lib, "vtkexpat-9.0.lib")
#pragma comment(lib, "vtkFiltersAMR-9.0.lib")
#pragma comment(lib, "vtkFiltersCore-9.0.lib")
#pragma comment(lib, "vtkFiltersExtraction-9.0.lib")
#pragma comment(lib, "vtkFiltersFlowPaths-9.0.lib")
#pragma comment(lib, "vtkFiltersGeneral-9.0.lib")
#pragma comment(lib, "vtkFiltersGeneric-9.0.lib")
#pragma comment(lib, "vtkFiltersGeometry-9.0.lib")
#pragma comment(lib, "vtkFiltersHybrid-9.0.lib")
#pragma comment(lib, "vtkFiltersHyperTree-9.0.lib")
#pragma comment(lib, "vtkFiltersImaging-9.0.lib")
#pragma comment(lib, "vtkFiltersModeling-9.0.lib")
#pragma comment(lib, "vtkFiltersParallel-9.0.lib")
#pragma comment(lib, "vtkFiltersParallelImaging-9.0.lib")
#pragma comment(lib, "vtkFiltersPoints-9.0.lib")
#pragma comment(lib, "vtkFiltersProgrammable-9.0.lib")
#pragma comment(lib, "vtkFiltersSelection-9.0.lib")
#pragma comment(lib, "vtkFiltersSMP-9.0.lib")
#pragma comment(lib, "vtkFiltersSources-9.0.lib")
#pragma comment(lib, "vtkFiltersStatistics-9.0.lib")
#pragma comment(lib, "vtkFiltersTexture-9.0.lib")
#pragma comment(lib, "vtkFiltersTopology-9.0.lib")
#pragma comment(lib, "vtkFiltersVerdict-9.0.lib")
#pragma comment(lib, "vtkfreetype-9.0.lib")
#pragma comment(lib, "vtkGeovisCore-9.0.lib")
#pragma comment(lib, "vtkgl2ps-9.0.lib")
#pragma comment(lib, "vtkglew-9.0.lib")
#pragma comment(lib, "vtkhdf5-9.0.lib")
#pragma comment(lib, "vtkhdf5_hl-9.0.lib")
#pragma comment(lib, "vtkImagingColor-9.0.lib")
#pragma comment(lib, "vtkImagingCore-9.0.lib")
#pragma comment(lib, "vtkImagingFourier-9.0.lib")
#pragma comment(lib, "vtkImagingGeneral-9.0.lib")
#pragma comment(lib, "vtkImagingHybrid-9.0.lib")
#pragma comment(lib, "vtkImagingMath-9.0.lib")
#pragma comment(lib, "vtkImagingMorphological-9.0.lib")
#pragma comment(lib, "vtkImagingSources-9.0.lib")
#pragma comment(lib, "vtkImagingStatistics-9.0.lib")
#pragma comment(lib, "vtkImagingStencil-9.0.lib")
#pragma comment(lib, "vtkInfovisCore-9.0.lib")
#pragma comment(lib, "vtkInfovisLayout-9.0.lib")
#pragma comment(lib, "vtkInteractionImage-9.0.lib")
#pragma comment(lib, "vtkInteractionStyle-9.0.lib")
#pragma comment(lib, "vtkInteractionWidgets-9.0.lib")
#pragma comment(lib, "vtkIOAMR-9.0.lib")
#pragma comment(lib, "vtkIOAsynchronous-9.0.lib")
#pragma comment(lib, "vtkIOCityGML-9.0.lib")
#pragma comment(lib, "vtkIOCore-9.0.lib")
#pragma comment(lib, "vtkIOEnSight-9.0.lib")
#pragma comment(lib, "vtkIOExodus-9.0.lib")
#pragma comment(lib, "vtkIOExport-9.0.lib")
#pragma comment(lib, "vtkIOExportGL2PS-9.0.lib")
#pragma comment(lib, "vtkIOExportPDF-9.0.lib")
#pragma comment(lib, "vtkIOGeometry-9.0.lib")
#pragma comment(lib, "vtkIOImage-9.0.lib")
#pragma comment(lib, "vtkIOImport-9.0.lib")
#pragma comment(lib, "vtkIOInfovis-9.0.lib")
#pragma comment(lib, "vtkIOLegacy-9.0.lib")
#pragma comment(lib, "vtkIOLSDyna-9.0.lib")
#pragma comment(lib, "vtkIOMINC-9.0.lib")
#pragma comment(lib, "vtkIOMotionFX-9.0.lib")
#pragma comment(lib, "vtkIOMovie-9.0.lib")
#pragma comment(lib, "vtkIONetCDF-9.0.lib")
#pragma comment(lib, "vtkIOOggTheora-9.0.lib")
#pragma comment(lib, "vtkIOParallel-9.0.lib")
#pragma comment(lib, "vtkIOParallelXML-9.0.lib")
#pragma comment(lib, "vtkIOPLY-9.0.lib")
#pragma comment(lib, "vtkIOSegY-9.0.lib")
#pragma comment(lib, "vtkIOSQL-9.0.lib")
#pragma comment(lib, "vtkIOTecplotTable-9.0.lib")
#pragma comment(lib, "vtkIOVeraOut-9.0.lib")
#pragma comment(lib, "vtkIOVideo-9.0.lib")
#pragma comment(lib, "vtkIOXML-9.0.lib")
#pragma comment(lib, "vtkIOXMLParser-9.0.lib")
#pragma comment(lib, "vtkjpeg-9.0.lib")
#pragma comment(lib, "vtkjsoncpp-9.0.lib")
#pragma comment(lib, "vtklibharu-9.0.lib")
#pragma comment(lib, "vtklibproj-9.0.lib")
#pragma comment(lib, "vtklibxml2-9.0.lib")
#pragma comment(lib, "vtkloguru-9.0.lib")
#pragma comment(lib, "vtklz4-9.0.lib")
#pragma comment(lib, "vtklzma-9.0.lib")
#pragma comment(lib, "vtkmetaio-9.0.lib")
#pragma comment(lib, "vtknetcdf-9.0.lib")
#pragma comment(lib, "vtkogg-9.0.lib")
#pragma comment(lib, "vtkParallelCore-9.0.lib")
#pragma comment(lib, "vtkParallelDIY-9.0.lib")
#pragma comment(lib, "vtkpng-9.0.lib")
#pragma comment(lib, "vtkpugixml-9.0.lib")
#pragma comment(lib, "vtkRenderingAnnotation-9.0.lib")
#pragma comment(lib, "vtkRenderingContext2D-9.0.lib")
#pragma comment(lib, "vtkRenderingCore-9.0.lib")
#pragma comment(lib, "vtkRenderingFreeType-9.0.lib")
#pragma comment(lib, "vtkRenderingGL2PSOpenGL2-9.0.lib")
#pragma comment(lib, "vtkRenderingImage-9.0.lib")
#pragma comment(lib, "vtkRenderingLabel-9.0.lib")
#pragma comment(lib, "vtkRenderingLOD-9.0.lib")
#pragma comment(lib, "vtkRenderingOpenGL2-9.0.lib")
#pragma comment(lib, "vtkRenderingSceneGraph-9.0.lib")
#pragma comment(lib, "vtkRenderingUI-9.0.lib")
#pragma comment(lib, "vtkRenderingVolume-9.0.lib")
#pragma comment(lib, "vtkRenderingVolumeOpenGL2-9.0.lib")
#pragma comment(lib, "vtkRenderingVtkJS-9.0.lib")
#pragma comment(lib, "vtksqlite-9.0.lib")
#pragma comment(lib, "vtksys-9.0.lib")
#pragma comment(lib, "vtkTestingRendering-9.0.lib")
#pragma comment(lib, "vtktheora-9.0.lib")
#pragma comment(lib, "vtktiff-9.0.lib")
#pragma comment(lib, "vtkverdict-9.0.lib")
#pragma comment(lib, "vtkViewsContext2D-9.0.lib")
#pragma comment(lib, "vtkViewsCore-9.0.lib")
#pragma comment(lib, "vtkViewsInfovis-9.0.lib")
#pragma comment(lib, "vtkWrappingTools-9.0.lib")
#pragma comment(lib, "vtkzlib-9.0.lib")
#endif

이렇게 작성한 Property Sheet 파일은 경로가 수정될 경우 VTK_DIR 매크로만 수정을하면 되며 사용하는 Object가 추가될 경우 VTK_Prep.h 파일만 수정하면 되며 다른 프로젝트에 적용시 이 두 파일을 적용을 하면 된다.


프로젝트 코드 작성

리소스 뷰의 대화상자 리소스에 Picture Control을 올리고 이름을 IDC_STATIC_VTK_FRAME으로 설정하고 속성중 Type를 Owner Draw로 설정한다. 그리고 아래과 같이 코드를 추가하였

// Header 파일
public:
	vtkSmartPointer< vtkRenderWindow >		m_pVTKRenderWnd;
	void initVTKWindow(void* hWnd);
	void resizeVTKWindow();

// Source 파일
void CTestVTKDlg::initVTKWindow(void* hWnd)
{
	if (m_pVTKRenderWnd == nullptr)
	{
		// Interactor 생성
		vtkSmartPointer<vtkRenderWindowInteractor> pInteractor =
			vtkSmartPointer<vtkRenderWindowInteractor>::New();

		// Trackball Camera 인터랙션 스타일 적용
		pInteractor->SetInteractorStyle(
			vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New());

		// Renderer 생성
		vtkSmartPointer<vtkRenderer> pRenderer =
			vtkSmartPointer<vtkRenderer>::New();
		pRenderer->SetBackground(0.0, 0.0, 0.0);

		// RenderWindow 생성 후 Dialog 핸들, Interactor, Renderer 설정
		m_pVTKRenderWnd = vtkSmartPointer<vtkRenderWindow>::New();
		m_pVTKRenderWnd->SetParentId(hWnd);
		m_pVTKRenderWnd->SetInteractor(pInteractor);
		m_pVTKRenderWnd->AddRenderer(pRenderer);
		m_pVTKRenderWnd->Render();
	}
}

void CTestVTKDlg::resizeVTKWindow()
{
	CRect rc;
	GetDlgItem(IDC_STATIC_VTK_FRAME)->GetClientRect(&rc);
	m_pVTKRenderWnd->SetSize(rc.Width(), rc.Height());
}

BOOL CTestVTKDlg::OnInitDialog()
{
	|

	if (GetDlgItem(IDC_STATIC_VTK_FRAME))
	{
		initVTKWindow(GetDlgItem(IDC_STATIC_VTK_FRAME)->GetSafeHwnd());
		resizeVTKWindow();
	}

	return TRUE;  // return TRUE  unless you set the focus to a control
}


프로젝트 실행

이렇게 작성된 프로젝트를 실행하면 dll파일이 없다는 에러 메시지가 출력되는데 프로젝트의 속성에 Debugging 페이지의 Environment 항목에 VTK 빌드 결과물의 bin 폴더를 지정해준다.

Debugging > Environment: PATH=$(VTK_DIR)\bin


설정 후 프로그젝트를 실행하면 대화상자의 Picture Control에 검은색 배경이 보이면 정상적으로 실행이 된 것이다.


Cone 그려보기

대화 상자에 버튼을 올리고 버튼의 이벤트 핸들러에 아래와 같이 코드를 추가한다.

void CTestVTKDlg::OnBnClickedButtonCone()
{
	// Create a cone source
	vtkSmartPointer<vtkConeSource> pConeSource =
		vtkSmartPointer<vtkConeSource>::New();

	// Create a mapper and actor
	vtkSmartPointer<vtkPolyDataMapper> pMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	pMapper->SetInputConnection(pConeSource->GetOutputPort());

	vtkSmartPointer<vtkActor> pActor =
		vtkSmartPointer<vtkActor>::New();
	pActor->SetMapper(pMapper);

	// Visualize
	vtkSmartPointer<vtkRenderer> pRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	pRenderer->AddActor(pActor);
	pRenderer->SetBackground(0.1, 0.2, 0.3);
	pRenderer->ResetCamera();

	// Rendering
	m_pVTKRenderWnd->AddRenderer(pRenderer);
	m_pVTKRenderWnd->Render();
}

추가후 실행하면 아래와같이 각뿔 형태의 콘이 출력된다.



참고한 서적이나 인터넷의 자료에는 프로젝트의 메모리 누수를 방지하기위해서 VTK Dll들을 Delay Load를 설정해야 한다고 하였으나 본인이 테스트한 VTK 9.0.1 과 Visual Studio 2019버전에서의 테스트에서는 Delay Load를 설정하지 않아도 메모리 누수가 발생하지 않았다.


참고 자료

VTK 프로그래밍 - 일진사

https://luckygg.tistory.com/130




2020/07/22

ZXing-cpp 라이브러리를 이용한 QRCode 인식

ZXing-cpp(https://github.com/glassechidna/zxing-cpp) 라이브러리를 이용한 QRCode 인식을 해 보았다.

그간 ZXing-cpp 라이브러리를 보다 쉽게 사용하기 위해 OpenCV 라이브러리를 포함하여 만들려 했으나 굳이 그럴 필요 없이 기본 사양으로 만들어 OpenCV Raw 데이터를 이용하여 바코드 검사를 수행하도록 해 보았다. 다행스럽게도 동작이 잘 되었다. 디버그 모드에서 인식속도와 인식률은 떨어지지만 동작은 잘 되었다.


try
{
	zxing::ArrayRef<char> greyData((char*)pBuff, nWidth * nHeight);
	zxing::Ref< zxing::LuminanceSource > source(new zxing::GreyscaleLuminanceSource(greyData, nWidth, nHeight, 0, 0, nWidth, nHeight));

	zxing::Ref< zxing::Binarizer> binarizer(new zxing::GlobalHistogramBinarizer(source));
	zxing::Ref< zxing::BinaryBitmap> bitmap(new zxing::BinaryBitmap(binarizer));

	zxing::Ref< zxing::Reader > reader;
	reader.reset(new zxing::MultiFormatReader);
	zxing::Ref< zxing::Result> result(reader->decode(bitmap, zxing::DecodeHints(zxing::DecodeHints::DEFAULT_HINT)));

	zxing::Ref< zxing::String > ResultString = result->getText();
	if ( ResultString->getText().length() > 0 )
	{
		++nDetectedBarcodeCount;
		strncpy_s( szResult, nBufSize, ResultString->getText().c_str(), _TRUNCATE );

		strcat_s(szExtraResult, nBufSize, zxing::BarcodeFormat::barcodeFormatNames[result->getBarcodeFormat().value]);
		
		// Get result point count
		char szPoint[20];
		zxing::ArrayRef< zxing::Ref<zxing::ResultPoint> > resultPoints = result->getResultPoints();
		if ( resultPoints->size() > 0 ) strcat_s(szExtraResult, nBufSize, "|");
		for (int p = 0; p < resultPoints->size(); p++)
		{
			sprintf_s(szPoint, 20, "%.1fx%.1f", resultPoints[p]->getX(), resultPoints[p]->getY());

			if (p > 0) strcat_s(szExtraResult, nBufSize, ","); // Add Seprator
			strcat_s(szExtraResult, nBufSize, szPoint);
		}
	}
}
catch (const zxing::ReaderException& e)
{
	char szLog[2048] = { 0 };
	sprintf_s(szLog, _TRUNCATE, "zxing::ReaderException: %s", e.what());
	CZXingBarcode::writeLog(szLog);

	nErrorCode = -101;
}
catch (const zxing::IllegalArgumentException& e)
{
	char szLog[2048] = { 0 };
	sprintf_s(szLog, _TRUNCATE, "zxing::IllegalArgumentException: %s", e.what());
	CZXingBarcode::writeLog(szLog);

	nErrorCode = -102;
}
catch (const zxing::Exception& e)
{
	char szLog[2048] = { 0 };
	sprintf_s(szLog, _TRUNCATE, "zxing::Exception: %s", e.what());
	CZXingBarcode::writeLog(szLog);

	nErrorCode = -103;
}
catch (const std::exception& e)
{
	char szLog[2048] = { 0 };
	sprintf_s(szLog, _TRUNCATE, "std::exception: %s", e.what());
	CZXingBarcode::writeLog(szLog);

	nErrorCode = -104;
}

2020/06/18

[MFC] 관리자 권한을 필요로 하는 프로그램 만들기

관리자 권한이 필요한 프로그램을 만들어야 할 일이 있어 만드는 방법을 찾아보았다.

방법은 간단하였다. Visual Studio의 프로젝트 속성에서 Linker의 Manifest File 설정 항목중 UAC Execution Level 을 "requireAdministrator" 로 설정해 주면된다.

이렇게 만들어진 프로그램은 프로그램 아이콘에 방패모양이 오버레이된다.

Visual Studio 에서 프로젝트를 실행하려 할 경우 관리자 권한이 필요하여 아래 이미지처럼 관리자 계정으로 다시 시작을 요하는 메시지 박스가 나온다.

재시작 메뉴를 선택하면 현재 기동중인 Visual Studio가 종료되고 새로운 Visual Studio가 실행되며 관리자 권한은 요청하는 메시지 박스가 나타난다.

확인 후 실행된 Visual Studio은 아래처럼 관리자 권한으로 실행되었다.

이제 프로젝트를 실행할 수 있다.

2020/05/29

[MFC] TreeCtrl 전체 노드 확장하기

	// 전체 Tree 확장
	std::function< void (HTREEITEM) > ldExpand = [&](HTREEITEM hItem)
	{
		if ( m_treeLibrary.ItemHasChildren(hItem) )
		{
			m_treeLibrary.Expand( hItem, TVE_EXPAND );
			HTREEITEM hChild = m_treeLibrary.GetChildItem(hItem);
			if ( hItem != nullptr ) ldExpand(hChild);
		}

		hItem = m_treeLibrary.GetNextSiblingItem(hItem);
		if ( hItem != nullptr ) ldExpand(hItem);
	};

	HTREEITEM hRootItem = m_treeLibrary.GetRootItem();
	ldExpand(hRootItem);

2019/03/06

[MFC] Document/View Architecture를 사용하지 않고 FormView 사용하기

CFormView를 이용한 간단한 프로그램을 만들 때 Visual C++ 에서 제공하는 Document/View Architecture를 사용할 경우 불필요한 작업이 많은 것 같아 이를 사용하지 않고 만드는 방법을 알아보았다. 

SDI 프로젝트를 만들때 Document/View Architecture 옵션을 제거하고 프로젝트를 만든 후 기본적으로 만들어지는 View외에 추가로 CFormView를 상속받는 View을 하나 만들어 기존 View와 교체를 하면 가능하였다.

하지만 새로운 View를 만들어 교체를 할 때 일반 변수를 이용하여 Stack에 만들경우 프로그램 종료시 에러가 발생하였다. 이미 해제된 View를 다시한 번 삭제하려 하기때문인 것 같았다. Heap 메모리에 만들어지도록 하면 문제가 없었다.

//CChildFormView.h
class CChildFormView : public CFormView
{
public:  // Change constructor to public. It is private by default
 CChildFormView();           // protected constructor used by dynamic creation
 virtual ~CChildFormView();
};




//CMainFrm.h
#include "ChildFormView.h"

class CMainFrame : public CFrameWnd
{
protected:  // control bar embedded members
 CChildFormView    *m_pWndView;
};




//CMainFrm.cpp
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
  return -1;

 // First, build the view context structure
 CCreateContext ccx;

 // Designate the class from which to build the view
 ccx.m_pNewViewClass = RUNTIME_CLASS(CChildFormView);

 // Using the structure, create a view
 m_pWndView = DYNAMIC_DOWNCAST(CChildFormView, this->CreateView(&ccx));

 // Did we succeed ?
 if (!m_pWndView)
 {
  TRACE0("Creation of view failed\n");
  return -1;
 }

 // Do layout recalc
 RecalcLayout();

 // Show the view and do an initial update
 m_pWndView->ShowWindow(SW_SHOW);
 m_pWndView->OnInitialUpdate();

 // Set this view active
 SetActiveView(m_pWndView);

 // Order it to resize the parent window to fit
 m_pWndView->ResizeParentToFit(FALSE);

 // create a view to occupy the client area of the frame
//  if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
//  {
//   TRACE0("Failed to create view window\n");
//   return -1;
//  }

 if (!m_wndStatusBar.Create(this))
 {
  TRACE0("Failed to create status bar\n");
  return -1;      // fail to create
 }
 m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));

 return 0;
}


https://www.codeproject.com/Articles/5445/Using-views-effectively-without-the-doc-view-overh

2016/11/03

Using CEF(Chromium Embedded Framework) with MFC Part2

이전 글(http://neodreamer-dev.blogspot.kr/2016/11/UsingCEFwithMFCPart1.html)에 기록한대로 만든 libcef_dll_warpper.dll 을 테스트하여 보았다.
테스트에 사용된 코드는 인터넷에서 CEF 사용 방법을 찾아 돌아다니다 얻은 여러 코드를 조합하여 작성한 코드인데 출처가 기억이 나지 않는다.
단순히 CEF를 올리고 구글 페이지로 접속을 하는 코드이다.
프로젝트는 다이얼로그 기반으로 기본 컨트롤을 모두 삭제하고 브라우저를 생성하기 위해 Static  컨트롤 하나만 올린 상태이다.


//////////////////////////////////////////////////////////////////////////
// CEF
//#define CEF_USING_SANDBOX
#include "include/cef_app.h"
#include "include/cef_client.h"

//* CEF_3.2840.1511
 #ifdef _WIN64
  #ifdef _DEBUG
    #pragma comment(lib, "../CEF_3.2840.1511/bin_x64/Debug/libcef.lib")
    #ifdef CEF_USING_SANDBOX
      // MT Only
      #pragma comment(lib, "../CEF_3.2840.1511/lib_x64/Sandbox/Debug/libcef_dll_wrapper.lib")
    #else
      #ifdef _DLL
        // MD
        #pragma comment(lib, "../CEF_3.2840.1511/lib_x64/Debug/libcef_dll_wrapper_mdd.lib")
      #else
        // MT
        #pragma comment(lib, "../CEF_3.2840.1511/lib_x64/Debug/libcef_dll_wrapper_mtd.lib")
      #endif
    #endif
  #else // Release
    #pragma comment(lib, "../CEF_3.2840.1511/bin_x64/Release/libcef.lib")
    #ifdef CEF_USING_SANDBOX
      // MT Only
      #pragma comment(lib, "../CEF_3.2840.1511/lib_x64/Sandbox/Release/libcef_dll_wrapper.lib")
    #else
      #ifdef _DLL
        // MD
        #pragma comment(lib, "../CEF_3.2840.1511/lib_x64/Release/libcef_dll_wrapper_md.lib")
      #else
        // MT
        #pragma comment(lib, "../CEF_3.2840.1511/lib_x64/Release/libcef_dll_wrapper_mt.lib")
      #endif
    #endif
  #endif
#else
  #ifdef _DEBUG
    #pragma comment(lib, "../CEF_3.2840.1511/bin_x86/Debug/libcef.lib")
    #ifdef CEF_USING_SANDBOX
      // MT Only
      #pragma comment(lib, "../CEF_3.2840.1511/lib_x86/Sandbox/Debug/libcef_dll_wrapper.lib")
    #else
      #ifdef _DLL
        // MD
        #pragma comment(lib, "../CEF_3.2840.1511/lib_x86/Debug/libcef_dll_wrapper_mdd.lib")
      #else
        // MT
        #pragma comment(lib, "../CEF_3.2840.1511/lib_x86/Debug/libcef_dll_wrapper_mtd.lib")
      #endif
    #endif
  #else // Release
    #pragma comment(lib, "../CEF_3.2840.1511/bin_x86/Release/libcef.lib")
    #ifdef CEF_USING_SANDBOX
      // MT Only
      #pragma comment(lib, "../CEF_3.2840.1511/lib_x86/Sandbox/Release/libcef_dll_wrapper.lib")
    #else
      #ifdef _DLL
        // MD
        #pragma comment(lib, "../CEF_3.2840.1511/lib_x86/Release/libcef_dll_wrapper_md.lib")
      #else
        // MT
        #pragma comment(lib, "../CEF_3.2840.1511/lib_x86/Release/libcef_dll_wrapper_mt.lib")
      #endif
    #endif
  #endif
#endif
//*/
//////////////////////////////////////////////////////////////////////////

BOOL CTestCEFinMFCDlg::DestroyWindow()
{
  CefShutdown();

  return CDialogEx::DestroyWindow();
}

BOOL CTestCEFinMFCDlg::OnInitDialog()
{
  :
  CRect rcBrowser;
  GetDlgItem(IDC_STATIC_BROWSER)->GetClientRect(&rcBrowser);

  //Create the necessary objects needed to initialize CEF 
  CefMainArgs cefMainArgs(theApp.m_hInstance);

  CefSettings cefSettings;
  CefBrowserSettings cefBrowserSettings;
  CefRefPtr<CefApp> cefApplication;
  CefWindowInfo cefWindowinfo;

  cefSettings.multi_threaded_message_loop = true; //needed for MFC projects (unless we want to implement custom message-loop)
  cefWindowinfo.SetAsChild(GetDlgItem(IDC_STATIC_BROWSER)->GetSafeHwnd(), rcBrowser);

  //   CefRefPtr<CefClient> client(new ClientHandler());
  //   m_Handler = (ClientHandler*)client.get();

  //Initialize CEF 
  bool bSucceeded = CefInitialize(cefMainArgs, cefSettings, cefApplication, nullptr);
  CefRefPtr<CefRequestContext> request_context;

  CefRefPtr<CefClient> client;
  if (bSucceeded)
  {
    CefBrowserHost::CreateBrowser(cefWindowinfo, client, L"http://www.google.com/", cefBrowserSettings, request_context);
  }  
  :
}


Using CEF(Chromium Embedded Framework) with MFC Part1

Using CEF(Chromium Embedded Framework) with MFC Part1

MFC를 이용하여 Application을 만들 때 Windows 기본 브라우저 말고 크롬을 올리기 위해 방법을 찾아 보았다.
Chromium Embedded Framework(이하 CEF) 라는 프로젝트를 찾았고 현재 버전 3까지 나와 있다. CEF를 MFC 프로젝트에 사용을 하려면 libcef_dll_wrapper.dll을 만들어야 한다.
이때, 컴파일러 옵션중 Runtime Library 설정에 따라 사용할 수 있는 libcef_dll_wrapper.dll을 만들어야 한다. 라이브러리를 만들 때 Sandbox 사용 설정 여부에따라 만들어진 라이브러리의 사용에 제한이 있는 것 같았다. 우선 Sandbox 설정을 제외하고 빌드 해 보았다.
빌드를 하는 방법은 어렵지 않으나 나중에 참고하기 위해 정리를 하였다.

libcef_dll_wrapper.dll를 만들기 위해서는 CEF Automated Builds 사이트(http://opensource.spotify.com/cefbuilds/index.html)에서 소스를 다운 받는다. 그리고 빌드 환경을 구성할 CMake 를 준비한다.
글을 작성하는 현재 버전은 CEF 3.2840.1512.g3f66e81(Chromium 54.0.2840.59) 이고, 빌드에 사용된 버전은 CEF 3.2840.1511.gb345083(Chromium 54.0.2840.59) 이다.
사용하고자 하는 버전과 일치하는 Standard Distribution 을 다운 받아 압축을 해제한다.
CMake를 실행하여 소스 경로에 압축을 해제한 경로를 설정하고 Build the binaries 경로에 프로젝트를 생성한 경로를 설정한고 Configure를 신행한다.
많은 설정 중 마지막에 있는 USE_OFFICIAL_BUILD_SANDBOX, USE_SANDBOX 설정을 해제한다.
해제하지 않을 경우 만들어 지는 프로젝트는 Runtime Library 옵션이 /MT 로 고정이 된다. 다른 옵션을 만들어 테스트해 보았지만 기존의 만들어진 cef_sandbox 라이브러리가 /MT 옵션으로 고정되어 있어서인지 다른 설정으로 바꾸면 프로젝트를 빌드 할 때 링크 에러가 발생하여고 빌드가 되지 않았다.
Sandbox를 사용하지 않는 경우에는 여러 Runtime Library에 대한 사용에 문제가 없었다. Sandbox 이용에 대해서는 나중에 좀 더 확인을 해 봐야겠다.
설정을 마치고 Configure 를 실행 한 후 Generate를 실행하여 프로젝트를 생성한다.

그리고 Build the binaries 경로에있는 cef.sln 을 Visual Studio로 열어 libdef_dll_wrapper 프로젝트의 속성 페이지를 열어 추가하고자 하는 프로젝트와 동일한 Runtime Library 옵션을 선택하고 빌드한다.
본인의 경우 /MD /MDd /MT /MTd 옵션을 각각 설정하고 출력 파일 이름을 달리하여 추후 사용할 때 골라서 사용할 수 있도록 빌드하였다. 그래서 만들어진 파일이 아래 파일들이다.
libcef_dll_wrapper_mtd.pdb
libcef_dll_wrapper_mdd.lib
libcef_dll_wrapper_mtd.lib
libcef_dll_wrapper_mdd.pdb
libcef_dll_wrapper_mt.lib
libcef_dll_wrapper_md.lib

이 파일들을 이용하여 MFC 프로젝트에 CEF를 사용하면 된다.

2016/10/05

Using VTK with MFC Project

VTK 버전 7.0이 나와서 새로 빌드도 해 보고 다시 공부좀 해볼까 하여 오랜만에 VTK를 빌드해 보았다.
아주 오랜만에 다시 해 보는 것이고 이전 기록이 많지않아 동일한 시행착오를 피할 수 없었다.
빌드를 무사히 마치고 Visual Studio 에서 테스트 하는데 더 큰 걸림돌이 있었다.
검색 결과 CMake를 이용하지 않는 경우 초기화(?) 코드가 필요 하였다.
게다가 버전 7은 버전 6에서 변경된 사항이 있어 동일한 코드로 초기화가 되지 않았다.
추후 동일한 문제로 고생하지 않기 위해 기록을 남긴다.


For VTK 6.x
다른 헤더파일을 포함하기 전에 먼저 "vtkAutoInit.h"를 포함하고 일부 모듈을 초기화 해 주어야 한다.

#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingFreeTypeOpenGL);
VTK_MODULE_INIT(vtkRenderingOpenGL);

#define vtkRenderingCore_AUTOINIT 4(vtkInteractionStyle,vtkRenderingFreeType,vtkRenderingFreeTypeOpenGL,vtkRenderingOpenGL)
#define vtkRenderingVolume_AUTOINIT 1(vtkRenderingVolumeOpenGL)
http://www.vtk.org/Wiki/VTK/VTK_6_Migration/Factories_now_require_defines


For VTK 7.x
VTK 7.x의 경우 OpenGL이 OpenGL2로 새롭게 바뀌었으며 빌드할 때 별도의 설정을 하지 않은 경우 OpenGL2로 설정이 되기때문에 VTK 6.x 에서 초기에 수행한 OpenGL 설정을 OpenGL2 로 변경을 해 주어야 한다. 그리고 vtkRenderingFreeTypeOpenGL 은 삭제되었다 한다.

#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingOpenGL2);

#define vtkRenderingCore_AUTOINIT 3(vtkInteractionStyle,vtkRenderingFreeType,vtkRenderingOpenGL2)
http://www.visitusers.org/index.php?title=VTK_7.1_Upgrade

2015/05/26

[MFC] VTK Hello World

천천히 VTK 를 공부하고 있다.


지난 번 라이브러리를 빌드 한 후 VTK C++ Tutorial을 하나하나씩 해보기로 하였다. 그 첫번째로 Hello World 이다.
Tutorial에서는 C++ 코드와 CMake를 이용한 빌드를 소개하고 있다. 이를 이전에 빌드한 vtkGUISupportMFC 를 이용하여 대화상자에 출력하도록 해 보았다.



m_pvtkMFCWindow = new vtkMFCWindow(this);
m_pvtkMFCWindow->GetRenderWindow()->AddRenderer(m_pvtkRenderer);
m_pvtkRenderer->SetBackground(0.0, 0.0, 0.5);


// This creates a polygonal cylinder model with eight circumferential facets.
//
m_pCylinder = vtkCylinderSource::New();
m_pCylinder->SetResolution(8);

// The mapper is responsible for pushing the geometry into the graphics
// library. It may also do color mapping, if scalars or other attributes
// are defined.
//
m_pCylinderMapper = vtkPolyDataMapper::New();
m_pCylinderMapper->SetInputConnection(m_pCylinder->GetOutputPort());

// The actor is a grouping mechanism: besides the geometry (mapper), it
// also has a property, transformation matrix, and/or texture map.
// Here we set its color and rotate it -22.5 degrees.
m_pCylinderActor = vtkActor::New();
m_pCylinderActor->SetMapper(m_pCylinderMapper);
m_pCylinderActor->GetProperty()->SetColor(1.0000, 0.3882, 0.2784);
m_pCylinderActor->RotateX(30.0);
m_pCylinderActor->RotateY(-45.0);

// Render on MFCWindow
// Add the actors to the renderer, set the background and size
//
m_pvtkRenderer->AddActor(m_pCylinderActor);
m_pvtkRenderer->SetBackground(0.1, 0.2, 0.4);

// We'll zoom in a little by accessing the camera and invoking a "Zoom"
// method on it.
m_pvtkRenderer->ResetCamera();
m_pvtkRenderer->GetActiveCamera()->Zoom(1.5);



Original Post : http://neodreamer-dev.tistory.com/745

2015/05/23

CListCtrl 에서 Check 상태 변화 확인 하기

CListCtrl에서 Check Box를 보이게 한 후 상태 변화를 확인하기 위해 LVN_ITEMCHANGED 의 메시지 핸들러의 파라메터를 확인해 보니 Item의 Uncheck와 check 가 각각 4096(0x1000) 과 8192(0x2000) 값으로 전달 되었다.


void CDlgTestDlg::OnLvnItemchangedList2(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

if(pNMLV->uChanged & LVIF_STATE)
{
if( (pNMLV->uOldState & 0x1000) && (pNMLV->uNewState & 0x2000) )
{
TRACE("Checked Item : %d\n", pNMLV->iItem);
}
else if( (pNMLV->uOldState & 0x2000) && (pNMLV->uNewState & 0x1000) )
{
TRACE("Unchecked Item : %d\n", pNMLV->iItem);
}
}

*pResult = 0;
}


Original Post : http://neodreamer-dev.tistory.com/744

2015/03/31

VTK 6.2 빌드하기

얼마 전 공개된 VTK 6.2 버전을 빌드해 보았다.


VTK를 빌드하기 위해서는 kitware에서 제공하는 Cmake 툴이 필요하다.


Cmake 툴을 실행하고 Source Code 경로에 VTK 6.2 버전의 경로를 설정한다.
그리고 binaries 경로는 Visual Studio project가 생성될 경로이다. 적당한 경로를 설정하고 "Advanced" 옵션을 선택하여 모든 옵션을 볼 수 있도록 한다.


그리고 "Configure"버튼을 선택하여 Configuration을 진행한다.
처음 진행을 하면 경로가 없는 경우 경로을 생성한다는 메시지 박스가 출력이 된다.



그리고 프로젝트를 생성하기 위한 컴파일러 버전을 선택하는 대화상자가 나타난다.



컴파일러를 선택하고 Configuration을 진행하면 옵션 리스트가 갱신이 되고 모든 옵션이 붉은색 하이라이트로 표시 된다.

기본적으로 아래 언급된 옵션들에 대하여 사용 여부를 선택 한다.


"BUILD_SHARED_LIBS"
이 옵션은 라이브러리를 Dynamic으로 할 것인지 Static으로 할 것인지 설정하는 옵션으로 이 옵션을 선택하면 Dynamic DLL 이 생성하는 프로젝트가 만들어지고 그렇지 않은 경우 Static DLL을 생성하는 프로젝트가 만들어 진다.


"BUILD_EXAMPLES"
예제 프로젝트를 생성할지 여부를 선택하는 것으로 이를 선택하면 생성된 프로젝트의 빌드 시간이 길어진다. (선택하지 않는 것이 좋다.)


"BUILD_TESTING"
테스트 프로젝트 생성 여부로 BUILD_EXAMPLES 와 같이 프로젝트의 빌드 시간에 많은 영향을 준다.(선택하지 않는 것이 좋다.)



"CMAKE_INSTALL_PREFIX"
생성될 프로젝트 중 install project를 빌드할 경우 최종 결과물이 복사될 경로이다. 빌드하는 PC에서만 사용하는경우 기본값(Program FIles/VTK)으로 두어도 되지만 추후 다른 프로젝트에 쓰고 이동을 하는 경우에 활용하기 위해 별도의 경로를 지정하였다.



"Module_vtkGUISupportMFC"
MFC의 GUI를 지원하기 위해 이 옵션을 선택한다.


옵션 설정을 마치고 "Configuration"을 다시 진행을 하면 "BUILD_TESTING"옵션을 해제한 경우 "...vtkTesting..." 옵션 몇 가지가 붉은색으로 표시가 되는데 이는 다시 "Configuration"을 진행하면 사라진다.


에러(붉은색 하이라이트 옵션)이 없음을 확인하고 "Generate"를 선택하면 binaries 경로도 지정된 곳에 프로젝트가 생성이 된다.


프로젝트 파일 중 VTK.sln 파일을 열어서 ALL_BUILD를 Debug와 Release를 빌드하면 필요한 파일들이 생성이 된다. 추가로 install 프로젝트를 빌드하는 경우 "CMAKE_INSTALL_PREFIX" 경로에 bin, include, lib 폴더가 생성이 되고 관련 파일들이 이 곳으로 복사되어 진다.


참고로 Visual Studio 2013 버전 이상을 사용하는 경우 MBCS 라이브러리를 추가로 설치하고 프로젝트를 빌드해야 한다. Visual Studio 2013 버전부터는 MBCS 라이브러리가 배제된 상태로 제공이 된다. VTK 모든 프로젝트를 Unicode로 설정하여 빌드해 보았는데 무수히 많은 에러를 토해내어서 포기 하였다.


Multibyte MFC Library for Visual Studio 2013


이제 빌드를 마쳤고 하나씩 공부해 나갈 차례이다.
Original Post : http://neodreamer-dev.tistory.com/737

2014/06/10

MFC 프로그램에 Console 대화상자 띄우기

#ifdef _DEBUG
# ifdef UNICODE
# pragma comment(linker, "/entry:wWinMainCRTStartup /subsystem:console")
# else
# pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console")
# endif
#endif


#ifdef _DEBUG
cout << "test consol out by cout\n";
printf("test consol out by printf\n");
#endif // _DEBUG
<

Original Post : http://neodreamer-dev.tistory.com/727

2012/06/01

[MFC] System Menu에 "About..." 메뉴 추가하기

DialogBased 응용프로그램에서 시스템 메뉴에 사용자 메뉴를 추가하기 위해 찾은 정보이다.



////////////////////////////////////////////////////////////////////////////////
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

<

Original Post : http://neodreamer-dev.tistory.com/658

2012/05/14

[MFC] CListCtrl 모든 컬럼 삭제하기

CListCtrl 의 모든 컬럼을 삭제하는 코드이다.

첫 번째 컬럼을 삭제하고  다머지 컬럼이 이동 되므로 0번 컬럼을 실패할 때까지 계속 삭제한다.

while ( m_list.DeleteColumn(0) );
<

Original Post : http://neodreamer-dev.tistory.com/651

2012/02/05

Visual C++ 프로젝트에 SQLite 포함시키기

SQLite 는 32비트 Dll 형태로 기본 배포가 되고 있다.

하지만 프로젝트를 진행함에 있어 다양한 환경에 접하게 된다. 요즘은 64비트 프로젝트로 일반화 되어 있어 32비트 Dll 만드로는 부족한 것이 많다.



이전에는 64비트 프로젝트에서 사용하기 위해 별도의 Dll 이나 Static Library 만들어 사용 하였다.

하지만 굳이 그렇게 별도의 라이브러리를 만들지 않아도 쉽게 프로젝트에 SQLite 를 포함 시킬 수 있다.



SQLite 사이트에서 배포하는 amalgamation 소스를 이용하면 된다.

프로젝트에 원하는 SQLite 버전의 amalgamation 소스를 추가 한다. 추가되는 파일은 아래 4개 파일 이다.


shell.c


sqlite3.c


sqlite3.h


sqlite3ext.h



이 파일들 중에서 sqlite3.c 와 sqlite3.h 파일을 이용하게 된다.

프로젝트를 컴파일 하면 아래와 같은 에러 메시지를 만나게 된다.

Error 1 error C1853: 'x64\Debug\xxx.pch' precompiled header file is from a previous version of the compiler, or the precompiled header is C++ and you are using it from C (or vice versa)


sqlite3.c 파일이 C로 작성이 되어 Precompiled Header 를 지원하지 않는다. 따라서 Precompiled Header를 사용하지 않도록 해야 하는데 프로젝트 전반적으로 설정할 경우 컴파일 속도에 많은 문제가 되므로 sqlite3.c 파일만 Precompiled Header를 사용하지 않도록 설정한다.

방법은 Solution Explorer 에서 sqlite3.c 파일을 선택하고 속성창을 실행해서 Precompiled Header를 사용하지 않음으로 설정하고 컴파일 하면 된다.

 &

Original Post : http://neodreamer-dev.tistory.com/636

2011/10/25

[MFC] CDialogEx

Visual Studio 2010 버전에서 대화상자를 만들다. 2010 버전에서는 기본적으로 CDialogEx를 상속받아 대화상자를 만드는 것을 보았다.



MFC 9.0 부터 지원하고있는 CDialogEx라는 녀석을 찾아 보았다. 기본제공하는 클래스라 MSDN에서 쉽게 찾을 수 있었다.

CDiglogEx는 CDialog에서 배경을 제어하는 함수만 추가된 클래스였다. 추가된 함수는 아래 두 개이다.

// Control Background color
void SetBackgroundColor(
COLORREF color,
BOOL bRepaint=TRUE
);

// Control Background Image
void SetBackgroundImage(
HBITMAP hBitmap,
BackgroundLocation location=BACKGR_TILE,
BOOL bAutoDestroy=TRUE,
BOOL bRepaint=TRUE
);
BOOL SetBackgroundImage(
UINT uiBmpResId,
BackgroundLocation location=BACKGR_TILE,
BOOL bRepaint=TRUE
);




SetBackgroundColor 는 배경색을 설정하는 것으로 원하는 색상을 파라메터로 넘기면 쉽게 대화상자의 배경색을 변경할 수 있다. 기본 제공하는 클래스 에서는 체크박스와의 사소한 버그가 있다고 한다.


SetBackgroundImage 는 비트맵 객체나 비트맵 리소스로 배경 채워 준다.

채우는 방법은 기본 적으로 타일(BACKGR_TILE)형태로 하며 몇 가지 형태(BACKGR_TILE, BACKGR_TOPLEFT, BACKGR_TOPRIGHT, BACKGR_BOTTOMLEFT, BACKGR_BOTTOMRIGHT)로 설정할 수 있다.


배경색 변경의 사소한 버그도 있고 배경이미지를 컨트롤 하는 것에도 유연성이 많이 부족해 보인다. 제대로 배경을 설정하고자 한다면 다시 만들어야 할 듯 하다.


CDialogEx on MSDN 

Original Post :
http://neodreamer-dev.tistory.com/607

2011/10/17

CStdioFile::WriteString 의 함정

텍스트 파일 저장에 편하여 사용하는 CStdioFile 클래스의 WriteString에서 꼭 알아야할 사항이 있다.

뭐 나만 모르고 있는 것 일 수도 있지만...  CStdioFile::WriteString 은 널 문자를 쓰지 않고 Line feed(\n) 문자를 Carriage Return(\r) 과 Line Feed(\n) 짝을 이뤄 파일에 저장을 한다.



따라서 다섯개의 "\r\n"을 출력하면 아래 처럼 Carriage Return이 하나 더 붙어서 출력이 된다. 아래 내용을 읽어들인 프로그램은 Notepad2로 이 파일을 Mac 형식으로 인식해서 보여준다.



이렇게 작성한 파일은 나중에 메모장에서 Word Wrap 기능사용시 문제를 일으키기도 하는 것 같다.

CStdioFile::WriteString를 사용할 때는 여느 파일 작성때와 같이 버릇처럼 줄넘김을 윈도우 기본 형태인 \r\n 형태로 출력하면 안되겠다.



아마 처음 CStdioFile::WriteString 함수를 접할 때 MSDN을 한번만 이라도 주위깊게 읽었더라면 쉽게 알고 있을만한 사항이다.



MSDN 에서 CStdioFile::WriteString 함수에 대한 Remark 부분에 아래와 같은 설명이 되어 있다.

The terminating null character ('\0') is not written to the file. Any newline character in lpsz is written to the file as a carriage return–linefeed pair.

 



CStdioFile::WriteString on MSDN



+ 2011/10/19

이 문제는 CStdioFile::WriteString 함수만의 문제가 아니였다. 기본적으로 C 에서의 파일(FILE) 입출력 할 때 텍스트 모드로 할 경우 자동으로 변경 되는 것이다. MSDN에서 찾아보면 텍스트 모드에 대해서 아래와 같은 설명이 있었다.

in text mode, carriage return?linefeed combinations are translated into single linefeeds on input, and linefeed characters are translated to carriage return?linefeed combinations on output.


fopen on MSDN


&

Original Post : http://neodreamer-dev.tistory.com/601

2011/10/07

함수 이름 가져오는 매크로

흥배님의 블로그를 통해 함수 이름을 가져오는 매크로인 __FUNCTION__, __FUNCSIG__ 에 대해 알게되어 이와 유사한 매크로가 더 있는 찾아 보았다.



MSDN 에서 Predefined Macros 로 찾으니 쉽게 찾아 졌다.

흥배님께서 언급한 두 개의 매크로 외에 __FUNCDNAME__ 라는 녀석도 있었다. 이들의 쓰인 결과를 보면 어떤 역할을 하는 매크로 인지 쉽게 알 수 있다.



아래 코드는 MSDN에서 발췌한 코드 이다. MSDN의 Predefined Macros 페이지에 보다 다양한 매크로에 대해 설명 하고 있다.

// Demonstrates functionality of __FUNCTION__, __FUNCDNAME__, and __FUNCSIG__ macros
void exampleFunction()
{
printf("Function name: %s\n", __FUNCTION__);
printf("Decorated function name: %s\n", __FUNCDNAME__);
printf("Function signature: %s\n", __FUNCSIG__);

// Sample Output
// -------------------------------------------------
// Function name: exampleFunction
// Decorated function name: ?exampleFunction@@YAXXZ
// Function signature: void __cdecl exampleFunction(void)
}

 



Predefined Macros on MSD

Original Post :
http://neodreamer-dev.tistory.com/584

2011/04/06

Dialog based 프로젝트에서 Windows 7 Taskbar 아이콘에 Progress 출력하기

Dialog based 프로젝트의 경우 CFrameWnd 클래스가 없어서 적접적으로 Taskbar 관련 함수를 사용할 수 없다. 이때에는 CoCreateInstance 함수를 이용하여 Taskbar Button 객체를 가져와야 한다. 하지만 이때에 Taskbar Button 이 만들어 진 후에 작업을 해야 한다.



프로그램이 완전히 실행한 뒤에 Taskbar Button 객체를 가져와도 되지만 Taskbar Button 이 만들어진 후를 감지하여 객체를 가져오는 것이 보다 유연한 방법일 것이다. 그러기 위해서는 TaskbarButtonCreated 메시지를 받아 처리하여야 한다.



아래 코드는 메시지 등록과 이를 처리하는 과정 그리고 간단하게 Progress 를 출력하는 코드이다.

////////////////////////////////////////////////////////////////////////////////
// Header
ITaskbarList3* m_pTaskbar;

static const UINT WM_TASKBARBUTTONCREATED;
LRESULT OnTaskbarBtnCreated ( WPARAM wParam, LPARAM lParam );


////////////////////////////////////////////////////////////////////////////////
// Source
const UINT CMyTaskbarDlg::WM_TASKBARBUTTONCREATED
= RegisterWindowMessage( _T("TaskbarButtonCreated") );

BEGIN_MESSAGE_MAP(CMyTaskbarDlg, CDialogEx)
:
ON_REGISTERED_MESSAGE(WM_TASKBARBUTTONCREATED, &CMyTaskbarDlg::OnTaskbarBtnCreated)
:
END_MESSAGE_MAP()

LRESULT CMyTaskbarDlg::OnTaskbarBtnCreated ( WPARAM wParam, LPARAM lParam )
{
if ( CoCreateInstance(
CLSID_TaskbarList,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&m_pTaskbar) ) != S_OK )
{
m_pTaskbar = NULL;
}

return 0;
}

void CMyTaskbarDlg::OnBnClickedBtnProgressDisplay()
{
if ( m_pTaskbar != NULL )
{
switch ( m_cmbProgressType.GetCurSel() )
{
case 1:
m_pTaskbar->SetProgressState( m_hWnd, TBPFLAG::TBPF_INDETERMINATE );
TRACE("Display Progress TBPFLAG::TBPF_INDETERMINATE \n");
break;

case 2:
m_pTaskbar->SetProgressState( m_hWnd, TBPFLAG::TBPF_NORMAL );
m_pTaskbar->SetProgressValue( m_hWnd, 72, 100 );
TRACE("Display Progress TBPFLAG::TBPF_NORMAL \n");
break;

case 3:
m_pTaskbar->SetProgressState( m_hWnd, TBPFLAG::TBPF_ERROR );
m_pTaskbar->SetProgressValue( m_hWnd, 72, 100 );
TRACE("Display Progress TBPFLAG::TBPF_ERROR \n");
break;

case 4:
m_pTaskbar->SetProgressState( m_hWnd, TBPFLAG::TBPF_PAUSED );
m_pTaskbar->SetProgressValue( m_hWnd, 72, 100 );
TRACE("Display Progress TBPFLAG::TBPF_PAUSED \n");
break;

default:
m_pTaskbar->SetProgressState( m_hWnd, TBPFLAG::TBPF_NOPROGRESS );
TRACE("Display Progress TBPFLAG::TBPF_NOPROGRESS \n");
break;
}
}
}




2011/04/06 - [Dev Story/Tips] - Windows 7 Taskbar 아이콘에 Progress Bar 출력하기


Original Post : http://neodreamer-dev.tistory.com/530

Windows 7 Taskbar 아이콘에 Progress Bar 출력하기

Windows 7 의 테스트바 아이콘은 많은 기능을 갖고 있다. 그 중 하나인 진행 상태를 표시해 보았다.

Visual Studio 2010 버전을 사용할 경우 이는 대단히 간단한 것이다. 



CFrameWnd 의 멤버 변수인 아래 세 개의  함수로 구현할 수 있다.


  • SetProgressBarState

  • SetProgressBarRange

  • SetProgressBarPosition




SetProgressBarState





void SetProgressBarState(


   TBPFLAG tbpFlags


);



Progress 의 상태를 설정하는 함수로 인자 아래와 같은 인자를 넘겨줄 수 있다.

TBPF_NOPROGRESS, TBPF_INDETERMINATE, TBPF_NORMAL, TBPF_ERROR, TBPF_PAUSED.



TBPF_NOPROGRESS - Progress 사용하지 않는 상태





TBPF_INDETERMINATE - 끝이 정해지지 않은 상태





TBPF_NORMAL - 기본 상태





TBPF_ERROR - 에러가 발생한 상태로 아래와 같이 붉은색으로 표시 된다.





TBPF_PAUSED - 진행이 멈춘 상태로 아래와 같이 노란색으로 표시 된다.









SetProgressBarRange 




void SetProgressBarRange(


   int nRangeMin,


   int nRangeMax


);



Progress 표시 범위 설정하는 함수로 최소값과 최대값을 전달하여 설정할 수 있다. 







SetProgressBarPosition




void SetProgressBarPosition(


   int nProgressPos

); 



Progress 의 현재 값을 설정하는 함수.

 

이 함수 사용에 주의할 점은 SetProgressBarState 에서 TBPF_NOPROGRESS, TBPF_INDETERMINATE 에서 설정을하고 SetProgressBarPosition 함수가 수행이 되면 Progress Bar 는 TBPF_NORMAL 상태로 출력하게 된다.



아래 코드는 간단한 사용 예로 실제 진행에 대하 것은 빠진 상태이다.

m_pFrame = (CMainFrame*)GetParentFrame();


switch ( m_cmbProgressType.GetCurSel() )
{
case 1: // TBPFLAG::TBPF_INDETERMINATE
m_pFrame->SetProgressBarState( TBPFLAG::TBPF_INDETERMINATE );
TRACE("Display Progress TBPFLAG::TBPF_INDETERMINATE \n");
break;

case 2: // TBPFLAG::TBPF_NORMAL
m_pFrame->SetProgressBarState( TBPFLAG::TBPF_NORMAL );
m_pFrame->SetProgressBarRange( 0, 100 );
m_pFrame->SetProgressBarPosition( 72 );
TRACE("Display Progress TBPFLAG::TBPF_NORMAL \n");
break;

case 3: // TBPFLAG::TBPF_ERROR
m_pFrame->SetProgressBarState( TBPFLAG::TBPF_ERROR );
m_pFrame->SetProgressBarRange( 0, 100 );
m_pFrame->SetProgressBarPosition( 72 );
TRACE("Display Progress TBPFLAG::TBPF_ERROR \n");
break;

case 4: // TBPFLAG::TBPF_PAUSED
m_pFrame->SetProgressBarState( TBPFLAG::TBPF_PAUSED );
m_pFrame->SetProgressBarRange( 0, 100 );
m_pFrame->SetProgressBarPosition( 72 );
TRACE("Display Progress TBPFLAG::TBPF_PAUSED \n");
break;

default: // TBPFLAG::TBPF_NOPROGRESS
m_pFrame->SetProgressBarState( TBPFLAG::TBPF_NOPROGRESS );
TRACE("Display Progress TBPFLAG::TBPF_NOPROGRESS \n");
break;
}

<

Original Post : http://neodreamer-dev.tistory.com/529