출처 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=3638

조경민 USES_COMVERSION (bro@shinbiro.com)
====================================================

BSTR test( BSTR bstrVal )
{
  USES_CONVERSION;
  char* pszVal;
  W2A(bstrVal,pszVal);
  하면 pszVal 안에 BSTR문자열값이 들어간다.

  BSTR bstrCopy;
  A2W(pszVal,bstrCopy);
  하면 pszVal값이 bstrCopy에 들어간다. SysAlloc된 상태

     사용후
  SysFreeString(bstrCopy);해야 함

  BSTR bstrRet;
  A2W(pszVal,bstrRet);

  return bstrRet;    // ATL컴포넌트 메소드가 BSTR리턴시
}                    // SysAlloc후 리턴한다.
                     // VC Client에서 SysFreeString해야함
                     // VB Client에서는 알아서 프리시킴

BSTR<->char* 컨버팅이 간편한

USES_CONVERSION을 쓰려면...

1. ATL Project
 -> 그냥 쓸수 있다.

2. MFC Project
 -> #include <comdef.h>
    #include <afxpriv.h>

3. Win32 Dll Project
#include <comdef.h>
#include <CRTDBG.H>
#include <atlconv.h>

를 하면 된다. ( 하나씩 찾아봤음 -_-;)


COM에서 WideChar와 AnsiChar 바꾸는 매크로

VARIANT에 문자열 넣기

// com support class
#include <comdef.h>
#include <AFXPRIV.H>    // USES_CONVERSION 이 정의된 곳

USES_CONVERSION;    
VARIANT var;
VariantInit(&var);
var.vt = VT_BSTR;
var.bstrVal = SysAllocString(A2W("하하하하하"));


*웹페이지에서는 문자열은 VARIANT를 써야 한다.



다음은 ASP서포트 상태에서 BSTR과 char*사이의 변환이다.

    if( m_piServer )
    {
        USES_CONVERSION;
        BSTR bstrLogicPath, bstrPhysicPath;
        bstrLogicPath = SysAllocString(A2W("/NstChart"));
       
        m_piServer->MapPath( bstrLogicPath, &bstrPhysicPath)

        SysFreeString( bstrLogicPath );
       
        char* pszPhysicPath = W2A(bstrPhysicPath);
               
        m_plgManager->fnSetPlugPath( pszPhysicPath );

    }



------------------------------------------------------------------
참고 테크니컬 노트
TN059: Using MFC MBCS/Unicode Conversion Macros
This note describes how to use the macros for MBCS/Unicode conversion which are defined in
AFXPRIV.H. These macros are most useful if your application deals directly with the OLE API or for
some reason, often needs to convert between Unicode and MBCS.

Overview

In MFC 3.x, a special DLL was used (MFCANS32.DLL) to automatically convert between Unicode and MBCS
when OLE interfaces were called. This DLL was an almost transparent layer that allowed OLE
applications to be written as if the OLE APIs and interfaces were MBCS, even though they are always
Unicode (except on the Macintosh). While this layer was convenient and allowed applications to be
quickly ported from Win16 to Win32 (MFC, Microsoft Word, Microsoft Excel, and VBA, are just some of
the Microsoft applications that used this technology), it also had a sometimes significant
performance hit. For this reason, MFC 4.x does not use this DLL and instead talks directly to the
Unicode OLE interfaces. To do this, MFC needs to convert to Unicode to MBCS when making a call to
an OLE interface, and often needs to convert to MBCS from Unicode when implementing an OLE
interface. In order to handle this efficiently and easily, a number of macros were created to make
this conversion easier.

One of the biggest hurdles of creating such a set of macros is memory allocation. Because the
strings cannot be converted in place, new memory to hold the converted results must be allocated.
This could have been done with code similar to the following:

// we want to convert an MBCS string in lpszA
int nLen = MultiByteToWideChar(CP_ACP, 0,lpszA, -1, NULL, NULL);
LPWSTR lpszW = new WCHAR[nLen];
MultiByteToWideChar(CP_ACP, 0,
lpszA, -1, lpszW, nLen);
// use it to call OLE here
pI->SomeFunctionThatNeedsUnicode(lpszW);
// free the string
delete[] lpszW;

