COM(Component Object Model) 개념잡기 MFC。

1. COM

1.1 COM의 개념

COM(Component Object Model)이란 한마디로 어떤 프로그램이나 시스템을 이루는 컴포넌트들이 상호 통신할 수 있도록 하는 메커니즘이라고 할 수 있다. 여기서 컴포넌트란 .ocx, .dll, .exe를 확장자로 갖는 실행 가능한 바이너리 화일이다. 물론 COM은 이외에도 다음과 같은 특성 및 기능을 갖는다.

  • 언어 독립성(Language Independence)

이 말은 다른 개발 도구(VB, VJ++, VC++, Delphi 등)를 사용하여 작성한 컴포넌트들이 상호 통신할 수 있다는 것을 의미한다. 다시 말해 VC++로 컴포넌트를 만들고, VB나 Delphi 등 COM을 지원하는 툴로 만든 프로그램(이 프로그램을 COM 컴포넌트의 클라이언트를 하자)에서 컴포넌트를 마치 동일한 개발 도구로 생성한 프로그램 모듈처럼 사용할 수 있다는 것을 의미한다. 이 기능은 개발자들에게 많은 편의를 제공한다.

  • Binary Standard

이 말은 VC++로 작성된 COM 컴포넌트를 VB 등에서 사용하기 위해 VC++의 소스가 전혀 필요없다는 것을 의미한다. VB 개발자는 VC++로 작성된 .exe, .ocx, .dll 등과 같은 binary만 있으면 이 컴포넌트를 사용할 수 있다.

  • Version Control

COM에 기반하여 작성한 컴포넌트는 하위 호환성 및 상위 호환성을 제공한다. 현재 사용되고 있는 모듈에 새로운 기능이 요구된다면 COM에서는 쉽게 새로운 기능을 기존의 모듈에 추가할 수 있다. 새로운 기능을 포함하는 모듈은 새로운 기능을 필요로하는 클라이언트들에게는 새로운 기능을 이전 기능을 필요로 하는 클라이언트들에게는 이전 기능을 동시에 제공할 수 있다.

  • Location Transparency

이 말은 컴포넌트가 물리적 위치에 관계없이 다른 컴포넌트 혹은 컴포넌트 클라이언트에 의해 사용될 수 있다는 것을 의미한다. COM 컴포넌트는 In-process, out-of-process, out-of-machine(네트워크를 통한 리포트 머신)에서 실행될 수 있다.

In-process 형태로 수행되는 컴포넌트는 .dll, .ocx 형태로 생성된다. 이 컴포넌트들은 컴포넌트 클라이언트의 메모리 영역으로 로드되어 사용된다.

out-of-process 형태로 수행되는 컴포넌트는 .exe 형태로 생성된다. 이 부류의 컴포넌트는 클라이언트와 동일한 머신에서 수행된다.

out-of-machine 형태로 수행되는 컴포넌트도 .exe 형태로 생성된다. 이 컴포넌트는 클라이언트가 수행되는 머신과 네트워크를 통해 연결된 다른 머신에서 수행된다.

 

간단하게 COM의 개념에 대해 설명했다. 한마디로 COM은 서로 다른 프로그램들이 서로 통신할 수 있도록 하는 Specification이라고 할 수 있다. 이러한 기능 이외에도 COM은 재사용성, 객체 지향 등 많은 특징 및 기능을 가지고 있다.

 

1.2 Interface

인터페이스란 한마디로 COM이 제공하는 기능이라고 할 수 있다. 실제로 인터페이스는 관련있는 함수들의 집합을 정의하는 수단이다. COM 컴포넌트는 하나 이상의 인터페이스를 제공해야한다.

COM은 언어(개발도구)에 독립적이라고 하였다. 이것은 바이너리 화일(.exe, .dll)로 배포되는 COM 컴포넌트가 자신이 제공하는 기능을 COM 객체를 사용하려고 하는 클라이언트 프로그램에게 알려줄 수 있는 방법이 있어야 한다는 것을 의미한다.

