5.Active X 이용하기

본장은 전장에서 설명한 ActiveX 에 대한 참고항목입니다. 전장은 ActiveX를 만드는 방법에 대하여 중점적으로 설명하였습니다. 본장에서는 현재 설정되어 있는 여러 ActiveX프로그램을 사용하는 방법에 대해서 설명합니다. 본장에서는 ActiveX를 사용하는 방법을 설명하기 위해 Grid 컨트롤과 Image View 두개의 ActiveX 를 로드하는 예를 설명합니다.

대상자: 초급,중급,고급

Chapter 등급: 선택

공부방법:

전장의 내용을 이해하셨다면 볼필요가 없는 항목입니다. 다만 ActiveX를 이용하는 부분에 대해서 참고하고자 하는 분들만 본항목을 읽어보시기 바랍니다.

1.Grid Control

Grid Control은 화면에 표형식으로 박스가 그려지는 기능을 가지고 있습니다. 엑셀이나 스프레드 쉬트처럼 가로와 세로 배열을 설정하고 이곳에 데이터를 넣고자 할때 자주사용하는 컨트롤입니다. 이컨트롤을 이용하여 프로그램을 작성하는 방법을 설명하겠습니다.

<1>프로그램 설치

AppWizard로 프로그램 프로젝트를 만들 때 Step 3에서 Active X controls를체크해 줌으로써 본 프로그램에서 Active X 컨트롤이이 가능해집니다.(Step3에서 자동적으로 Active X conrols에 체그가 되어 잇습니다.) 다음 어떤 OCX를 사용할 것인가는 Project 메뉴에서 Add To Project를 선택하고 Components and Controls 항목을 선택하면 그림 4-5-1과 같은 화면이 나옵니다. 그림 4-5-1에서 Registered ActiveX Controls 항목을 선택하면 그림 4-5-2와 같은 화면이 나타나면서 현재 등록되어 있는 Active X 리스트들이 화면에 나옵니다.

(그림 4-5-1)Components and Contorls Gallary

(4-5-2)현재 컴퓨터에 등록된 Active 컨트롤 리스트

예를 들어 Grid Control을 선택하게 되면 Grid Control을 컨트롤하는 소스인 CGridCtrl.h와 CGridCtrl.hpp가 선택되고 그 외 OCX용 폰트 컨트롤 클래스 COleFont와 이미지 관리 클래스 CPicture가 함께 프로젝트에 삽입됩니다.

(그림 4-5-3) Grid Control 클래스가 프로젝트에 설정되는 화면

여기서 중요한 것이 CGridCtrl 클래스입니다. 이 클래스 안에 public이라고 정의되고 연결된 함수 리스트 중 몇 가지를 본다면 다음과 같습니다.

CString GetText(); //현재 칼럼의 데이터를 얻는다.

void SetText(LPCTSTR); //현재 칼럼에 데이터를 넣는다.

short GetRows();//세로 열의 수를 얻느다.

void SetRows(short); //세로 열의 라인을 설정한다.

short GetCols(); //컬럼의 수를 얻는다.

void SetCols(short); //컬럼의 수를 설정한다.

short GetRow(); //현재 설정된 세로 열 번호를 얻는다.

void SetRow(short); //세로 열번호로 커서를 이동한다.

short GetCol(); //컬럼 번호를 얻는다.

void SetCol(short); //컬럼 번호로 이동한다.

그리드란 그림 4-5-4처럼 도표가 나오는 것을 말합니다.

(그림 4-5-4)Grid Control 실행 화면

CGridCtrl 클래스를 실행하면 나타나는데 위 도표에서 어떤 일을 할까요? 먼저 특정칸에 데이터를 넣고 싶겠지요? 그 다음 특정칸의 데이터를 받고 싶고요. 다음 특정칸으로 이동하고 싶을테고 특정칸에 마우스 버튼이 클릭되었는가를 알고 싶을테고요. 그럼 지금부터 탐정이 되어 봅시다. 만약 특정칸에 데이터를 받는 함수가 있다면 그 함수명이 무엇일지 한번 추측해 보세요.