This approach as a number of problems. The main problem is that it is a lot of code to write, test,
and debug. Something that was a simple function call, is now much more complex. In addition, there
is a significant runtime overhead in doing so. Memory has to be allocated on the heap and freed
each time a conversion is done. Finally, the code above would need to have appropriate #ifdefs
added for Unicode and Macintosh builds (which don’t require this conversion to take place).

The solution we came up with is to create some macros which 1) mask the difference between the
various platforms, and 2) use an efficient memory allocation scheme, and 3) are easy to insert into
the existing source code. Here is an example of one of the definitions:

#define A2W(lpa) (    ((LPCSTR)lpa == NULL) ? NULL : (           _convert = (strlen(lpa)+1),        AfxA2WHelper((LPWSTR) alloca(_convert*2),
lpa, _convert)    ))

Using this macro instead of the code above and things are much simpler:

// use it to call OLE here
USES_CONVERSION;
pI->SomeFunctionThatNeedsUnicode(T2OLE(lpszA));

There are extra calls where conversion is necessary, but using the macros is simple and effective.

The implementation of each macro uses the _alloca() function to allocate memory from the stack
instead of the heap. Allocating memory from the stack is much faster than allocating memory on the
heap, and the memory is automatically freed when the function is exited. In addition, the macros
avoid calling MultiByteToWideChar (or WideCharToMultiByte) more than one time. This is done by
allocating a little bit more memory than is necessary. We know that an MBC will convert into at
most one WCHAR and that for each WCHAR we will have a maximum of two MBC bytes. By allocating a 
little more than necessary, but always enough to handle the conversion the second call second call
to the conversion function is avoided. The call to the helper function AfxA2Whelper reduces the
number of argument pushes that must be done in order to perform the conversion (this results in
smaller code, than if it called MultiByteToWideChar directly).

In order to for the macros to have space to store the a temporary length, it is necessary to
declare a local variable called _convert that does this in each function that uses the conversion
macros. This is done by invoking the USES_CONVERSION macro as seen above in the example.

There are both generic conversion macros and OLE specific macros. These two different macro sets
are discussed below. All of the macros reside in AFXPRIV.H.

Generic Conversion Macros

The generic conversion macros form the underlying mechanism. The macro example and implementation
shown in the previous section, A2W, is one such “generic” macro. It has no relation to OLE
specifically. The set of generic macros is listed below:

A2CW        (LPCSTR) -> (LPCWSTR)
A2W        (LPCSTR) -> (LPWSTR)
W2CA        (LPCWSTR) -> (LPCSTR)
W2A        (LPCWSTR) -> (LPSTR)

Besides doing text conversions, there are also macros and helper functions for converting
TEXTMETRIC, DEVMODE, BSTR, and OLE allocated strings. These macros are beyond the scope of this
discussion ? refer to AFXPRIV.H for more information on those macros.

OLE Conversion Macros

The OLE conversion macros are designed specifically for handling functions which expect OLESTR
characters. If you examine the OLE headers you will see many references to LPCOLESTR and OLECHAR.
These types are used to refer to the type of characters used in OLE interfaces in a way that is not
specific to the platform. OLECHAR maps to char in Win16 and Macintosh platforms and WCHAR in Win32.

In order to keep the number of #ifdef directives in the MFC code to a minimum we have a similar
macro for each conversion that where OLE strings are involved. The following macros are the most
commonly used:

T2COLE    (LPCTSTR) -> (LPCOLESTR)
T2OLE    (LPCTSTR) -> (LPOLESTR)
OLE2CT    (LPCOLESTR) -> (LPCTSTR)
OLE2T    (LPCOLESTR) -> (LPCSTR)

Again there are similar macros for doing TEXTMETRIC, DEVMODE, BSTR, and OLE allocated strings.
Refer to AFXPRIV.H for more information.

Other Considerations

Don’t use the macros in a tight loop. For example, you do NOT want to write the following kind of
code:

void BadIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
for (int ii = 0; ii < 10000; ii++)
pI->SomeMethod(ii, T2COLE(lpsz));
}