이처럼 바이너리로 배포되는 COM 객체가 제공하는 기능을 기술한 것이 인터페이스이다. 인터페이스는 COM 컴포넌트가 무슨("What") 기능을 제공하는지를 알려준다. 하지만 인터페이스를 통해서 COM 컴포넌트가 어떻게("How") COM 컴포넌트의 사용자가 원하는 기능을 제공하는지는 알 수 없다. 사실 인터페이스에 대해 설명한다면 하면 너무도 길고, 지루한 이야기가 될 것이다. 따라서 그런 지루한 이야기는 관심 있는 분들만 찾아서 보시기 바란다.

"Inside COM"이나 Microsoft Web Site의 COM Specification을 보면 인터페이스에 대해 자세히 알 수 있습니다. 만일 제가 시간이 나면 인터페이스에 대한 문제는 다시 자세히 다루기로 하겠습니다.

 

2. 첫번째 COM 예제

첫 예제로 사원에 대한 정보를 네트워크를 통해 주고 받는 COM 컴포넌트와 클라이언트를 작성해 보도록 하자.

2.1 COM 컴포넌트 작성

먼저 VC++ 5.0 이상을 이용하여 COM 객체를 만들어 보자. 다음의 절차를 따른다.

  1. File/New/Project에서 "ATL COM AppWizard"를 선택하고 "Project Name"에 Employee라고 입력한다.
  2. "Server Type"에서 "Executable(EXE)"를 선택한다.
  3. "ClassView"에서 "employee classes"를 오른쪽 마우스 버튼으로 선택하고 "New ATL Object"를 선택한다.
  4. "ATL Object Wizard"에서 "objects/Simple Object"를 선택하고 "Next" 버튼을 클릭한다.
  5. "ATL Object Wizard 등록 정보" 대화상자에서 "Short Name"에 "EmpObj"라고 입력한다. 그러면 "CoClass", "Class", "Interface" 등은 자동으로 채워진다. "Attributes" 탭을 클릭한다.
  6. "확인" 버튼을 클릭한다.
  7. 클래스 뷰를 확장시켜서 "CEmpObj"라는 클래스와 "IEmpObj"라는 인터페이스가 생성된 것을 확인한다.
  8. "IEmpObj" 인터페이스를 오른쪽 마우스 버튼으로 클릭하고 "Add Property"를 클릭한다. 리스트 박스로 나타나는 프로퍼티 타입에는 BSTR을 선택하고, 프로퍼티 이름은 Name이라고 입력한 후 "OK" 버튼을 클릭한다.
  9. CEmpObj에 Name 프로퍼티를 저장할 멤버 변수로 char m_szName[40]을 추가한다.
  10. CEmpObj::get_Name의 구현 부분에 다음 코드를 추가한다.

    // TODO: Add your implementation code here
        USES_CONVERSION;
        *pVal = SysAllocString(A2OLE(m_szName));
        return S_OK;
  11. CEmpObj::set_Name의 구현 부분에 다음 코드를 추가한다.

    // TODO: Add your implementation code here    
        USES_CONVERSION;
        strcpy(m_szName, OLE2A(newVal));
        return S_OK;
  12. 서버 코드가 완성되었다. 빌드 한다.

2.2 COM Client 작성

  1. File/New/Projects에서 MFC AppWizard(exe)를 선택하고 프로젝트 이름은 "EmpClient"로 한다.
  2. MFC AppWizard - Step 1 of 4에서 "Dialog based"로 프로그램 유형을 선택한다.
  3. MFC AppWizard - Step 2 of 4에서 "Automation"을 선택하고, "ActiveX Controls" 선택을 해제한다.
  4. "Finish" 버튼을 클릭한다.
  5. stdafx.h 화일에 다음을 추가한다.

    #import "C:\temp\COMSample\COMObject\employee.tlb" no_namespace named_guids
  6. CEmpClientDlg에 IEmpObjPtr 타입 멤버 변수로 m_pEmp를 추가한다.
  7. CEmpClientDlg::OnInitDialog에 다음 코드를 추가한다.

    HRESULT hr = m_pEmp.CreateInstance(__uuidof(EmpObj));
    if(FAILED(hr))
        AfxMessageBox("객체 생성에 실패했습니다 !!");
  8. COM 객체를 사용할 때 다음과 같은 문법을 사용한다.

    8.1 프로퍼티를 읽을 때
        CString strName = (LPCTSTR)m_pEmp->Name;

    8.2 프로퍼티에 값을 셋팅할 때
        m_pEmp->Name = strName.AllocSysString();

    8.3 객체의 메소드를 호출할 때
        hr = m_pEmp->ComputeSalary(nWorkHour);

    8.4 객체 사용을 마치고 객체를 소멸시킬 때
        m_pEmp = 0;