GetText 또는 GetTextData가 아닐까요? 이런 비슷한 함수가 CGridCtrl 클래스에 존재하는가를 확인해 보는 거죠.

CString GetText();이라는 함수가 있지요. 그럼 이 함수가 텍스트를 받는 함수겠군요. 다음 데이터를 넣는 함수는 위에서 무엇일까요? void SetText(LPCTSTR);겠지요. 그럼 다음 것들도 추측해 보죠. short GetRows();는 무엇일까요? Row란 세로 열를 의미하죠. 결국 현재 위치의 세로로 몇 행인가를 알아보는 것이고 SetRows란 세로 몇 번에 위치하라는 이야기입니다.

이렇게 추측으로 함수를 알아내는 것입니다. OCX뿐만 아닙니다. 어떤 클래스가 있다면 도움말을 눌러서 클래스 멤버를 봅니다. 그 안에 여러 함수들이 나올 것입니다. 그 함수들과 옆에 써진 도큐먼트를 보고 □아! 이 클래스에서 이런 동작은 이 함수를 사용하면 되겠구나.□ 이렇게 생각할 수가 있는 것이죠. 혹시 영문이라 읽기 힘든 분들은 저처럼 추측하세요. 그리고 실행시켜 보세요. 그러면 알 수 있을 겁니다. 사실 그 많은 MFC 클래스와 함수를 어떻게 다 외웁니까? 다 도움말 보고 하는 거죠.

<2>리소스로 연결

OCX 파일이 등록되면 리소스에는 자동적으로 선택된 OCX를 설정하는 아이콘이

나타납니다. 만약 Grid Control을 선택하였다면 리소스 에디터에는      버튼이 나

옵니다. 이 버튼을 선택해서 대화상자에 설정을 하면 그림 4-5-3과 같은 형태가 나오죠.

자, 그럼 이것을 컨트롤할 때 어떻게 할까요?

(힌트 클래스는 CGridCtrl이고 DDX_Control ...)

대화상자에 대해서 전에 공부를 했다면 알 것입니다.

만일 Grid Control 리소스 ID가 IDM_GRID라고 한다면 헤더에

CGridCtrl m_grid;

다음 소스에

DDX_Control(pDX,IDM_GRID,m_grid)

라고 설정하면 됩니다. 그리고 m_grid에서 발생하는 이벤트는 클래스 위자드를 이용하여 함수를 만들고 칼럼 이동은 m_grid.SetRows(), 텍스트 받는 것은 m_grid.GetText()라는 함수를 사용하면 됩니다.

쉽게 보면 그냥 대화상자에서 Ctrl 클래스를 구동하는 것과 비슷하죠.

<3>Active X는 OLE Automation의 확장 형태이다.

지금까지 보면 CGridCtrl이란 클래스는 CListCtrl이나 CAnimateCtrl과 비슷하게 보입니다. 또한 구동 방법도 비슷합니다. 전장에서도 설명하였듯이 내부적으로는 큰차이가 있습니다. 클래스 소스의 일부분을 보겠습니다.

CString CGridCtrl::GetText()

{

CString result;

GetProperty(0x1, VT_BSTR, (void*)&result);

return result;

}

void CGridCtrl::SetText(LPCTSTR propVal)

{

SetProperty(0x1, VT_BSTR, propVal);

}

long CGridCtrl::GetRowHeight(short Index)

{

long result;

static BYTE parms[] =

VTS_I2;

InvokeHelper(0x1f, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, parms,

Index);

return result;

}

보통 함수는 GetProperty나 SetProperty 또는 InvokeHelper입니다. 그럼 이게 무엇일까요? GetProperty는 서버 프로그램에서 데이터를 받자는 말이고 SetProperty는 서버 프로그램 데이터를 넣겠다는 이야기입니다. InvokeHelper는 서버에게 특정한 동작을 수행하라는 이야기입니다.즉 InvokeHelper이란 바로 메소드를 의미합니다.

3개의 함수가 모두 메소드와 프로퍼티를 컨트롤 하는 것입니다.  결국 Automation의 기능을 확장한 형태가 되는 것입니다.

<4>어떤 ActiveX 가 있는가?