The code above could result in allocating megabytes of memory on the stack depending on what the
contents of the string lpsz is!  It also takes time to convert the string for each iteration of the
loop. Instead move such constant conversions out of the loop:

void MuchBetterIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
LPCOLESTR lpszT = T2COLE(lpsz);
for (int ii = 0; ii < 10000; ii++)
pI->SomeMethod(ii, lpszT);
}

If the string is not constant, then encapsulate the method call into a function. This will allow
the conversion buffer to be freed each time. For example:

void CallSomeMethod(int ii, LPCTSTR lpsz)
{
USES_CONVERSION;
pI->SomeMethod(ii, T2COLE(lpsz));
}

void MuchBetterIterateCode2(LPCTSTR* lpszArray)
{
for (int ii = 0; ii < 10000; ii++)
CallSomeMethod(ii, lpszArray[ii]);
}

Never return the result of one of the macros, unless the return value implies making a copy of the
data before the return. For example, this code is bad:

LPTSTR BadConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI->GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; // bad! returning alloca memory
}

The code above could be fixed by changing the return value to something which copies the value:

CString BetterConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI->GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; // CString makes copy
}

The macros are easy to use and easy to insert into your code, but as you can tell from the caveats
above, you need to be careful when using them.

ActiveX 컨트롤은 광범위한 OLE 기능을 지원하고 다양한 소프트웨어의 요구 사항에 맞게 사용자 지정할 수 있는 COM(Component Object Model) 기반의 다시 사용 가능한 소프트웨어 구성 요소입니다. ActiveX 컨트롤은 일반적인 ActiveX 컨트롤 컨테이너와 인터넷의 World Wide Web 웹 페이지 모두에 사용할 수 있도록 설계되었습니다. ActiveX 컨트롤은 여기에 설명된 MFC를 사용하거나 ATL(액티브 템플릿 라이브러리)을 사용하여 만들 수 있습니다.

ActiveX 컨트롤은 자신이 만든 창 안에 자신을 포함시킬 수 있으며, 마우스 클릭과 같은 이벤트에 응답하고, 자동화 개체의 속성 및 메서드와 비슷한 속성 및 메서드가 포함된 인터페이스를 통해 관리될 수 있습니다.

이러한 컨트롤은 데이터베이스 액세스, 데이터 모니터링 또는 그래프 그리기 등의 여러 가지 용도로 개발될 수 있습니다. ActiveX 컨트롤은 이식성 외에도, 기존 OLE 컨테이너와의 호환성이나 OLE 컨테이너 메뉴와 ActiveX 컨트롤 메뉴를 통합하는 기능과 같이 이전 ActiveX 컨트롤에는 없었던 기능도 지원합니다. 또한, ActiveX 컨트롤은 컨트롤 사용자가 호출할 수 있도록 읽기/쓰기 속성이나 메서드를 노출시키는 자동화 기능을 완벽하게 지원합니다.

창 없는 ActiveX 컨트롤과 활성화될 때만 창을 만드는 컨트롤을 만들 수도 있습니다. 창 없는 컨트롤을 사용하면 응용 프로그램의 화면 표시 속도가 빨라지며 투명한 컨트롤과 사각형이 아닌 컨트롤도 만들 수 있습니다. 또한 ActiveX 컨트롤 속성을 비동기적으로 로드할 수도 있습니다.

ActiveX 컨트롤은 모든 OLE 컨테이너에 사용할 수 있는 in-process 서버(대개 작은 개체)로서 구현됩니다. ActiveX 컨트롤의 전체 기능은 ActiveX 컨트롤을 인식할 수 있도록 설계된 OLE 컨테이너 내에서만 사용할 수 있습니다. ActiveX 컨트롤을 지원하는 컨테이너의 목록은 ActiveX 컨트롤을 다른 응용 프로그램에서 사용을 참조하십시오. 이러한 컨테이너 형식(이하, "컨트롤 컨테이너"라고 함)은 ActiveX 컨트롤의 속성과 메서드를 사용하여 해당 컨트롤을 작동시킬 수 있으며, 이벤트 형식으로 ActiveX 컨트롤로부터 알림을 받습니다. 다음 그림은 이러한 상호 작용을 보여 줍니다.

