MFC ActiveX 컨트롤: 고급 항목
이 문서에서는 ActiveX 컨트롤 개발과 관련된 고급 항목에 대해 설명합니다. 다음 범위가 포함됩니다.
Important
ActiveX는 새로운 개발에 사용하지 않아야 하는 레거시 기술입니다. ActiveX를 대체하는 최신 기술에 관한 자세한 내용은 ActiveX 컨트롤을 참조하세요.
ActiveX 컨트롤에서 데이터베이스 클래스 사용
ActiveX 컨트롤 클래스는 클래스 라이브러리의 일부이므로 표준 MFC 애플리케이션에서 데이터베이스 클래스를 사용하는 것과 동일한 절차와 규칙을 적용하여 MFC 데이터베이스 클래스를 사용하는 ActiveX 컨트롤을 개발할 수 있습니다.
MFC 데이터베이스 클래스에 대한 일반적인 개요는 MFC 데이터베이스 클래스(DAO 및 ODBC)를 참조하세요. 이 문서에서는 MFC ODBC 클래스와 MFC DAO 클래스를 모두 소개하고 자세한 내용을 안내합니다.
참고 항목
DAO는 Office 2013까지 지원됩니다. DAO 3.6은 최종 버전이며 사용되지 않는 것으로 간주합니다. Visual C++ 환경 및 마법사는 DAO를 지원하지 않습니다(DAO 클래스가 포함되어 있고 계속 사용할 수 있지만). 새 프로젝트에는 OLE DB 템플릿 또는 ODBC 및 MFC를 사용하는 것이 좋습니다. 기존 애플리케이션에 기본 DAO만 사용해야 합니다.
매개 변수가 있는 속성 구현
매개 변수가 있는 속성(속성 배열이라고도 함)은 같은 유형의 값 컬렉션을 컨트롤의 단일 속성으로 노출하는 메서드입니다. 예를 들어 매개 변수가 있는 속성을 사용하여 배열 또는 사전을 속성으로 노출할 수 있습니다. Visual Basic에서는 배열 표기법을 사용하여 이러한 속성에 액세스합니다.
x = o.Array(2, 3) ' gets element of 2D array
o.Array(2, 3) = 7 ' sets element of 2D array
속성 추가 마법사를 사용하여 매개 변수가 있는 속성을 구현합니다. 속성 추가 마법사는 컨트롤 사용자가 위의 표기법을 사용하거나 표준 방식으로 속성에 액세스할 수 있도록 하는 Get/Set 함수 쌍을 추가하여 속성을 구현합니다.
메서드 및 속성과 마찬가지로 매개 변수가 있는 속성도 허용되는 매개 변수 수에 제한이 있습니다. 매개 변수가 있는 속성의 경우 제한은 15개의 매개 변수입니다(속성 값을 저장하기 위해 하나의 매개 변수가 예약됨).
다음 절차에서는 2차원 정수 배열로 액세스할 수 있는 Array라는 매개 변수가 있는 속성을 추가합니다.
속성 추가 마법사를 사용하여 매개 변수가 있는 속성을 추가하려면
컨트롤의 프로젝트를 로드합니다.
클래스 뷰에서 컨트롤의 라이브러리 노드를 확장합니다.
컨트롤의 인터페이스 노드(라이브러리 노드의 두 번째 노드)를 마우스 오른쪽 단추로 클릭하여 바로 가기 메뉴를 엽니다.
바로 가기 메뉴에서 추가를 클릭한 다음, 속성 추가를 클릭합니다.
속성 이름 상자에 .를 입력합니다
Array
.속성 유형 상자에서 .를 선택합니다
short
.구현 형식에서 Get/Set 메서드를 클릭합니다.
함수 가져오기 및 함수 설정 상자에 Get 및 Set Functions의 고유한 이름을 입력하거나 기본 이름을 적용합니다.
매개 변수 이름 및 매개 변수 형식 컨트롤을 사용하여 행(짧은 형식)이라는 매개 변수를 추가합니다.
열(short 형식)이라는 두 번째 매개 변수를 추가합니다.
Finish를 클릭합니다.
속성 추가 마법사에서 변경한 내용
사용자 지정 속성을 추가하면 속성 추가 마법사에서 컨트롤 클래스 헤더()를 변경합니다. H) 및 구현(. CPP) 파일.
컨트롤 클래스에 다음 줄이 추가됩니다. H 파일:
SHORT GetArray(SHORT row, SHORT column);
void SetArray(SHORT row, SHORT column, SHORT newVal);
이 코드는 호출 GetArray
된 두 개의 함수를 선언하며 SetArray
사용자가 속성에 액세스할 때 특정 행과 열을 요청할 수 있도록 합니다.
또한 속성 추가 마법사는 컨트롤 클래스 구현()에 있는 컨트롤 디스패치 맵에 다음 줄을 추가합니다. CPP) 파일:
DISP_PROPERTY_PARAM_ID(CMyAxUICtrl, "Array", dispidArray, GetArray, SetArray, VT_I2, VTS_I2 VTS_I2)
마지막으로, 함수 및 SetArray
함수의 GetArray
구현이 끝에 추가됩니다. CPP 파일. 대부분의 경우 속성 값을 반환하도록 Get 함수를 수정합니다. Set 함수는 일반적으로 속성 변경 전후에 실행해야 하는 코드를 포함합니다.
이 속성이 유용하려면 매개 변수가 있는 속성에 대한 값을 저장하기 위해 형식의 short
컨트롤 클래스에서 2차원 배열 멤버 변수를 선언할 수 있습니다. 그런 다음 Get 함수를 수정하여 매개 변수로 표시된 대로 적절한 행과 열에 저장된 값을 반환하고 Set 함수를 수정하여 행 및 열 매개 변수에서 참조하는 값을 업데이트할 수 있습니다.
ActiveX 컨트롤에서 오류 처리
컨트롤에서 오류 조건이 발생하는 경우 컨트롤 컨테이너에 오류를 보고해야 할 수 있습니다. 오류가 발생하는 상황에 따라 오류를 보고하는 두 가지 방법이 있습니다. 속성의 Get 또는 Set 함수 또는 OLE Automation 메서드의 구현 내에서 오류가 발생하는 경우 컨트롤은 COleControl::ThrowError를 호출해야 합니다. 이 오류는 컨트롤 사용자에게 오류가 발생했음을 알 수 있습니다. 오류가 다른 시간에 발생하는 경우 컨트롤은 재고 오류 이벤트를 발생시키는 COleControl::FireError를 호출해야 합니다.
발생한 오류 종류를 나타내려면 컨트롤에서 오류 코드를 ThrowError
전달하거나 FireError
에 전달해야 합니다. 오류 코드는 32비트 값이 있는 OLE 상태 코드입니다. 가능하면 OLECTL에 정의된 표준 코드 집합에서 오류 코드를 선택합니다. H 헤더 파일입니다. 다음 표에서는 이러한 코드를 요약합니다.
ActiveX 컨트롤 오류 코드
오류 | 설명 |
---|---|
CTL_E_ILLEGALFUNCTIONCALL | 잘못된 함수 호출 |
CTL_E_OVERFLOW | 오버플로 |
CTL_E_OUTOFMEMORY | 메모리 부족 |
CTL_E_DIVISIONBYZERO | 0으로 나누기 |
CTL_E_OUTOFSTRINGSPACE | 문자열 공간이 부족합니다. |
CTL_E_OUTOFSTACKSPACE | 스택 공간이 부족합니다. |
CTL_E_BADFILENAMEORNUMBER | 파일 이름 또는 번호가 잘못되었습니다. |
CTL_E_FILENOTFOUND | 파일 없음 |
CTL_E_BADFILEMODE | 파일 모드가 잘못되었습니다. |
CTL_E_FILEALREADYOPEN | 파일이 이미 열려 있습니다. |
CTL_E_DEVICEIOERROR | 디바이스 입/출력(I/O) 오류입니다. |
CTL_E_FILEALREADYEXISTS | 파일이 이미 있습니다. |
CTL_E_BADRECORDLENGTH | 레코드 길이가 잘못되었습니다. |
CTL_E_DISKFULL | 디스크가 꽉 찼습니다. |
CTL_E_BADRECORDNUMBER | 레코드 개수가 잘못되었습니다. |
CTL_E_BADFILENAME | 잘못된 파일 이름 |
CTL_E_TOOMANYFILES | 파일이 너무 많습니다. |
CTL_E_DEVICEUNAVAILABLE | 디바이스를 사용할 수 없습니다. |
CTL_E_PERMISSIONDENIED | 사용 권한이 거부됨 |
CTL_E_DISKNOTREADY | 디스크가 준비되지 않았습니다. |
CTL_E_PATHFILEACCESSERROR | 경로/파일 액세스 오류 |
CTL_E_PATHNOTFOUND | 경로를 찾을 수 없습니다. |
CTL_E_INVALIDPATTERNSTRING | 잘못된 패턴 문자열 |
CTL_E_INVALIDUSEOFNULL | NULL을 잘못 사용했습니다. |
CTL_E_INVALIDFILEFORMAT | 잘못된 파일 형식 |
CTL_E_INVALIDPROPERTYVALUE | 잘못된 속성 값 |
CTL_E_INVALIDPROPERTYARRAYINDEX | 잘못된 속성 배열 인덱스 |
CTL_E_SETNOTSUPPORTEDATRUNTIME | Set은 런타임에 지원되지 않습니다. |
CTL_E_SETNOTSUPPORTED | Set은 지원되지 않습니다(읽기 전용 속성). |
CTL_E_NEEDPROPERTYARRAYINDEX | 속성 배열 인덱스가 필요합니다. |
CTL_E_SETNOTPERMITTED | Set은 허용되지 않습니다. |
CTL_E_GETNOTSUPPORTEDATRUNTIME | Get은 런타임에 지원되지 않습니다. |
CTL_E_GETNOTSUPPORTED | Get은 지원되지 않습니다(쓰기 전용 속성). |
CTL_E_PROPERTYNOTFOUND | 속성을 찾을 수 없습니다. |
CTL_E_INVALIDCLIPBOARDFORMAT | 클립보드 형식이 잘못되었습니다. |
CTL_E_INVALIDPICTURE | 그림이 잘못되었습니다. |
CTL_E_PRINTERERROR | 프린터 오류 |
CTL_E_CANTSAVEFILETOTEMP | TEMP에 파일을 저장할 수 없음 |
CTL_E_SEARCHTEXTNOTFOUND | 검색 텍스트를 찾을 수 없습니다. |
CTL_E_REPLACEMENTSTOOLONG | 대체 텍스트가 너무 깁니다. |
필요한 경우 CUSTOM_CTL_SCODE 매크로를 사용하여 표준 코드 중 하나에서 다루지 않는 조건에 대한 사용자 지정 오류 코드를 정의합니다. 이 매크로의 매개 변수는 1000에서 32767 사이의 정수여야 합니다. 예시:
#define MYCTL_E_SPECIALERROR CUSTOM_CTL_SCODE(1000)
기존 VBX 컨트롤을 대체할 ActiveX 컨트롤을 만드는 경우 오류 코드가 호환되도록 VBX 컨트롤에서 사용하는 것과 동일한 숫자 값으로 ActiveX 컨트롤 오류 코드를 정의합니다.
컨트롤에서 특수 키 처리
경우에 따라 특정 키 입력 조합을 특별한 방식으로 처리하려고 할 수 있습니다. 예를 들어 여러 줄 텍스트 상자 컨트롤에서 ENTER 키를 누를 때 새 줄을 삽입하거나 방향 키 ID를 누를 때 편집 컨트롤 그룹 간에 이동합니다.
ActiveX 컨트롤의 기본 클래스인 경우 컨테이너가 COleControl
메시지를 처리하기 전에 CWnd::P reTranslateMessage를 재정의하여 메시지를 처리할 수 있습니다. 이 기술을 사용하는 경우 재정의에서 메시지를 처리하는 경우 항상 TRUE를 PreTranslateMessage
반환합니다.
다음 코드 예제에서는 방향 키와 관련된 메시지를 처리할 수 있는 방법을 보여 줍니다.
BOOL CMyAxUICtrl::PreTranslateMessage(MSG* pMsg)
{
BOOL bHandleNow = FALSE;
switch (pMsg->message)
{
case WM_KEYDOWN:
switch (pMsg->wParam)
{
case VK_UP:
case VK_DOWN:
case VK_LEFT:
case VK_RIGHT:
bHandleNow = TRUE;
break;
}
if (bHandleNow)
{
OnKeyDown((UINT)pMsg->wParam, LOWORD(pMsg->lParam), HIWORD(pMsg->lParam));
}
break;
}
return bHandleNow;
}
ActiveX 컨트롤의 키보드 인터페이스 처리에 대한 자세한 내용은 ActiveX SDK 설명서를 참조하세요.
런타임에 보이지 않는 대화 상자 컨트롤에 액세스
사용자 인터페이스가 없고 런타임에 보이지 않는 대화 상자 컨트롤을 만들 수 있습니다. 런타임에 보이지 않는 ActiveX 컨트롤을 대화 상자에 추가하고 CWnd::GetDlgItem을 사용하여 컨트롤에 액세스하는 경우 컨트롤이 제대로 작동하지 않습니다. 대신 다음 기술 중 하나를 사용하여 컨트롤을 나타내는 개체를 가져와야 합니다.
멤버 변수 추가 마법사를 사용하여 컨트롤 변수를 선택한 다음 컨트롤의 ID를 선택합니다. 멤버 변수 이름을 입력하고 컨트롤의 래퍼 클래스를 컨트롤 형식으로 선택합니다.
또는
지역 변수 및 하위 클래스를 대화 상자 항목으로 선언합니다. 다음과 유사한 코드 삽입(
CMyCtrl
래퍼 클래스, IDC_MYCTRL1 컨트롤의 ID)CCirc myCirc; myCirc.SubclassDlgItem(IDC_CIRCCTRL2, this); // ... use myCirc ... myCirc.UnsubclassWindow();