그림 4-5-2에서 보면 알 수 있듯이 많은 Active X 컨트롤이 있습니다. 그 중에서 몇 가지를 설명하겠습니다.

□AniButton Control : 애니메이션 버튼 컨트롤입니다. 움직이는 버튼을 설정할 때 사용합니다.

□Image List Control : 이미지를 리스트 형태로 출력해 주는 컨트롤입니다.

□Key State Control : 키 상태를 바꾸거나 정의하고 표시해 주는 컨트롤입니다.

□Microft Multimedia Controls : MCI를 이용하는 WAV, AVI 파일 등을 제어하는 컨트롤입니다.

□Micorft Comm Control : RS-232C 통신을 할 때 사용하는 컨트롤입니다.

<5>예제 Ex1011 프로그램

예제 Ex1011 프로그램은 OCX에서 Grid Control을 이용한 프로그램입니다. 메인뷰 클래스를 CFormView 클래스로 설정하여 화면에 그리드 컨트롤을 삽입시켰습니다. 화면에 Setting라는 버튼이 있는데 이 버튼을 클릭하면 가로와 세로에 칼럼 제목이 □가로..□□세로..□로 나타납니다.

마우스 버튼으로 특정 칼럼을 선택하면 화면에 현재 칼럼에 입력할 데이터를 설정하도록 하는 대화상자가 나타납니다. 그리고 수정한 데이터값이 그리드에 보여 주는 프로그램입니다. 그림 4-5-5가 본 프로그램의 실행 모습입니다.

(그림 4-5-5)Ex1011 프로그램 실행 모습

<6>ActiveX 설정과 이벤트 만들기

Project 메뉴에서 Add to Project 를 선택하고 Components and Controls을 선택한 다음 그림 4-5-1과 그림 4-5-2처럼 Grid Controls을 클릭하여 Grid Controls 클래스를 프로그램에 삽입합니다.

메인뷰와 연결된 자원(Resource)을 리소스 에디터를 이용하여 수정하여 Grid Controls을 그림 4-5-6처럼 보이도록 설정합니다. 다음 리소스 에디터에서 버튼을 하나 설정한 다음 버튼명을 □설정"으로 만듭니다. 버튼의 ID를 IDC_SETTING으로 설정합니다. Grid Controls은 IDC_GRID1로 설정합니다.

(그림 4-5-6) CEx1011View와 연결되는 자원 설정 화면

이제 CEx1011View 클래스에 IDC_GRID1과 연결될 멤버를 설정합니다.

ResourView 화면에 IDD_EX1011_FORM 즉 그림 4-5-6과 같은 화면에서 CTrl키를 누른 상태에서 마우스를 그리드 컨트롤에 클릭하면 그림 4-5-7과 같은 화면이 나타납니다. 이때 그림 4-5-7과 같이 Member variable name에 m_pGrid를 입력하고 Category를 Control로 Variable type CGridCtrl로 설정하면 됩니다.

(그림 4-5-7) 그리드 컨트롤 변수와 연결하기

이와 같이하면 Ex1011View.h 파일에 다음과 같이 설정되고

CGridCtrl m_pGrid;

CEx1011View.cpp에 다음과 같이 설정됩니다.

DDX_Control(pDX,IDC_GRID1,m_pGrid);

이렇게 함으로써  Grid Control과 Ex1011과의 연결이 끝났습니다. 이제 Setting 버튼을 클릭하면 그리드 칼럼 안에 글자를 기록할 수 있습니다. Setting 버튼을 눌렀을 때 발생하는 이벤트 함수를 클래스 위자드로 생성한 다음 다음과 같이 기록합니다.

char i;

char temp[20];

//가로 0

m_pGrid.SetCol(0);

//세로 0

m_pGrid.SetRow(0);

//Text란 글자를 넣음.

m_pGrid.SetText("Text");

//세로로 가면서 칼럼에 데이타 입력

for(i=1;i<10;i++)

{

m_pGrid.SetCol(i);

m_pGrid.SetRow(0);

sprintf(temp,"가로%d",i);

m_pGrid.SetText(temp);

}

//세로로 가면서 칼럼에 데이타 입력

for(i=1;i<10;i++)