ActiveX 컨트롤 컨테이너와 창 있는 ActiveX 컨트롤 간의 상호 작용

ActiveX 컨트롤 최적화에 대한 최신 내용은 MFC ActiveX 컨트롤: 최적화를 참조하십시오.

MFC ActiveX 컨트롤을 만들려면 ActiveX 컨트롤 프로젝트 만들기를 참조하십시오.

자세한 내용은 다음을 참조하십시오.

ActiveX 컨트롤의 기본 구성 요소

ActiveX 컨트롤은 컨트롤 컨테이너 및 사용자와의 효과적인 상호 작용을 위해 몇 가지 프로그래밍 요소를 사용합니다. 여기에는 COleControl 클래스, 이벤트 발생 함수 및 디스패치 맵이 포함됩니다.

사용자가 개발하는 모든 ActiveX 컨트롤 개체는 ActiveX 컨트롤 개체의 MFC 기본 클래스인 COleControl로부터 여러 가지 강력한 기능을 상속받습니다. 이러한 기능에는 현재 위치에서 활성화 및 자동화 논리가 포함됩니다. COleControl은 MFC 창 개체와 같은 기능 및 이벤트 발생 기능을 가진 컨트롤 개체를 제공합니다. 또한 COleControl은 창에서 제공하는 일부 기능(마우스 캡처, 키보드 포커스, 스크롤 등)을 컨테이너의 도움을 받아야만 구현할 수 있지만 화면 표시는 훨씬 빠른 창 없는 컨트롤도 제공합니다.

ActiveX 컨트롤 클래스는 COleControl에서 파생되기 때문에 특정 조건이 만족될 때 컨트롤 컨테이너에 메시지(이벤트라고 함)를 보내거나 "발생"시키는 기능을 상속받습니다. 이러한 이벤트는 컨트롤에 중요한 사항이 발생할 때 이를 컨트롤 컨테이너에 알리는 데 사용됩니다. 또한 이벤트에 매개 변수를 첨부하면 이벤트에 대한 추가 정보를 컨트롤 컨테이너에 보낼 수 있습니다. ActiveX 컨트롤 이벤트에 대한 자세한 내용은 MFC ActiveX 컨트롤: 이벤트를 참조하십시오.

마지막 요소인 디스패치 맵은 함수(메서드라고 함) 및 특성(속성이라고 함) 집합을 컨트롤 사용자에게 노출시키는 데 사용됩니다. 속성을 사용하면 컨트롤 컨테이너 또는 컨트롤 사용자가 컨트롤을 여러 가지 방식으로 조작할 수 있도록 합니다. 사용자는 컨트롤의 모양 또는 컨트롤의 특정 값을 변경하거나, 컨트롤이 관리하는 특정 데이터 부분에 액세스하는 등 컨트롤에 대한 요청을 할 수 있습니다. 이 인터페이스는 컨트롤 개발자에 의해 결정되며 클래스 뷰에서 정의할 수 있습니다. ActiveX 컨트롤 메서드와 속성에 대한 자세한 내용은 MFC ActiveX 컨트롤: 메서드속성 문서를 참조하십시오.

창 있는 컨트롤과 ActiveX 컨트롤 컨테이너 간의 상호 작용

컨트롤 컨테이너 내에서 컨트롤이 사용될 때 컨트롤은 속성과 메서드를 노출시키는 메커니즘과 이벤트를 발생시키는 메커니즘을 사용하여 컨트롤 컨테이너와 통신합니다. 다음 그림은 이 두 가지 메커니즘의 구현 방식을 보여 줍니다.

ActiveX 컨트롤 컨테이너와 ActiveX 컨트롤 간의 통신

위의 그림은 다른 OLE 인터페이스(자동화 및 이벤트 포함)가 컨트롤에 의해 처리되는 방식도 보여 줍니다.

