2008. 6. 15. 23:41

VariantUse 샘플: Variant 사용 설명

VariantUse 샘플에서는 기존 데이터를 variant로 변경하고 variant를 다른 데이터 형식으로 변경하는 방법을 보여 줍니다. 대부분의 COM 개체는 variant를 함수 매개 변수로 받아들입니다. 이 샘플을 통해 표준 C 데이터 형식을 variant로 변경하는 방법을 이해할 수 있습니다.

이 샘플에서는 통화, 날짜, SAFEARRAY, 다차원 배열, 문자열, char, short 및 long 형식을 다룹니다.

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

void CVarUseDlg::OnCurrency()
{
 VARIANT myVar;
 myVar.vt = VT_CY;
 

 // put 15.15 into the currency variant.
 CURRENCY myValue;
 myValue.Hi = 0;
 myValue.Lo = (LONG)(15*10000 + 1537);
// set the value to $15.15;
 myVar.cyVal = myValue;
 
//or
 myValue.int64 = (151234);
 myVar.cyVal = myValue;
 
 
 
 //Now get the value from a float and put it into the currency.
 float myMoney = (float)5.37;
 myVar.vt = VT_R4;
 myVar.fltVal = myMoney;
 //no loss of precission.
 ENSURE(SUCCEEDED(VariantChangeType(&myVar, &myVar, 0, VT_CY)));
 

 //Now get the value from a String
 USES_CONVERSION;
 myVar.bstrVal = SysAllocString(L"23.4345");
 myVar.vt = VT_BSTR;
 ENSURE(SUCCEEDED(VariantChangeType(&myVar, &myVar, 0, VT_CY)));

 //Finally output a currency to a string.
 myVar.cyVal.int64 += myVar.cyVal.int64;
// + myVar.cyVal;
 ENSURE(SUCCEEDED(VariantChangeType(&myVar, &myVar, 0, VT_BSTR)));
 
}

void CVarUseDlg::OnStrings()
{
 //Create a BSTR and assign it to a Variant
 BSTR x = SysAllocString(L"Hello");
 VARIANT myVariant;
 myVariant.vt = VT_BSTR;
 myVariant.bstrVal = x;
 SysFreeString(x);

 //Create a CString and change it to a variant;
 CString myCString(_T("My String"));
 CString mySecondString;
 
 BSTR y = myCString.AllocSysString();
 myVariant.bstrVal = y;
 mySecondString = y;
 SysFreeString(y);

 
 //Create two BSTRs and add them.
 BSTR a = SysAllocString(L"One two ");
 BSTR b = SysAllocString(L"three four.");
 _bstr_t my_bstr_t(a, TRUE);
 my_bstr_t += b;
 myVariant.bstrVal = my_bstr_t;
 // or
 myVariant.bstrVal = _bstr_t(a, FALSE) + b;

 //Change a bstr to a CString.
 CString ANewString(b);
 //or if CString already exists.
 myCString = b;


 //Use of CComBSTR
 CComBSTR myCComBSTR(L"Hello");
 myCComBSTR.Append(L", how are you?");
 VARIANT varFromCCom;
 varFromCCom.vt = VT_BSTR;
 varFromCCom.bstrVal = myCComBSTR;
 
}

void CVarUseDlg::OnBasic()
{
 //create a variant of the character 'c'
 VARIANT varC;
 varC.vt=VT_UI1;
 varC.cVal = 'c';

 //create a variant of the short 12
 VARIANT varS;
 varS.vt = VT_I2;
 varS.iVal = 12;

 //create a variant of the long 1234567;
 VARIANT varL;
 varL.vt = VT_I4;
 varL.lVal = 1234567;
}

void CVarUseDlg::OnSafeArray()
{

 //Create a standard array;
 int* pMyOriginalArray = new int[100];
 int count;
 for(count = 0; count < 100; count++) pMyOriginalArray[count] = count;

 
 //Now get ready to put it into a safe array
 HRESULT hr;
 //create an array bound
 SAFEARRAYBOUND rgsabound[1];
 rgsabound[0].lLbound = 0;  
//The first (and only) collumn of our array starts at 0.
 rgsabound[0].cElements = 100;
//and has 100 elements.
 
 //create the array
 SAFEARRAY FAR* pMySafeArray;
 pMySafeArray = SafeArrayCreate(VT_I4, 1, rgsabound);
//create the array of 4byte integers, one dimension
               //with the bounds stored in rgsabound.
 
 //now access the safe array's data.

 int* pData;
 hr = SafeArrayAccessData(  pMySafeArray, (void**)&pData);
//Get a pointer to the data.
 
 
 //copy the 400 bytes of data from our old array to the new one.
 memcpy_s(pData, 400, pMyOriginalArray, 400);
 
 //here we verify to you that the data is correct.
 for(count = 0; count < 100; count++) ASSERT(pData[count] == pMyOriginalArray[count]);
 SafeArrayUnaccessData(pMySafeArray);
 
 
 //To put the SafeArray in a Variant
 VARIANT myVariant;
 myVariant.parray = pMySafeArray;
 myVariant.vt = VT_ARRAY|VT_I4;
// state it's an array and what type it holds.
 
 
 //pass the Variant to a function call. 
 FunctionCallWithVariant(myVariant);
 //see that the original array was modified.
 hr = SafeArrayAccessData(myVariant.parray, (void**)&pData);
//Get a pointer to the data.
 ASSERT(pData[0] == 1234);
 SafeArrayUnaccessData(pMySafeArray);
 
 //Copy the variant.
 VARIANT NewVariant;
 NewVariant.vt = VT_EMPTY;
// must set variant type for copy to work.
 hr = VariantCopy(&NewVariant, &myVariant);

 //check array in copy of variant
 int* pNewData;
 hr = SafeArrayAccessData(NewVariant.parray, (void**) &pNewData);
 for(count = 0; count < 100; count++) ASSERT(pData[count] == pNewData[count]);
 ASSERT(pData != pNewData); //copying the varriant created a new copy of the
         
//array it contained too.  There is now 2 copies of the data.
 SafeArrayUnaccessData(NewVariant.parray);

 //Or you could use CreateVector to create the 1 dimensional array.
 SAFEARRAY* pMyVector = SafeArrayCreateVector(VT_I4, -50, 100);  //Vecoor of VT_I4, starting at 0
               
//with 100 elements.
 int* pVectorData;
 hr = SafeArrayAccessData(pMyVector, (void**)&pVectorData);
 memcpy_s(pVectorData, 400, pMyOriginalArray, 400);
//copy the 400 bytes of data from our old array into the new one.
 int element;
 long location[1] = {-50};
 hr = SafeArrayGetElement(pMyVector, location, (void*)&element);
 ASSERT(element == 0);
//element -50 is the first element from the original array
 location[0] = 0;
 hr = SafeArrayGetElement(pMyVector, location, (void*)&element);
 ASSERT(element == 50);
// element 0 is the 50th element from the original array
 delete[] pMyOriginalArray;
 hr = SafeArrayDestroy(pMySafeArray);
 hr = SafeArrayDestroy(pMyVector);
 hr = SafeArrayDestroy(NewVariant.parray);
 
}