CTreeCtrl::ModifyStyle시 GDI개체 증가 되는 문제 MFC。

ModifyStyle로 TVS_CHECKBOXES 를 사용한다고 체크하는 경우,
ImageList가 생성되어 4개의 GDI Object를 생성한다.
이는 사용자가 반드시 사용후에 삭제해 주어야 한다.

Ex>
CImageList* pImgList = NULL;

pImgList = m_ProdTypeTree.GetImageList(TVSIL_STATE);
if( pImgList )
pImgList->DeleteImageList();
------------------------------------------------------------------------------------------------------------------------

I don't have a GDI leak detector but testing with task manager, I get:
 
// Adds 4 GDI Objects
m_TreeCtl.ModifyStyle(0, TVS_CHECKBOXES);
...
...
// Removes 4 GDI Objects
HIMAGELIST hImgList = TreeView_SetImageList(m_TreeCtl.GetSafeHwnd(), NULL, TVSIL_STATE);
if (hImgList)
ImageList_Destroy(hImgList);
 
I can't find any info documenting a leak.

------------------------------------------------------------------------------------------------------------------------
ConstantDescription
TVS_CHECKBOXES

Version 4.70. Enables check boxes for items in a tree-view control. A check box is displayed only if an image is associated with the item. When set to this style, the control effectively uses DrawFrameControl to create and set a state image list containing two images. State image 1 is the unchecked box and state image 2 is the checked box. Setting the state image to zero removes the check box altogether. For more information, see Working with state image indexes.

Version 5.80. Displays a check box even if no image is associated with the item.

Once a tree-view control is created with this style, the style cannot be removed. Instead, you must destroy the control and create a new one in its place. Destroying the tree-view control does not destroy the check box state image list. You must destroy it explicitly. Get the handle to the state image list by sending the tree-view control aTVM_GETIMAGELIST message. Then destroy the image list with ImageList_Destroy.

If you want to use this style, you must set the TVS_CHECKBOXES style withSetWindowLong after you create the treeview control, and before you populate the tree. Otherwise, the checkboxes might appear unchecked, depending on timing issues.

------------------------------------------------------------------------------------------------------------------------

쓸만한 VBScript 모음 MFC。

- 수학 관련 함수

1. Abs 함수 : 인자로 전달된 값에 대한 절대값을 리턴하는 함수
   ex> Abs(number)

2. Atn 함수 : 인자로 전달된 숫자의 아크 탄젠트 값을 리턴
   ex> Atn(number)

3. Cos 함수 : 인자로 전달된 숫자의 코사인 값을 리턴
   ex> Cos(number)

4. Sgn 함수 : 지정된 표현식의 부호를 리턴
   ex> Sng(number)

5. Sin 함수 : 지정된 표현식의 사인 값을 리턴
   ex> Sin(number)

6. Sqr 함수 : 지정된 표현식의 제곱근을 리턴
   ex> Sqr(number)
         Dim num
         num = 4
         response.write Sqr(num)
   결과> 2

7. Tan 함수 : 지정된 값의 탄젠트 값을 리턴
   ex> Tan(number)

- 변환 함수

1. CBool 함수 : 인자로 전달된 값을 Boolean 형으로 변환. 값이 Boolean으로 인식될 수
                      없으면 런타임 오류가 발생
   ex> CBool(expression)
         Dim isBool, siNotBool
         isBool = 1: isNotBool = 0
         response.write CBool(isBool)
         response.write CBool(isBool)
   결과> True
            False

2. CByte 함수 : 인자로 전달된 값을 Byte 형식으로 변환
   ex> CByte(expression)

3. CCur 함수 : 인자로 전달된 값을 Currency 형식으로 변환
   ex> CCur(expression)

4. CDate 함수 : 인자로 전달된 값을 DateTime 형식으로 변환합니다.
   ex> CDate(expression)
         Dim date
         date = "2008-01-01"
         response.write CDate(date)
   결과> 2008-01-01