컨트롤과 컨트롤 컨테이너 간의 모든 통신은 COleControl에 의해 수행됩니다. COleControl은 컨트롤 컨테이너의 일부 요청을 처리하기 위해 컨트롤 클래스에 구현된 멤버 함수를 호출합니다. 모든 메서드와 일부 속성은 이러한 방식으로 처리됩니다. 또한 컨트롤 클래스는 COleControl의 멤버 함수를 호출하여 컨테이너와의 통신을 시작할 수도 있습니다. 이벤트는 이러한 방식으로 발생됩니다.

ActiveX 컨트롤의 활성 및 비활성 상태

컨트롤에는 활성 상태와 비활성 상태라는 두 가지 기본 상태가 있습니다. 일반적으로 이러한 상태는 컨트롤에 창이 있는지 여부에 따라 구분됩니다. 활성 컨트롤에는 창이 있으며 비활성 컨트롤에는 창이 없습니다. 창 없는 활성화가 도입되면서 이러한 구분이 더 이상 일반적인 것은 아니지만 아직도 많은 컨트롤에 이러한 구분이 적용됩니다.

창 없는 컨트롤이 활성화되면 해당 컨트롤은 컨트롤 컨테이너에서 마우스 캡처, 키보드 포커스, 스크롤 및 다른 창 서비스를 호출합니다. 비활성 컨트롤에 대해 마우스 상호 작용을 제공할 수 있으며 활성화될 때까지 기다렸다가 창을 만드는 컨트롤도 만들 수 있습니다.

창이 있는 컨트롤이 활성화되면 해당 컨트롤은 컨트롤 컨테이너, 컨트롤 사용자 및 Windows와 완벽하게 상호 작용할 수 있습니다. 다음 그림은 ActiveX 컨트롤, 컨트롤 컨테이너 및 운영 체제 간의 통신 방식을 보여 줍니다.

창 있는 ActiveX 컨트롤의 Windows 메시지 처리(활성화 시)

Serialization

데이터에 대한 serialization 기능(지속성이라고도 함)을 사용하면 컨트롤이 해당 속성 값을 영구 저장소에 쓸 수 있습니다. 그런 다음 해당 저장소에서 개체의 상태를 읽어 컨트롤을 다시 만들 수 있습니다.

그러나 컨트롤은 저장소 매체에 대한 액세스 권한을 얻을 수 없습니다. 대신 해당 컨트롤의 컨테이너가 적당한 시기에 사용할 저장소 매체를 컨트롤에 제공합니다. serialization에 대한 자세한 내용은 MFC ActiveX 컨트롤: Serializing 문서를 참조하십시오. serialization 최적화에 대한 자세한 내용은 ActiveX 컨트롤: 최적화의 지속성 및 초기화 최적화를 참조하십시오.

ActiveX 컨트롤 클래스 및 도구 설치

Visual C++를 설치할 때 설치할 항목에 ActiveX 컨트롤이 선택되어 있으면(기본적으로 선택됨) MFC ActiveX 컨트롤 클래스와 정식 버전 및 디버그 버전의 ActiveX 컨트롤 런타임 DLL이 자동으로 설치됩니다.

ActiveX 컨트롤 클래스 및 도구는 기본적으로 다음과 같이 \Program Files\Microsoft Visual Studio .NET의 하위 디렉터리에 설치됩니다.

  • \Common7\Tools

    Test Container 파일(TstCon32.exe와 해당 도움말 파일)이 들어 있습니다.

  • \Vc7\atlmfc\include

    MFC를 사용하여 ActiveX 컨트롤을 개발하는 데 필요한 포함 파일이 들어 있습니다.

  • \Vc7\atlmfc\src\mfc

    MFC로 작성된 특정 ActiveX 컨트롤 클래스의 소스 코드가 들어 있습니다.

  • \Vc7\atlmfc\lib

    MFC를 사용하여 ActiveX 컨트롤을 개발하는 데 필요한 라이브러리가 들어 있습니다.

또한 MFC ActiveX 컨트롤 샘플도 들어 있습니다. 이 샘플에 대한 자세한 내용은 컨트롤 샘플: MFC 기반 ActiveX 컨트롤을 참조하십시오.

http://cafe.naver.com/crazysystem/192