{

m_pGrid.SetCol(0);

m_pGrid.SetRow(i);

sprintf(temp,"세로%d",i);

m_pGrid.SetText(temp);

}

위와 같이 함으로써 그리드 위 맨 윗줄에 □가로 1, 가로 2, 가로 3..□이라는 글자가 기록되고 세로로 첫줄에 □세로 1, 세로 2, 세로 3..□이라고 기록됩니다.

다음은 클래스 위자드를 이용하여 IDC_GRID1에서 발생되는 메세지 DblClick 이벤트가 발생되었을 때 생성되는 함수 OnDblClickGrid1()를 만든 다음 다음과 같이 설정해 줍니다.

//특정 칼럼을 마우스로 더블클릭했을 경우

void CEx1101View::OnDblClickGrid1()

{

int raw,col;

//가로 칼럼수를 구한다.

raw=m_pGrid.GetRow();

//세로 칼럼수를 구한다.

col=m_pGrid.GetCol();

//가로 칼럼이나 세로 칼럼이 0이면 빠져나간다.

if(raw==0 || col==0)

return;

CString szTemp;

//현재 텍스트를 받는다.

szTemp=m_pGrid.GetText();

//텍스트를 수정하는 대화상자를 설정하고

CModeData *pDlg= new CModeData(szTemp);

//대화상자를 실행하고 OK 버튼을 누르면 데이타를 설정한다.

if(pDlg->DoModal()==IDOK)

m_pGrid.SetText((LPSTR)pDlg->m_strData.operator const char*());

delete pDlg;

}

데이터를 수정하는 대화상자 작성법은 설명하지 않겠습니다. 여기까지 공부해왔다면 CModeData 대화상자를 만드는 방법은 알테니까요.

<7>프로그램 소스

다음은 Ex1011의 View 클래스 소스입니다.

(프로그램 소스)

// Ex1011View.h : interface of the CEx1011View class

//

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INCLUDES()

#include "gridctrl.h"

//}}AFX_INCLUDES

#if !defined(AFX_EX1011VIEW_H__8BF07365_F706_11D0_A7D7_0000E8D03CE2__INCLUDED_)

#define AFX_EX1011VIEW_H__8BF07365_F706_11D0_A7D7_0000E8D03CE2__INCLUDED_

#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000

class CEx1011View : public CFormView

{

protected: // create from serialization only

CEx1011View();

DECLARE_DYNCREATE(CEx1011View)

public:

//{{AFX_DATA(CEx1011View)

enum { IDD = IDD_EX1011_FORM };

CGridCtrl	m_pGrid;

//}}AFX_DATA

// Attributes

public:

CEx1011Doc* GetDocument();

// Operations

public:

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CEx1011View)

public:

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

protected:

virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);

virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);

virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

virtual void OnPrint(CDC* pDC, CPrintInfo*);

//}}AFX_VIRTUAL

// Implementation

public:

virtual ~CEx1011View();

#ifdef _DEBUG

virtual void AssertValid() const;

virtual void Dump(CDumpContext& dc) const;

#endif

protected:

// Generated message map functions

protected:

//{{AFX_MSG(CEx1011View)

afx_msg void OnSetting();

afx_msg void OnDblClickGrid1();

DECLARE_EVENTSINK_MAP()

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

#ifndef _DEBUG  // debug version in Ex1011View.cpp

inline CEx1011Doc* CEx1011View::GetDocument()

{ return (CEx1011Doc*)m_pDocument; }

#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}

// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_EX1011VIEW_H__8BF07365_F706_11D0_A7D7_0000E8D03CE2__INCLUDED_)

// Ex1011View.cpp : implementation of the CEx1011View class

//

#include "stdafx.h"

#include "Ex1011.h"

#include "Ex1011Doc.h"

#include "Ex1011View.h"

#include "ModeData.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CEx1011View

IMPLEMENT_DYNCREATE(CEx1011View, CFormView)

BEGIN_MESSAGE_MAP(CEx1011View, CFormView)

//{{AFX_MSG_MAP(CEx1011View)

ON_BN_CLICKED(IDC_SETTING, OnSetting)