5. CDbl 함수 : 인자로 전달된 값을 Double 형으로 변환
   ex> CDbl(expression)

6. CInt 함수 : 인자로 전달된 값을 Integer형으로 변환
   ex> CInt(expression)

7. CLng 함수 : 인자로 전달된 값을 Long형으로 변환
   ex> CLng(expression)

8. CSng 함수 : 인자로 전달된 값을 Single 형으로 변환
   ex> CSng(expression)

9. Cstr 함수 : 인자로 전달된 값을 String 형으로 변환
   ex> Cstr(expression)

10. Fix 함수 : 지정된 숫자보다 작은 정수 중 가장 큰 정수를 리턴
   ex> Fix(number)

11. Int 함수 : 지정된 숫자보다 크거나 작은 정수 중 가장 작은 값이나 큰 값을 리턴
   ex> Int(number)

12. Hex 함수 : 인자로 전달된 값을 16진수로 변환
   ex> Hex(number)

13. Oct 함수 : 인자로 전달된 값을 8진수로 변환
   ex> Oct(number)

- 문자열 함수

1. Asc 함수 : 지정된 문자에 해당하는 ASCII 코드를 리턴
   ex> Asc(string)

2. Chr 함수 : 지정된 숫자에 해당하는 ASCII 문자를 리턴
   ex> Chr(charcode)

3. Filter 함수 : 지정된 문자열 배열에서 지정된 필터가 적용되는 배열의 일부 원소를 리턴
   ex> Filter(inputStrings, Value[, Include [, Compare]])
         Dim myArray, myNewArray
         myArray(0) = "박찬호"
         myArray(1) = "유재석"
         myArray(2) = "강호동"
         myNewArray = Filter(myArray, "호")
         response.write myNewArray(0)
         response.write myNewArray(1)
   결과> 박찬호
            강호동

4. InStr 함수 : 지정된 문자열에서 특정 문자열이 나타나는 위치를 문자열의 처음부터 검색
   ex> InStr([start, ] string1, string2, [ compare])
         Dim str
         str = "Microsoft Active Server Pages"
         response.write InStr(str, "e")
   결과> 16

5. InStrRev 함수 : 지정된 문자열에서 특정 문자열이 나타나는 위치를 문자열의 
                         마지막부터 검색
   ex> InStrRev([start, ] string1, string2, [ compare])
         Dim str
         str = "Microsoft Active Server Pages"
         response.write InstrRev(str, "a")
   결과> 26

6. Join 함수 : 지정된 문자열 배열을 하나의 문자열로 결합
   ex> Join(list [, delimiter])
         Dim strArray(3)
         strArray(0) = "Microsoft"
         strArray(1) = "Active"
         strArray(2) = "Server"
         strArray(3) = "Pages"
         response.write Join(strArray, " ")
   결과> Microsoft Active Server Pages

7. LCase 함수 : 지정된 문자열을 모두 소문자로 변환하여 리턴
   ex> LCase(string)

8. Left 함수 : 문자열의 왼쪽으로부터 지정된 개수만큼의 문자열을 리턴
   ex> Left(string, length)

9. Len 함수 : 지정된 문자열의 길이를 리턴
   ex> Len(string)

10. LTrim 함수 : 지정된 문자열에서 문자열 왼쪽의 공백을 제거
   ex> LTrim(string)

11. Mid 함수 : 지정된 문자열에서 특정 위치의 문자열을 리턴
   ex> Mid(string, start [, length])
         Dim str
         str = "Microsoft Active Server Pages"
         response.write Mid(str, 5, 10)
   결과> soft Activ

12. Replace 함수 : 지정된 문자열에서 특정 문자열을 변환
   ex> Replace(expression, find, replacewith [,start [,count [, compare]]])
         Dim str
         str = "Microsoft Active Server Pages"
         response.write Replace(str, e, E)
   결과> Microsoft ActivE SErvEr PagEs

13. Right 함수 : 지정된 문자열에서 오른쪽으로부터 지정된 길이만큼의 문자열을 리턴
   ex> Right(String, length)

14. RTrim 함수 : 지정된 문자열의 우측에 나타나는 공백을 제거
   ex> RTrim(string)

