ActiveX를 만들때 매개변수로 배열을 받아야 할 필요가 있다.
이 배열을 ActiveX의 매개변수에 어떻게 넣느냐가 문제이다.
일단 기본 데이터 형식은 아니기 때문에, VARIANT 형식으로 받아야 하겠다.
void ShowArray(VARIANT varArray)
나는 VS2003을 쓰는데, 휴.. MFC ActiveX에서 이렇게 메소드를 만들자마자 버그코드를 만들기 시작한다.
void TestOCX::ShowArray(LPVARIANT varArray) { CComVariant vtSource; // VT_BYREF 형식으로 입력되면 REF 값을 VARIANT로 복사한다. // VB Script 배열 형식은 VT_BYREF를 포함하므로 이걸 없앤다. ::VariantCopyInd(&vtSource, varArray); // Variant 형식이 VT_DISPATCH인지 확인한다. if(VT_DISPATCH == (VT_DISPATCH & V_VT(&vtSource)) ) { COleDispatchDriver disp; // COleDispatchDriver에 Attach한다. MFC는 좋은 클래스들을 많이 갖고 있다. disp.AttachDispatch(vtSource->pdispVal, FALSE); try { DISPID diLength; LPOLESTR length = L"length"; long nArrayLength = 0; // Dispatch에서 length의 DISPID를 구한다. hr = disp->m_lpDispatch->GetIDsOfNames(IID_NULL, &length, 1, LOCALE_USER_DEFAULT, &diLength); if(FAILED(hr)) { FireError(E_INVALIDARG, "매개변수 입력이 잘못되었습니다."); } // length의 속성값을 획득한다. disp.GetProperty(diLength, VT_I4, &nArrayLength); // 배열 길이 만큼 for문 돌면서 배열 값 출력 for(int i = 0; i < nArrayLength; i++) { DISPID diIndex; TCHAR szIndex[20]; CComBSTR bstrIndex; CComVariant vtData; // 배열 인덱스 속성값은 문자열로 지정하면 얻을 수 있다. // L"0", L"1", L"2" 처럼. StringCchPrintf(szIndex, 20, "%d", i); bstrIndex = szIndex; // 배열 인덱스의 DISPID를 얻는다. disp.m_lpDispatch->GetIDsOfNames(IID_NULL, &bstrIndex, 1, LOCALE_USER_DEFAULT, &diIndex); // 배열 값을 VARIANT 형식으로 받는다. disp.GetProperty(diIndex, VT_VARIANT, &vtData); // 예제에서는 배열의 값이 항상 문자열이여야 한다. if( VT_BSTR != V_VT(&vtData) ) { FireError(E_INVALIDARG, "문자열 배열만 입력 가능합니다."); break; } //배열의 값을 각각 메세지 박스로 출력한다. AfxMessageBox(CString(vtData.bstrVal)); } } catch(CMemoryException *pEx) { // 메모리 예외 처리 : 예제에서는 그냥 ReportError 및 FireError로 처리 pEx->ReportError(); FireError(E_OUTOFMEMORY, "메모리 오류입니다."); pEx->Delete(); } catch(COleException *pEx) { // OLE 예외 처리 : 예제에서는 그냥 ReportError 및 FireError로 처리 pEx->ReportError(); FireError(pEx->m_sc, "OLE 오류입니다."); pEx->Delete(); } catch(COleDispatchException* pEx) { // OLE Dispatch 예외 처리 : 예제에서는 그냥 ReportError 및 FireError로 처리 pEx->ReportError(); FireError(pEx->m_scError, "OLE Dispatch 오류입니다."); pEx->Delete(); } } }
예제를 보면 JScript 배열이 어떻게 구성되어 있는지 볼 수 있다.
TRACE를 따라가다보면 알겠지만, 배열의 크기가 3이라고 할때, length의 DISPID는 4값이면, "0"~"2"까지의 DISPID는 1~3 이다.
DISPID 5,6 값이 VT_DISPATCH로 되어 있고, 각각 constructor, prototype이라는 속성이 지원되는데, javascript 객체의 생성자와 객체의 재정의에 관련된 내용이여서 배열을 받는데 크게 사용되진 않는다.
alert(arrArray);
라고 하면 DISPID 0값이 나오는 것으로 확인할 수 있겠다.