//}}AFX_MSG_MAP

// Standard printing commands

ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CEx1011View construction/destruction

CEx1011View::CEx1011View()

: CFormView(CEx1011View::IDD)

{

//{{AFX_DATA_INIT(CEx1011View)

// NOTE: the ClassWizard will add member initialization here

//}}AFX_DATA_INIT

// TODO: add construction code here

}

CEx1011View::~CEx1011View()

{

}

void CEx1011View::DoDataExchange(CDataExchange* pDX)

{

CFormView::DoDataExchange(pDX);

//{{AFX_DATA_MAP(CEx1011View)

DDX_Control(pDX, IDC_GRID1, m_pGrid);

//}}AFX_DATA_MAP

}

BOOL CEx1011View::PreCreateWindow(CREATESTRUCT& cs)

{

// TODO: Modify the Window class or styles here by modifying

//  the CREATESTRUCT cs

return CFormView::PreCreateWindow(cs);

}

/////////////////////////////////////////////////////////////////////////////

// CEx1011View printing

BOOL CEx1011View::OnPreparePrinting(CPrintInfo* pInfo)

{

// default preparation

return DoPreparePrinting(pInfo);

}

void CEx1011View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

// TODO: add extra initialization before printing

}

void CEx1011View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

// TODO: add cleanup after printing

}

void CEx1011View::OnPrint(CDC* pDC, CPrintInfo*)

{

// TODO: add code to print the controls

}

/////////////////////////////////////////////////////////////////////////////

// CEx1011View diagnostics

#ifdef _DEBUG

void CEx1011View::AssertValid() const

{

CFormView::AssertValid();

}

void CEx1011View::Dump(CDumpContext& dc) const

{

CFormView::Dump(dc);

}

CEx1011Doc* CEx1011View::GetDocument() // non-debug version is inline

{

ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEx1011Doc)));

return (CEx1011Doc*)m_pDocument;

}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////

// CEx1011View message handlers

//가로 세로로 제목을 설정한다.

void CEx1011View::OnSetting()

{

char i;

char temp[20];

m_pGrid.SetCol(0);

m_pGrid.SetRow(0);

m_pGrid.SetText("Text");

for(i=1;i<10;i++)

{

m_pGrid.SetCol(i);

m_pGrid.SetRow(0);

sprintf(temp,"가로%d",i);

m_pGrid.SetText(temp);

}

for(i=1;i<10;i++)

{

m_pGrid.SetCol(0);

m_pGrid.SetRow(i);

sprintf(temp,"세로%d",i);

m_pGrid.SetText(temp);

}

}

BEGIN_EVENTSINK_MAP(CEx1011View, CFormView)

//{{AFX_EVENTSINK_MAP(CEx1011View)

ON_EVENT(CEx1011View, IDC_GRID1, -601 /* DblClick */, OnDblClickGrid1, VTS_NONE)

//}}AFX_EVENTSINK_MAP

END_EVENTSINK_MAP()

//그리트 컨트롤의 특정 컬럼을 선택했을때

//입력 대화상자를 나타내고 데이터가 입력되면

//이 데이터를  그리드에 넣는다.

void CEx1011View::OnDblClickGrid1()

{

int col=m_pGrid.GetCol();

int row=m_pGrid.GetRow();

if(col==0 || row==0)

return;

CString szTemp;

szTemp=m_pGrid.GetText();

int num=atoi(szTemp);

CModeData *pDlg = new CModeData(num);

if(pDlg->DoModal()==IDOK)

{

char temp[40];

sprintf(temp,"%d",pDlg->m_nData);

m_pGrid.SetText(temp);

}

delete pDlg;

}

(프로그램 소스끝)

2. BMP,JPG,GIF  출력 예제 Ex1012 프로그램