15. Space 함수 : 지정된 개수만큼의 공백을 리턴
   ex> Space(number)
         Dim str, str2
         str = "Microsoft"
         str2 = "Active Server Pages"
         response.write str & Space(5) & str2
   결과> Microsoft     Active Server Pages

16. Split 함수 : 지정된 문자열을 문자열 배열로 나눔
   ex> Split(expression [, delimiter [, count [, compare]]])
         Dim str, strArray
         str = "Microsoft Active Server Pages"
         strArray = Split(str, " ")
         response.write strArray(2)
   결과> Server

17. Strcomp 함수 : 지정된 두 문자열을 비교. 두 문자열이 같으면 0, 첫번째 문자열이 작으면
                           -1, 두번째 문자열이 작으면 1을 리턴
   ex> StrComp(string1, string2 [, compare])
         Dim str, str2
         str = "Microsoft"
         str2 = "microsoft"
         response.write StrComp(str, str2)
   결과> -1

18. String 함수 : 지정된 개수 만큼의 문자열을 반복하여 리턴
   ex> String(number, character)
         response.write String(10, "*")
   결과> **********

19. StrReverse 함수 : 지정된 문자열을 뒤집어서 출력
   ex> StrReverse(string)

20. Trim 함수 : 지정된 문자열의 좌우측 공백을 모두 제거
   ex> Trim(string)

21. UCase 함수 : 지정된 문자열을 모두 대문자로 변환
   ex> UCase(string)

- 날짜 및 시간 함수

1. Date 함수 : 현재 시스템의 날짜를 리턴
   ex> Date

2. DateAdd 함수 : 지정된 날짜에 지정된 간격의 시간을 더한 날짜를 리턴
   ex> DateAdd(interval, number, date)
         yyyy     : 년
         q         : 분기
         m         : 월
         y          : 일(1년 기준)
         d          : 일
         w         : 요일
         ww       : 주(일년 기준)
         h          : 시
         n          : 분
         s          : 초
         
         Dim myDate
         myDate = "2008-01-01"
         response.write DateAdd("d", 5, myDate)

3. DateDiff 함수 : 두 날짜 사이의 간격을 리턴
   ex> DateDiff(interval, date1, date2 [, firstDayOfWeek [, firstWeekOfYear]])
         Dim date1, date2
         date1 = "2008-01-01"
         date2 = "2008-01-03"
         response.write DateDiff("d", date1, date2)
         response.write DateDiff("d", date1, date2)
   결과> 2, -2

4. DatePart 함수 : 지정된 날짜에서 지정된 부분을 리턴
   ex> DatePart(interval, date [, firstDayOfWeek [, firstWeekOfYear]])
         Dim myDate
         myDate = "2008-01-15"
         response.write DatePart("d", myDate)
   결과> 15

5. DateSerial 함수 : 지정된 년, 월, 일을 이용하여 DateTime 형을 리턴
   ex> DateSerial(year, month, day)
         response.write DateSerial("2008", "1", "1")
   결과> 2008-01-01

6. DateValue 함수 : 지정된 날짜 및 시간 중 날짜 부분을 리턴
   ex> DateValue(date)

7. Day 함수 : 날짜 및 시간 데이터에서 일을 리턴
   ex> Day(date)

8. Hour 함수 : 날짜 및 시간 데이터에서 시간을 리턴
   ex> Hour(date)

9. Minute 함수 : 지정된 날짜 및 시간 데이터에서 분을 리턴
   ex> Minute(time)

10. Month 함수 : 지정된 날짜에서 월을 리턴
   ex> Month(date)

11. MonthName 함수 : 지정된 숫자에 해당하는 월의 이름을 가져옵니다.
   ex> MonthName(month [, abbreviate])
         response.wrkte MonthName(1, False)

12. Now 함수 : 시스템의 현재 날짜 및 시간 데이터를 리턴
   ex> Now

13. Time 함수 : 시스템의 현재 시간을 리턴
   ex> Time

14. Timer 함수 : 자정부터 현재 시간까지의 시간 간격을 초 단위로 리턴
   ex> Timer

15. TimeSerial 함수 : 지정된 숫자를 이용하여 시간 데이터를 생성
   ex> TimeSerial(hour, minute, second)

16. TimeValue 함수 : 지정된 표현식을 시간 데이터로 변환
   ex> TimeValue(time)

