본문 바로가기

Visual C++/MFC CScrollView

MFC CScrollView example

MFC MDI 뷰에 스크롤바 적용하기


화면에 DCM 파일을 출력하는 예를 보려면 여기 링크를 눌러 참조하세요


MFC 기반의 프로젝트에서 MDI 뷰에 스크롤바를 적용하려면 View 클래스의 기반클래스를 CScrollView로 설정하면 된다.

그러므로 프로젝트 생성시 Wizard의 마지막 단계에서 View의 기반클래스를 CView로 하지않고 CScrollView로 하면 된다.


View의 기반클래스가 CScrollView로 설정되면 다음과 같은 View 클래스가 선언된다

class CDCMTK_IMG_OutputView : public CScrollView

{



위와 같은 방법으로 생성된 뷰에는 스크롤바가 적용된다. 그러나 스크롤바가 화면에 보여지는 시기는 개발자가 소스코드를 편집하여 변경해주어야 한다


View 클래스의 OnInitialUpdate() 함수에는 기본적으로 다음과 같은 내용으로 작성되어 있다

void CDCMTK_IMG_OutputView::OnInitialUpdate()

{

CScrollView::OnInitialUpdate();


CSize sizeTotal;

// TODO: 이 뷰의 전체 크기를 계산합니다.

sizeTotal.cx = sizeTotal.cy = 100;

SetScrollSizes(MM_TEXT, sizeTotal); // MM_TEXT 는 논리적인 크기의 단위가 픽셀이라는 것을 의미한다

}


위의 기본코드에서 사용된 100 이라는 숫자는 논리적인 화면의 크기를 의미하며 화면의 크기가 이 숫자 이하로 작아지면 스크롤바가 나타나고 화면의 크기가 이 숫자보다 커지면 스크롤바가 사라지게 된다. 그러므로 이 숫자는 보여져야 하는 내용물의 크기로 설정할 필요가 있다.

예를 들어 보여져야 할 이미지의 전체 크기로 설정하면 화면이 이미지의 크기보다 작아지면 자동으로 스크롤바가 나타나게 된다.


SetScrollSizes() 함수는 CScrollView 클래스의 멤버함수이며 코드상의 임의의 위치에서 호출이 가능하기 때문에 화면보다 큰 이미지를 보여주기 직전에 그 이미지의 크기를 구해서 CSize 에 설정하고 SetScrollSizes() 함수를 호출하면 해당 이미지의 크기보다 화면이 작은 경우에 스크롤바가 나타나게 된다.


CSize imgSize;

imgSize.cx = width;

imgSize.cy = height;

SetScrollSizes(MM_TEXT, imgSize);



스크롤바가 생성된 모습




View 클래스의 주요함수 내용


#include "stdafx.h"


#include "dcmtk/config/osconfig.h" 

#include "dcmtk/dcmdata/dctk.h"

#include "dcmtk/dcmimgle/dcmimage.h"

#include "dcmtk/dcmjpeg/djutils.h"

#include "dcmtk/dcmjpeg/djdecode.h"



#pragma comment(lib, "dcmtk.lib")


// 중간 코드 생략


// CDCMTK_IMG_OutputView 그리기

DicomImage *ptrDicomImage = NULL;

void* data = NULL;

BITMAPINFO bi;

HBITMAP hbmp = 0;


void CDCMTK_IMG_OutputView::OnDraw(CDC* pDC)

{

CDCMTK_IMG_OutputDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!pDoc)

return;


// TODO: 여기에 원시 데이터에 대한 그리기 코드를 추가합니다.


//LPCTSTR lpstrFile = _T("D:\\test\\sample.dcm");

LPCTSTR lpstrFile = _T("D:\\test\\샘플.dcm");


USES_CONVERSION;


char* filename = W2A(lpstrFile);


DcmFileFormat* ptrDcmFileFormat = new DcmFileFormat();

OFCondition cond = ptrDcmFileFormat->loadFile(filename);

if (cond.good())

{

//AfxMessageBox(_T("DCM파일 로드성공"));

}

else if(cond.bad())

{

AfxMessageBox(_T("DCM파일 로드실패"));

exit(0);

}


DJDecoderRegistration::registerCodecs(); // register JPEG codecs

DcmDataset *dataset = ptrDcmFileFormat->getDataset();


// decompress data set if compressed

dataset->chooseRepresentation(EXS_LittleEndianExplicit,NULL);


E_TransferSyntax xfer = ptrDcmFileFormat->getDataset()->getOriginalXfer();


if(ptrDicomImage==NULL)

    ptrDicomImage = new DicomImage(ptrDcmFileFormat, xfer, CIF_AcrNemaCompatibility, 0, 1);


if(ptrDicomImage != NULL)

{

//AfxMessageBox(_T("DicomImage 인스턴스 생성 성공"));

}

else

{

AfxMessageBox(_T("DicomImage 인스턴스 생성 실패"));

exit(0);

}


if(ptrDicomImage->getStatus()!= EIS_Normal) exit(0);


int width  = (int)ptrDicomImage->getWidth();

int height = (int)ptrDicomImage->getHeight();


        // 스크롤바가 나타나고 사라지는 화면의 기준크기 설정

CSize imgSize;

imgSize.cx = width;

imgSize.cy = height;

SetScrollSizes(MM_TEXT, imgSize);


int nResult = ptrDicomImage->setMinMaxWindow();


if(data==NULL) 

{

ptrDicomImage->createWindowsDIB(data, width*height);

if(data!=NULL) // data 는 사용후 반드시 헤제해야 함

{

//BITMAPINFO bi; 

bi.bmiHeader.biSize        = sizeof(bi); 

bi.bmiHeader.biWidth       = width; 

bi.bmiHeader.biHeight      = -height; 

bi.bmiHeader.biPlanes      = 1; 

bi.bmiHeader.biBitCount    = 24; 

bi.bmiHeader.biCompression = BI_RGB;

bi.bmiHeader.biSizeImage   = 0;

}

}

// hbmp 는 사용후 반드시 헤제해야 함

hbmp = CreateDIBitmap(pDC->GetSafeHdc(), &bi.bmiHeader, CBM_INIT, data, &bi, DIB_RGB_COLORS);

if(hbmp)

{  

HDC memDC = CreateCompatibleDC(pDC->GetSafeHdc()); // memDC 는 사용후 반드시 헤제해야 함

SelectObject(memDC, hbmp); 

 

SetStretchBltMode(memDC, HALFTONE);

StretchBlt(pDC->GetSafeHdc(), 0, 0, width, height,

memDC, 0, 0, width, height, SRCCOPY);

DeleteDC(memDC); 

DeleteObject(hbmp);

}

//delete data;

}



void CDCMTK_IMG_OutputView::OnInitialUpdate()

{

CScrollView::OnInitialUpdate();


CSize sizeTotal;

// TODO: 이 뷰의 전체 크기를 계산합니다.

sizeTotal.cx = sizeTotal.cy = 100;

SetScrollSizes(MM_TEXT, sizeTotal);


}