장치 독립적인 이미지 파일은 일반적으로  BMP를 사용합니다.. 그외 이미지 파일로써 많이 사용하는 파일들이 JPG,GIF 등등 여러 이미지 파일들이 잇습니다. 사실 JPG나 GIF파일을 화면에 출력하기 위해서 하는 작업들은 매우 복잡합니다. GIF는 그렇다 하더라도 JPG는 매우 복잡한 구조로 되어있고 DCT라는 알고리듬을 알아야만 이 이미지 파일을 출력할수 있습니다. 프로그램을 제작하는데 만일 이런 이미지 파일을 단순히 출력만 할 필요가 있을 경우 이미지 구조를 모르고 있거나 또는 영상에 대한 기본 알고리듬이 없는 프로그래머에게는 문제가 되는 부분입니다. 이럴 경우 Active X만 알고 있다면 이런 이미지도 바로 출력을 할 수가 있습니다. Ex1012는 ActiveX 컨트롤 중에서 Microsoft ActiveX Image Control 1.0 을 사용하여 화면에 JPG,GIF같은 복잡한 형태의 이미지를 화면에 출력하는 방법을 설명하겠습니다. ActiveX 의 단점은 바로 함수 설명이 부족하다는 것입니다. 많은 OCX들이 있으나 이것을 사용하는 도움말 기능이 많이 없습니다. 결국 프로그래머는 함수만 보고 이것이 어떤 파일인가 추측을 해갈 수밖에 없습니다.

Ex1012 프로그램을 한 번 추측으로 만들어 보겠습니다.

Ex1012는 SDI 형태이고 CEx1012View는 FormView를 상속받아서 만듭니다. 이렇게 만들면 쉽게 ActiveX를 결합하고 그 기능을 알수 있으니까요.

Project 항목에서 Add To Project항목을 선택하고 Components and Controls를 선택하여 Components and Controls Gallery 가 나오면 Registered ActiveX Controls를 선택하여 현재 등록되어 잇는 ActiveX의 리스트들을 봅니다. 그림 4-5-8 과 같은 화면이 나오고  Microsoft ActiveX Image Control 1.0  이란 항목이 있습니다. 여기에서 □Image Control이라면 그림 파일을 보여주는 컨트롤 일 것 같다!□ 라는 추측을 한 번해보고 □그래 한 번 삽입해보자 결정한후 Insert 버튼을 클릭합니다.

(그림 4-5-8) Microsoft ActiveX Image Control 1.0 삽입

이와 같이 하였더니 disimage.cpp와 disimage.h가 만들어 졌습니다. 여기에서 함수를 보기 위해서 disimage.h를 열어 보니 다음과 같았습니다.

#if !defined(AFX_DISIMAGE_H__8BF0739B_F706_11D0_A7D7_0000E8D03CE2__INCLUDED_)

#define AFX_DISIMAGE_H__8BF0739B_F706_11D0_A7D7_0000E8D03CE2__INCLUDED_

#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000

// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++

// NOTE: Do not modify the contents of this file.  If this class is regenerated by

//  Microsoft Visual C++, your modifications will be overwritten.

/////////////////////////////////////////////////////////////////////////////

// CDISImage wrapper class

class CDISImage : public CWnd

{

protected:

DECLARE_DYNCREATE(CDISImage)

public:

CLSID const& GetClsid()

{

static CLSID const clsid

= { 0xd4a97620, 0x8e8f, 0x11cf, { 0x93, 0xcd, 0x0, 0xaa, 0x0, 0xc0, 0x8f, 0xdf } };

return clsid;

}

virtual BOOL Create(LPCTSTR lpszClassName,

LPCTSTR lpszWindowName, DWORD dwStyle,

const RECT& rect,

CWnd* pParentWnd, UINT nID,

CCreateContext* pContext = NULL)

{ return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID); }

BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle,

const RECT& rect, CWnd* pParentWnd, UINT nID,

CFile* pPersist = NULL, BOOL bStorage = FALSE,

BSTR bstrLicKey = NULL)

{ return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID,

pPersist, bStorage, bstrLicKey); }

// Attributes

public:

// Operations

public:

CString GetPicturePath();

void SetPicturePath(LPCTSTR lpszNewValue);

};

//{{AFX_INSERT_LOCATION}}

// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_DISIMAGE_H__8BF0739B_F706_11D0_A7D7_0000E8D03CE2__INCLUDED_)