void CVarUseDlg::OnOleArray()
{
 //Create and fill an array.
 int* pMyOriginalArray = new int[100];
 int* pData;
 int count;
 for(count = 0; count < 100; count++) pMyOriginalArray[count]=count;
 
 //Put it into a safe array.
 COleSafeArray myOleSafeArray;
 myOleSafeArray.CreateOneDim(VT_I4, 100, pMyOriginalArray);
// create one dimension array of 4-byte values
                     // 100 entries w/data from pMyOriginalArray.
 // Access that safe array.
 //Get a pointer to the Data.
 myOleSafeArray.AccessData((void**)&pData);
 //verify all of the data.
 for(count = 0; count < 100; count++) ASSERT(pData[count] == pMyOriginalArray[count]);
 myOleSafeArray.UnaccessData();
 
 //clean up.
 delete[] pMyOriginalArray;
}

void CVarUseDlg::OnMultiDimensionArray()
{
 short pMyOriginalData[2][3][4][5];
 HRESULT hr;
 //initialize data
 for(short a = 0; a < 2; a++)
  for(short b = 0; b < 3; b++)
   for(short c = 0; c < 4; c++)
    for(short d = 0; d < 5; d++)
     pMyOriginalData[a][b][c][d] = a*b*c*d;

 

 SAFEARRAY* pMyArray;
 SAFEARRAYBOUND rgsabound[4];
 for(int count = 2; count < 6; count++)
 {
  rgsabound[count - 2].lLbound = 0;
  rgsabound[count - 2].cElements = count;
 }
 pMyArray = SafeArrayCreate(VT_I2, 4, rgsabound);
 short* pData;
 hr = SafeArrayAccessData(pMyArray, (void**)&pData);
 memcpy_s(pData, 2*3*4*5*2, pMyOriginalData, 2*3*4*5*2);
 short element;
 long location[4] = {1,2,3,4};
 hr = SafeArrayGetElement(pMyArray, location, (void*)&element);
 ASSERT(element == 1*2*3*4);
 
 
 
 hr = SafeArrayDestroy(pMyArray);
 ASSERT(hr != S_OK);
 hr = SafeArrayUnaccessData(pMyArray);
 hr = SafeArrayDestroy(pMyArray);
 ASSERT(hr == S_OK);
 
}

void CVarUseDlg::OnDate()
{
 VARIANT timeSelection;
 COleDateTime timeNow;
 DATE curDate;
 HRESULT hr;
 //Get current Time.
 timeNow = COleDateTime::GetCurrentTime();
 
 //Put time into variant.
 timeSelection.vt = VT_DATE;
 timeSelection.date = timeNow.m_dt;
 
 
//Convert Variant into string using Variant Change Type.
 hr = VariantChangeType(&timeSelection, &timeSelection, 0, VT_BSTR);
 CString sCurTime(timeSelection.bstrVal);
 
 
 
//Get Time as System Time.
 SYSTEMTIME mySysTime;
 timeNow.GetAsSystemTime(mySysTime);
 
 //Use COleDateTime functionality to get change SYSTEMTIME into DATE.
 COleDateTime pastTime(mySysTime);
 curDate = pastTime.m_dt;


 //Use COldeDateTime Format command to get date as CString.
 LPCTSTR format = _T("%X %z"); 
//Current time and time zone.
 
//Note see "strftime" help for valid formating strings.
 CString sTime = pastTime.Format(format);

}

void CVarUseDlg::FunctionCallWithVariant(VARIANT myVariant)
{
 HRESULT hr;
 int* pData;
 int count;
 hr = SafeArrayAccessData(myVariant.parray, (void**)&pData); //access the array stored in the varriant.
 for(count = 0; count < 100; count++) ASSERT(pData[count] == count);
//check data;
 pData[0] = 1234;
//modify data
 SafeArrayUnaccessData(myVariant.parray);
}

------------------------------------------------------------------------------------------
출처 : MSDN 2005

첨부 파일 : 소스 원본 (Visual Studio 2005 Project)