17. WeekDay 함수 : 지정된 날짜의 요일을 숫자로 출력합니다.
   ex> WeekDay(date [, firstdayofweek])
         Dim date1
         date1 = "2008-01-01"
         response.write WeekDay(date1)
   결과> 3

18. WeekdayName 함수 : 지정된 WeekDay 값이 표현하는 요일의 이름을 가져옴
   ex> Weekdayname(weekday, abbreviate, firstdayofweek)

19. Year 함수 : 지정된 날짜에서 년을 리턴
   ex> Year(date)

- 형식 지정 함수

1. FormatCurrency 함수 : Currency 하위 데이터 형의 출력에 대한 형식을 지정
   ex> Dim num1
         num1 = 123456
         response.write FormatCurrency(num1)
   결과 > \123,456

2. FormateDateTime 함수 : 날짜 및 시간 데이터의 출력 형식을 결정하는 함수
   ex> FormatDateTime(Date [, NamedFormat])

3. FormatNumber 함수 : 숫자형 데이터의 출력 형식을 결정
   ex> Dim num1
         num1 = 123456
         response.write FormatNumber(num1)
   결과> 123,456,00

4. FormatPercent 함수 : 지정된 표현식을 100으로 나눈 퍼센트 형식으로 출력
   ex> Dim num1
         num1 = 0.9
         response.write FormatPercent(num1)
   결과> 90.00%

- 기타 함수

1. Array 함수 : 괄호에 전달된 인자의 수만큼의 크기를 가지며 각 인자의 값을 각 원소의
                     값으로 하는 배열을 리턴하는 함수
   ex> Array(arguments)
         Dim myArray
         myArray = Array(1,2,3)
         response.write myArray(0)
         response.write myArray(1)
         response.write myArray(2)
   결과> 1 2 3

2. Eval 함수 : 전달된 문자열을 VBScript 표현식으로 간주하고 실행한 결과를 리턴
   ex> Eval(expression)
         Dim num1
         num1 = 10
         Eval num1 = num1 + 2
         response.write num1
   결과> 12

3. IsArray 함수 : 지정된 변수가 배열인지 아닌지를 검사
   ex> IsArray(varname)
         Dim numArray(3)
         response.write isArray(numArray)
   결과> True

4. IsDate 함수 : 전달된 표현식이 날짜 데이터인지 아닌지 검사
   ex> IsDate(expression)
         Dim num1
         num1 = 10
         response.write IsDate(num1)
   결과> False

5. IsEmpty 함수 : 전달된 표현식의 초기화 여부를 검사하는 함수
   ex> IsEmpty(expression)
         Dim num1
         response.write IsEmpty(num1)
   결과> True

6. IsNull 함수 : 전달된 표현식이 Null 표현인지 아닌지 검사
   ex> IsNull(expression)

7. IsNumeric 함수 : 전달된 표현식이 숫자인지 아닌지를 검사
   ex> IsNumeric(expression)

8. IsObject 함수 : 전달된 표현식이 객체인지 아닌지 검사
   ex> IsObject(expression)

9. LBound 함수 : 지정된 배열 변수의 첫번재 원소 인텍스를 리턴
   ex> Dim strArray(3)
         strArray(0) = "Microsoft"
         strArray(1) = "Active"
         strArray(2) = "Server"
         strArray(3) = "Pages"
         response.write LBound(strArray)
   결과> 0

10 . UBound 함수 : 지정된 배열 변수의 마지막 원소 인텍스를 리턴
   ex> Dim strArray(3)
         strArray(0) = "Microsoft"
         strArray(1) = "Active"
         strArray(2) = "Server"
         strArray(3) = "Pages"
         response.write UBound(strArray)
   결과> 3

WDF 2013 봉천동 동네 사진관。

Canon EOS 550D
Sigma 10-20mm f3.5 EX DC HSM
10mm | F3.5  |  1/400s  |  ISO 100


마지막이 될지도 모를 WDF
떨어져 버린 체력이 서운해.

진격의 거인 봉천동 동네 사진관。

Canon EOS 5D Mark Ⅱ
Canon 24-70mm f2.8L USM
70mm | F11  |  1/200s  |  ISO 100


요즘 가장 핫한!
저비용 고효율 코스프레!

1 2 3 4 5 6 7 8