여기에서 public안에 Create함수가 있고 그리고 GetPicturePath()함수와 SetPicturePath()함수가 있습니다. Create란 분명히 이미지를 출력하는 어떤 영역을 만들고자 하는 함수일것입니다. 만일 FormView에 ResourceView를 이용하여 이 컨트롤을 설정하면 Create함수는 자동적으로 설정이 될것이고 나머지 두함수를 추측해 봅니다. GetPicturePath 란 의미를 보면 □그림의 경로를 얻는다□ 라는 뜻일것이고 SetPicturePath()함수란 □그림의 경로를 설정한다□ 라는 의미일것입니다. 그렇다면 □아하! SetPicturePath()함수를 이용하여 그림 파일의 경로를 설정하면 되겠구나□ 이렇게 추측을 하는 것이지요. 이제 CEx1012View와 연결된 자원 IDD_EX1012_FORM 에 방금 등록한 Microsoft ActiveX Image Control 1.0 삽입 합니다. 삽입한 형태가 바로 그림 4-5-9 입니다.

(그림 4-5-9)IDD_EX1012_FORM 설정 형태

이제 이 Image 컨트롤을 CEx1012View의 멤버로 그림 4-5-10과 같이 연결합니다.

(그림 4-5-10)CEx1012View와 연결

이렇게 함으로써 CDISImage컨트롤은 m_pImage와 연결되었습니다.

CEx1012View에서 File Open메뉴항목을 선택하였을 때 실행하는 함수

void CEx1012View::OnFileOpen() 을 설정하고 다음과 같이 코딩합니다.

void CEx1012View::OnFileOpen()

{

//파일 대화상자를 만든다.

char Filter[]="All format(*.*)|*.*|Gif format(*.gif)|*.gif|JPG format(*.jpg)|*.jpg|bmp format(*.bmp)|*.bmp|";

CFileDialog fileDlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,Filter);

if(fileDlg.DoModal()==IDOK)

{

//선택된 파일명을 얻고

CString data=fileDlg.GetPathName();

//이것을 ActiveX 컨트롤 클래스에 설정한다.

m_pImage.SetPicturePath(data);

//화면을 갱신한다.

Invalidate(TRUE);

}

}

즉 이미지 파일의 경로 파일 대화상자를 통해서얻고 위에서 본 SetPicturePath함수를 이용하여 이 파일명을 넘겨주는 것입니다. 그렇게 한후 화면에 나타날수도

있다고 간주하여 Invalidate(TRUE); 함수를 작성합니다.

드라마틱 하게 이와 같이 하여 프로그램을 작성하고 컴파일 한후에 실행을 하였더니 그림 4-5-11과 같이 화면에 그림이 나타났습니다.

(그림 4-5-11) Ex1012 실행 결과

ActiveX 컨트롤 를 이용할 때 사용설명서가 없는 고로 필자는 이방법을 많이 사용합니다. 상업용 ActiveX는 설명서를 함께 포함하지만 공개용이나 또는 마이크로 소프트사에서 Visual C++ 과 함께 동봉된 ActiveX는 이런 설명서가 다소 빈약합니다. (사실 ActiveX컨트롤 사용법만 설명하여도 책한권을 될겁니다...)

결국 우리는 우리가 필요한 부분을 위와 같은 형태로 추리해 나가면서 사용할수 밖에 없다고 봅니다. 또하나의 방법은 ActiveX Control Test Container를 사용하면 됩니다. 이 툴은 메뉴의 Tools에서 선택하시면 됩니다.

<1>프로그램 소스

다음은 Ex1012의 View클래스 부분 소스입니다.

(프로그램 소스)

// Ex1012View.h : interface of the CEx1012View class

//

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INCLUDES()

#include "disimage.h"

//}}AFX_INCLUDES

#if !defined(AFX_EX1012VIEW_H__8BF07393_F706_11D0_A7D7_0000E8D03CE2__INCLUDED_)

#define AFX_EX1012VIEW_H__8BF07393_F706_11D0_A7D7_0000E8D03CE2__INCLUDED_

#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000

class CEx1012View : public CFormView

{

protected: // create from serialization only

CEx1012View();

DECLARE_DYNCREATE(CEx1012View)

public:

//{{AFX_DATA(CEx1012View)

enum { IDD = IDD_EX1012_FORM };

CDISImage	m_pImage;

//}}AFX_DATA

// Attributes

public:

CEx1012Doc* GetDocument();

// Operations

public:

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CEx1012View)

public:

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

protected:

virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);

virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);

virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

virtual void OnPrint(CDC* pDC, CPrintInfo*);

//}}AFX_VIRTUAL

// Implementation

public:

virtual ~CEx1012View();

#ifdef _DEBUG

virtual void AssertValid() const;

virtual void Dump(CDumpContext& dc) const;

#endif

protected:

// Generated message map functions

protected:

//{{AFX_MSG(CEx1012View)

afx_msg void OnFileOpen();

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

#ifndef _DEBUG  // debug version in Ex1012View.cpp

inline CEx1012Doc* CEx1012View::GetDocument()

{ return (CEx1012Doc*)m_pDocument; }

#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}

// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_EX1012VIEW_H__8BF07393_F706_11D0_A7D7_0000E8D03CE2__INCLUDED_)

// Ex1012View.cpp : implementation of the CEx1012View class

//

#include "stdafx.h"

#include "Ex1012.h"

#include "Ex1012Doc.h"

#include "Ex1012View.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CEx1012View

IMPLEMENT_DYNCREATE(CEx1012View, CFormView)

BEGIN_MESSAGE_MAP(CEx1012View, CFormView)

//{{AFX_MSG_MAP(CEx1012View)

ON_COMMAND(ID_FILE_OPEN, OnFileOpen)

//}}AFX_MSG_MAP

// Standard printing commands

ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CEx1012View construction/destruction

CEx1012View::CEx1012View()

: CFormView(CEx1012View::IDD)

{

//{{AFX_DATA_INIT(CEx1012View)

// NOTE: the ClassWizard will add member initialization here

//}}AFX_DATA_INIT

// TODO: add construction code here

}

CEx1012View::~CEx1012View()

{

}

void CEx1012View::DoDataExchange(CDataExchange* pDX)

{

CFormView::DoDataExchange(pDX);

//{{AFX_DATA_MAP(CEx1012View)

DDX_Control(pDX, IDC_IMAGE1, m_pImage);

//}}AFX_DATA_MAP

}

BOOL CEx1012View::PreCreateWindow(CREATESTRUCT& cs)

{

// TODO: Modify the Window class or styles here by modifying

//  the CREATESTRUCT cs

return CFormView::PreCreateWindow(cs);

}

/////////////////////////////////////////////////////////////////////////////

// CEx1012View printing

BOOL CEx1012View::OnPreparePrinting(CPrintInfo* pInfo)

{

// default preparation

return DoPreparePrinting(pInfo);

}

void CEx1012View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

// TODO: add extra initialization before printing

}

void CEx1012View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

// TODO: add cleanup after printing

}

void CEx1012View::OnPrint(CDC* pDC, CPrintInfo*)

{

// TODO: add code to print the controls

}

/////////////////////////////////////////////////////////////////////////////

// CEx1012View diagnostics

#ifdef _DEBUG

void CEx1012View::AssertValid() const

{

CFormView::AssertValid();

}

void CEx1012View::Dump(CDumpContext& dc) const

{

CFormView::Dump(dc);

}

CEx1012Doc* CEx1012View::GetDocument() // non-debug version is inline

{

ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEx1012Doc)));

return (CEx1012Doc*)m_pDocument;

}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////

// CEx1012View message handlers

void CEx1012View::OnFileOpen()

{

//파일 대화상자를 만든다.

char Filter[]="All format(*.*)|*.*|Gif format(*.gif)|*.gif|JPG format(*.jpg)|*.jpg|bmp format(*.bmp)|*.bmp|";

CFileDialog fileDlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,Filter);

if(fileDlg.DoModal()==IDOK)

{

//선택된 파일명을 얻고

CString data=fileDlg.GetPathName();

//이것을 ActiveX 컨트롤 클래스에 설정한다.

m_pImage.SetPicturePath(data);

//화면을 갱신한다.

Invalidate(TRUE);

}

}

(프로그램 소스끝)