À⵿»ç´Ï ½ÃÀå¿¡
create: 2004/07/17, last update: 2004/08/25

ATL ·Î ÀÛ¼ºÇÑ Active X ÄÁÆ®·ÑÀÇ »ùÇÃ


ATL À» »ç¿ëÇØ , ÇÁ·ÓÆÛƼ ÆäÀÌÁö , Á¢¼Ó Æ÷ÀÎÆ® , thread¸¦ ½ÇÀåÇÑ Active X ÄÁÆ®·ÑÀ» ¸¸µé ±âȸ°¡ ÀÖ¾úÀ¸¹Ç·Î , ÀÚ½ÅÀÇ ¸Þ¸ð¿¡ »ùÇÃÀ» ³²°å½À´Ï´Ù.
µ¡ºÙ¿© ÀÌÇÏÀÇ ¼³¸í¿¡¼­´Â VC++ 6 À» »ç¿ëÇÏ°í ÀÖ½À´Ï´Ù.
ÄÁÆ®·ÑÀÇ ÀÛ¼º
VC À» ±âµ¿ÇØ , ¸Þ´º·ÎºÎÅÍ [ÆÄÀÏ] - [½Å±Ô ÀÛ¼º] À» ¼±ÅÃÇØ ,[½Å±Ô ÀÛ¼º] ´ÙÀ̾ó·Î±×¸¦ Ç¥½ÃÇÕ´Ï´Ù. [ÇÁ·ÎÁ§Æ®] ÅÇÀ¸·Î ,[ATL COM AppWizard] ¸¦ ¼±ÅÃÇØ , ÇÁ·ÎÁ§Æ®¸íÀ» Àû´çÇÏ°Ô (¿©±â¿¡¼­´Â atlctrlsample À¸·Î Çß´ø) ÀÔ·ÂÇØ ,[OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

½Å±Ô ÀÛ¼º ´ÙÀ̾ó·Î±×

[ATL COM AppWizard ½ºÅÜ 1/1] ¿¡¼­ , ¼­¹ö ŸÀÔÀ» ´ÙÀ̳ª¹Í ¸µÅ© ¶óÀ̺귯¸® (DLL) ·Î ÇØ ,MFC ÀÇ ¼­Æ÷Æ®¿¡ üũ¸¦ ³Ö°í (MFC ¸¦ »ç¿ëÇÏÁö ¾Ê´Â °æ¿ì´Â , ´ç¿¬È÷ üũÀÇ ÇÊ¿ä´Â ¾ø½À´Ï´Ù),[Á¾·á] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

ATL COM AppWizard ½ºÅÜ 1/1

È®ÀÎÀ» À§ÇÑ [½Å±Ô ÇÁ·ÎÁ§Æ® Á¤º¸] ·Î [OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

½Å±Ô ÇÁ·ÎÁ§Æ® Á¤º¸

´ÙÀ½¿¡ ÀÛ¼ºÇÏ´Â ÄÁÆ®·Ñ·ÎºÎÅÍ , Á¢¼Ó Æ÷ÀÎÆ®¸¦ »ç¿ëÇØ À̺¥Æ® ÅëÁöÇÒ ¶§¿¡ »ç¿ëÇÏ´Â ATL ¿ÀºêÁ§Æ®¸¦ ÀÛ¼ºÇÕ´Ï´Ù.
¸Þ´º·ÎºÎÅÍ [»ðÀÔ] - [ATL ¿ÀºêÁ§Æ®ÀÇ ½Å±Ô ÀÛ¼º] À» ¼±ÅÃÇØ [ATL ¿ÀºêÁ§Æ® À§Àúµå] ¸¦ Ç¥½ÃÇÕ´Ï´Ù.
[Ä«Å×°í¸®] ¿¡ ¿ÀºêÁ§Æ® ,[¿ÀºêÁ§Æ®] ¿¡ ½ÉÇà ¿ÀºêÁ§Æ®¸¦ ¼±ÅÃÇØ ,[´ÙÀ½¿¡] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

ATL ¿ÀºêÁ§Æ® À§Àúµå

Ç¥½ÃµÇ´Â [ATL ¿ÀºêÁ§Æ® À§ÀúµåÀÇ ÇÁ·ÓÆÛƼ] ÀÇ [À̸§] ÅÇÀ¸·Î [¼îÆ® ³×ÀÓ] À» Àû´çÇÏ°Ô (¿©±â¿¡¼­´Â SampleParam À¸·Î Çß´ø) ÀÔ·ÂÇØ ,[¾ÖÆ®¸®ºäÆ®(attribute)] ÅÇÀ¸·Î [thread ¸ðµ¨] À» ¾ÆÆÄÆ®¸ÕÆ®¿¡ ,[ÀÎÅÍÆäÀ̽º] ¸¦ µà¾ó , [¾Æ±×¸®°ÔÀ̼Ç] À» ³× ·Î ÇØ ,[OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

ATL ¿ÀºêÁ§Æ® À§ÀúµåÀÇ ÇÁ·ÓÆÛƼ - À̸§

ATL ¿ÀºêÁ§Æ® À§ÀúµåÀÇ ÇÁ·ÓÆÛƼ - ¾ÖÆ®¸®ºäÆ®(attribute)

´ÙÀ½¿¡ ÄÁÆ®·ÑÀ» ÀÛ¼ºÇÕ´Ï´Ù.
¸Þ´º·ÎºÎÅÍ [»ðÀÔ] - [ATL ¿ÀºêÁ§Æ®ÀÇ ½Å±Ô ÀÛ¼º] À» ¼±ÅÃÇØ [ATL ¿ÀºêÁ§Æ® À§Àúµå] ¸¦ Ç¥½ÃÇÕ´Ï´Ù.
[ÄÁÆ®·Ñ] ¿¡ ¿ÀºêÁ§Æ® ,[¿ÀºêÁ§Æ®] ¿¡ Ç® ÄÁÆ®·ÑÀ» ¼±ÅÃÇØ ,[´ÙÀ½¿¡] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

ATL ¿ÀºêÁ§Æ® À§Àúµå

Ç¥½ÃµÇ´Â [ATL ¿ÀºêÁ§Æ® À§ÀúµåÀÇ ÇÁ·ÓÆÛƼ] ÀÇ [À̸§] ÅÇÀ¸·Î [¼îÆ® ³×ÀÓ] À» Àû´çÇÏ°Ô (¿©±â¿¡¼­´Â SampleCtrl À¸·Î Çß´ø) ÀÔ·ÂÇØ ,[¾ÖÆ®¸®ºäÆ®(attribute)] ÅÇÀ¸·Î [thread ¸ðµ¨] À» ¾ÆÆÄÆ®¸ÕÆ®¿¡ ,[ÀÎÅÍÆäÀ̽º] ¸¦ µà¾ó , [¾Æ±×¸®°ÔÀ̼Ç] À» ³×¿¡ ,[ISupportErrorInfo ¼­Æ÷Æ®] ¿Í [connection Æ÷ÀÎÆ®ÀÇ ¼­Æ÷Æ®] ¿¡ üũ¸¦ ³Ö¾î [OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.
¡Ø[±× ¿Ü],[½ºÅå ÇÁ·ÓÆÛƼ] ´Â µðÆúÆ®ÀΠäÀÔ´Ï´Ù.

ATL ¿ÀºêÁ§Æ® À§ÀúµåÀÇ ÇÁ·ÓÆÛƼ - À̸§

ATL ¿ÀºêÁ§Æ® À§ÀúµåÀÇ ÇÁ·ÓÆÛƼ - ¾ÖÆ®¸®ºäÆ®(attribute)

[ClassView] ¿¡ ÀÛ¼ºµÈ Ŭ·¡½º°¡ Ç¥½ÃµÇ°í ÀÖ´Â °ÍÀ» È®ÀÎÇØ ÁÖ¼¼¿ä.

ClassView

¿ì¼± , ¸Þ´º·ÎºÎÅÍ [ºôµå] - [ºôµå] ¸¦ ¼±ÅÃÇØ , ºôµå ÇØ ÁÖ¼¼¿ä. ¶óÀ̺귯¸®¿¡ ÃÖ½ÅÀÇ °Í SDK À» »ç¿ëÇÏ°í ÀÖ´Â °æ¿ì ,
c:\documents and settings\bono\my documents\visual studio projects\atlctrlsample\samplectrl.h(97) : 
error C2668: 'InlineIsEqualGUID' : µ°ÊÞ°Û°ÄÞÇÔ¼öÀ� È£ÃâÀ» ÇØ°áÇÒ ¼ö°¡ ¾ø½À´Ï´Ù. 
(½Å±â´É ; ÍÙÌßÀ» ÂüÁ¶)
¿Í °°Àº ¿¡·¯°¡ µÇ´Â °æ¿ì°¡ ÀÖ½À´Ï´Ù. ¿øÀÎÀº ¸¶ÀÌÅ©·Î¼ÒÇÁÆ® ¼­Æ÷Æ® ±â¼ú Á¤º¸ 243298 - [VC60] C2668 ¿¡·¯°¡ InlineIsEqualGUID ÀÇ Á¤ÀÇ ºÎºÐ¿¡¼­ ¹ß»ý À¸·Î ¸®Æ÷Æ® µÇ°í ÀÖ½À´Ï´Ù.
³ªÀÇ È¯°æ¿¡¼­µµ »õ·Î¿î SDK À» ÂüÁ¶ÇÏ°í ÀÖ±â (À§ÇØ)¶§¹®¿¡ , ÀÌ ¿¡·¯°¡ ³ª¿É´Ï´Ù. ¼­Æ÷Æ® ±â¼ú Á¤º¸¿¡¼­´Â ¸î°³ÀÇ È¸ÇÇ ¹æ¹ýÀÌ ¼Ò°³µÇ°í ÀÖ½À´Ï´Ù¸¸ , ³ª´Â ¾Æ·¡¿Í °°Àº ¹æ¹ýÀ» ¼±ÅÃÇß½À´Ï´Ù.

ÄÁÆ®·ÑÀÇ Å¬·¡½ºÀÎ CSampleCtrl ÀÇ Çì´õ CSampleCtrl.h ÀÇ °Í ISupportsErrorInfo ÀÇ ½ÇÀå ºÎºÐ InterfaceSupportsErrorInfo() ÀÇ °Í InlineIsEqualGUID() À» È£ÃâÇÏ°í ÀÖ´Â °³¼Ò¿¡ ATL ÀÇ InlineIsEqualGUID() ¸¦ »ç¿ëÇϵµ·Ï , ½Äº°ÀÚ ATL:: ¸¦ ºÎ°¡Çß½À´Ï´Ù.
    STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
    {
        static const IID* arr[] = 
        {
            &IID_ISampleCtrl,
        };
        for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
        {
            if (ATL::InlineIsEqualGUID(*arr[i], riid))
                return S_OK;
        }
        return S_FALSE;
    }
ÆíÁýÀÌ »ì¸é(ÀÚ) , ÀçÂ÷ ºôµå ÇØ ÁÖ¼¼¿ä.
À§Àúµå·Î ÄÁÆ®·ÑÀ» ÀÛ¼ºÇßÀ» ¶§¿¡ , ÇÁ·ÎÁ§Æ®ÀÇ µð·ºÅ丮³»¿¡ ÄÁÆ®·Ñ Å×½ºÆ®¿ëÀÇ °Í HTML ÀÌ »ý¼ºµÇ°í Àֱ⠶§¹®¿¡ (¿©±â¿¡¼­´Â SampleCtrl.htm) ºôµå°¡ ³¡³ª¸é(ÀÚ) , ÀÌ Å×½ºÆ® ÆäÀÌÁö¸¦ IE ·Î ¿­·Á , ÀÌÇÏ¿Í °°ÀÌ Ç¥½ÃµÇ¸é OK ÀÔ´Ï´Ù.
¡ØIE ÀÇ ¼³Á¤À¸·Î Active X ÄÁÆ®·ÑÀ» Ç¥½ÃÇÒ ¼ö ÀÖµµ·Ï ÇØ µÎ¾î ÁÖ¼¼¿ä.

IE À§¿¡¼­ Ç¥½ÃÇÑ ÄÁÆ®·Ñ

ÇÁ·ÓÆÛƼ¸¦ Ãß°¡ÇÏ´Â
ÇÁ·ÓÆÛƼ¸¦ Ãß°¡ÇÕ´Ï´Ù. ¿©±â¿¡¼­´Â µðÆúÆ®·Î ÄÁÆ®·Ñ¿¡ Ç¥½ÃµÇ°í Àִ ij¸¯ÅÍ ¶óÀÎ "ATL 3.0 : SampleCtrl" À» ÇÁ·ÓÆÛƼ·ÎºÎÅÍ ¼³Á¤ÇÒ ¼ö ÀÖµµ·Ï(µíÀÌ) ÇÕ´Ï´Ù.
ÃÖÃÊ·Î IDL ¿¡ÀÇ ÇÁ·ÓÆÛƼÀÇ Ãß°¡¿Í ´ëÀÀÇÏ´Â CSampleCtrl ÀÇ ¸Þ¼Òµå¸¦ Ãß°¡ÇÕ´Ï´Ù. [ClassView] ±×¸®°í ISampleCtrl ¸¦ ¿À¸¥ÂÊ Å¬¸¯ÇØ , Ç¥½ÃµÇ´Â pop-up menu·ÎºÎÅÍ [ÇÁ·ÓÆÛƼÀÇ Ãß°¡] ¸¦ ¼±ÅÃÇÕ´Ï´Ù.

ÇÁ·ÓÆÛƼ¸¦ Ãß°¡

[ÀÎÅÍÆäÀ̽º¿¡ ÇÁ·ÓÆÛƼ¸¦ Ãß°¡] ´ÙÀ̾ó·Î±×°¡ Ç¥½ÃµÇ±â ¶§¹®¿¡ ,[ÇÁ·ÓÆÛƼÀÇ Á¾·ù] ¿¡ BSTR,[ÇÁ·ÓÆÛƼ¸í] ¿¡ DisplayString ¸¦ ¼³Á¤ÇØ ,[OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

ÀÎÅÍÆäÀ̽º¿¡ ÇÁ·ÓÆÛƼ¸¦ Ãß°¡

´ÙÀ½¿¡ , ÇÁ·ÓÆÛƼġ¸¦ º¸Á¸Çϱâ À§ÇÑ º¯¼ö ¸â¹ö¸¦ Ãß°¡ÇÕ´Ï´Ù. SampleCtrl.h (À»)¸¦ ¿­¾î , Ŭ·¡½º Á¤ÀÇ¿¡ CString ÀÇ º¯¼ö m_DisplayString ¸¦ Ãß°¡ÇÕ´Ï´Ù.
            (rc.left + rc.right) / 2, 
            (rc.top + rc.bottom) / 2, 
            pszText, 
            lstrlen(pszText));

        return S_OK;
    }

private:
    // ÇÁ·ÓÆÛƼ DisplayString ÀÇ °ªÀ» º¸°ü À¯ÁöÇÑ´Ù. 
    CString m_DisplayString;
};

#endif //__SAMPLECTRL_H_
´ÙÀ½¿¡ , ÇÁ·ÓÆÛƼġ¸¦ m_DisplayString ·Î ¼³Á¤/ÃëµæÇÏ´Â Äڵ带 ¾¹´Ï´Ù.
Á¶±Ý Àü , ÇÁ·ÓÆÛƼ¸¦ Ãß°¡ÇßÀ» ¶§¿¡ CSampleCtrl.cpp ¿¡ get_DisplayString(),put_DisplayString() °¡ Ãß°¡µÇ°í Àֱ⠶§¹®¿¡ , ¿©±â¿¡ Äڵ带 Ãß°¡ÇÕ´Ï´Ù.

Ãß°¡µÈ ¸Þ¼Òµå

¿©±â¿¡¼­´Â ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇß½À´Ï´Ù.
STDMETHODIMP CSampleCtrl::get_DisplayString(BSTR *pVal)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState())

    *pVal = m_DisplayString.AllocSysString();

    return S_OK;
}

STDMETHODIMP CSampleCtrl::put_DisplayString(BSTR newVal)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState())

    m_DisplayString = newVal;
    // ÄÁÆ®·ÑÀÌ º¯°æµÈ °ÍÀ» ¼³Á¤ÇÑ´Ù. 
    SetDirty(TRUE);
    // À繦ȭ ÇÏ°í ½ÍÀº °ÍÀ» ÄÁÅ×À̳ʿ¡ ÅëÁöÇÑ´Ù. 
    FireViewChange();

    return S_OK;
}
´ÙÀ½¿¡ m_DisplayString ¸¦ Ç¥½ÃÇϵµ·Ï(µíÀÌ) µðÆúÆ®ÀÇ ¹¦È­ Äڵ带 º¯°æÇÕ´Ï´Ù.
CSampleCtrl.h ÀÇ OnDraw() ¸¦ ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇß½À´Ï´Ù.
    HRESULT OnDraw(ATL_DRAWINFO& di)
    {
        RECT& rc = *(RECT*)di.prcBounds;
        Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);

        SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);
        // ÇÁ·ÓÆÛƼġ¸¦ Ç¥½ÃÇϵµ·Ï(µíÀÌ) º¯°æÇÑ´Ù. 
        //LPCTSTR pszText = _T("ATL 3.0 : SampleCtrl");
        LPCTSTR pszText = m_DisplayString;
        TextOut(di.hdcDraw, 
            (rc.left + rc.right) / 2, 
            (rc.top + rc.bottom) / 2, 
            pszText, 
            lstrlen(pszText));

        return S_OK;
    }
ÀÌ°ÍÀ¸·Î , ÇÁ·ÓÆÛƼ¸¦ Ç¥½ÃÇÒ ¼ö ÀÖ°Ô µË´Ï´Ù. ¶ó°í ÁÁÀº ½ÍÀº °÷ÀÔ´Ï´Ù¸¸ , ¾ÆÁ÷ÀÔ´Ï´Ù. IE µî¿¡¼­ ÇÁ·ÓÆÛƼ¸¦ ¼³Á¤ÇÏ°í ½ÍÀº °æ¿ì ,IPersistPropertyBag ¸¦ ½ÇÀåÇÒ ÇÊ¿ä°¡ ÀÖ½À´Ï´Ù. ±×·¸´Ù°í Çصµ ,ATL ±×·³ IPersistPropertyBagImpl À̶ó°í ÇÏ´Â µðÆúÆ®ÀÇ ½ÇÀåÀÌ Á¦°øµÇ°í Àֱ⠶§¹®¿¡ , ÀÚ½ÅÀÇ ÄÁÆ®·Ñ Ŭ·¡½º¿¡¼­ ÀÌ°ÍÀ» °è½ÂÇÏ´Â °Í¸¸À¸·Î ³¡³³´Ï´Ù.
CSampleCtrl.h ÀÇ Å¬·¡½º Á¤ÀÇÀÇ °è½ÂÇϴ Ŭ·¡½º¸¦ ±â¼úÇÏ´Â ºÎºÐ¿¡
public IPersistPropertyBagImpl<CSampleCtrl> // ÇÁ·ÓÆÛƼ¸¦ Ãë±ÞÇÏ´Â
À» Ãß°¡ÇÕ´Ï´Ù.
class ATL_NO_VTABLE CSampleCtrl : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public IDispatchImpl<ISampleCtrl, &IID_ISampleCtrl, &LIBID_ATLCTRLSAMPLELib>,
    public CComControl<CSampleCtrl>,
    public IPersistStreamInitImpl<CSampleCtrl>,
    public IOleControlImpl<CSampleCtrl>,
    public IOleObjectImpl<CSampleCtrl>,
    public IOleInPlaceActiveObjectImpl<CSampleCtrl>,
    public IViewObjectExImpl<CSampleCtrl>,
    public IOleInPlaceObjectWindowlessImpl<CSampleCtrl>,
    public ISupportErrorInfo,
    public IConnectionPointContainerImpl<CSampleCtrl>,
    public IPersistStorageImpl<CSampleCtrl>,
    public ISpecifyPropertyPagesImpl<CSampleCtrl>,
    public IQuickActivateImpl<CSampleCtrl>,
    public IDataObjectImpl<CSampleCtrl>,
    public IProvideClassInfo2Impl<&CLSID_SampleCtrl, &DIID__ISampleCtrlEvents, &LIBID_ATLCTRLSAMPLELib>,
    public IPropertyNotifySinkCP<CSampleCtrl>,
    public CComCoClass<CSampleCtrl, &CLSID_SampleCtrl>,
    public IPersistPropertyBagImpl<CSampleCtrl>    // ÇÁ·ÓÆÛƼ¸¦ Ãë±ÞÇÏ´Â
{
public:
    CSampleCtrl()
    {
°Ô´Ù°¡ Ŭ·¡½º Á¤ÀÇÁßÀÇ °Í BEGIN_COM_MAP(CSampleCtrl) À¸·ÎºÎÅÍ END_COM_MAP() ÀÇ »çÀÌ¿¡
COM_INTERFACE_ENTRY(IPersistPropertyBag)
¸¦ Ãß°¡ÇÕ´Ï´Ù.
    COM_INTERFACE_ENTRY(IConnectionPointContainer)
    COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
    COM_INTERFACE_ENTRY(IQuickActivate)
    COM_INTERFACE_ENTRY(IPersistStorage)
    COM_INTERFACE_ENTRY(IDataObject)
    COM_INTERFACE_ENTRY(IProvideClassInfo)
    COM_INTERFACE_ENTRY(IProvideClassInfo2)
    COM_INTERFACE_ENTRY(IPersistPropertyBag)
END_COM_MAP()
¸¶Áö¸·À¸·Î , ÇÁ·ÓÆÛƼÀÇ ¸íĪÀ» Á¤ÀÇÇϱâ À§ÇØ(¶§¹®¿¡) ,BEGIN_PROP_MAP(CSampleCtrl) ·ÎºÎÅÍ END_PROP_MAP() ÀÇ »çÀÌ¿¡
PROP_ENTRY("DisplayString", 1, GetObjectCLSID())
¸¦ Ãß°¡ÇÕ´Ï´Ù. µ¡ºÙ¿© Á¦ 2 ÀμöÀÇ °Í 1 Àº , À§Àúµå¿¡ ÀÇÇØ IDL ¿¡ Ãß°¡µÈ ÇÁ·ÓÆÛƼ DisplayString ÀÇ ÇÁ·ÓÆÛƼ ID ÀÔ´Ï´Ù.
BEGIN_PROP_MAP(CSampleCtrl)
    PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
    PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
    PROP_ENTRY("DisplayString", 1, GetObjectCLSID())
    // Example entries
    // PROP_ENTRY("Property Description", dispid, clsid)
    // PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()
ºôµå°¡ ³¡³ª¸é(ÀÚ) , ÇÁ·ÓÆÛƼġ¸¦ ¼³Á¤Çϵµ·Ï(µíÀÌ) ÄÁÆ®·Ñ Å×½ºÆ®¿ëÀÇ °Í HTML (SampleCtrl.htm) À» ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇÕ´Ï´Ù.
<HTML>
<HEAD>
<TITLE>¿ÀºêÁ§Æ® SampleCtrl ¿ë ATL 3.0 Å×½ºÆ® ÆäÀÌÁö</TITLE>
</HEAD>
<BODY>
<OBJECT ID="SampleCtrl" CLASSID="CLSID:B94F2CEA-B317-4CEC-8448-B9E733BE663A">
<PARAM NAME="DisplayString" VALUE="¾È³çÇϼ¼¿ä">
</OBJECT>
</BODY>
</HTML>
ÆíÁýÀÌ ³¡³ª¸é(ÀÚ) , Å×½ºÆ® ÆäÀÌÁö¸¦ IE ·Î ¿­·Á ÁÖ¼¼¿ä. ÀÌÇÏ¿Í °°ÀÌ Ç¥½ÃµÇ¸é OK ÀÔ´Ï´Ù.

IE ±×¸®°í Ç¥½ÃÇÑ ÄÁÆ®·Ñ

µ¡ºÙ¿© ÇÁ·ÓÆÛƼ¸¦ ½ÇÀåÇϸé(ÀÚ) , ÀÌÇÏ¿Í °°Àº ´ÙÀ̾ó·Î±×°¡ ³ª¿À±â ½ÃÀÛÇÏ°Ô µË´Ï´Ù.

°æ°í ´ÙÀ̾ó·Î±×

ÀÌ°ÍÀº , ÄÁÆ®·ÑÀÌ ¾ÈÀüÀ̶ó°í ¸¶Å·µÇ¾î ÀÖÁö ¾Ê±â ¶§¹®ÀÔ´Ï´Ù. ÀÌ°ÍÀ» ¸¶Å© Çϱâ À§Çؼ­ IObjectSafety ¸¦ ½ÇÀåÇÕ´Ï´Ù. ATL ¿¡´Â IObjectSafetyImpl ÀÌ Á¦°øµÇ°í Àֱ⠶§¹®¿¡ , Åë»óÀº , ÀÌ°ÍÀ» ÄÁÆ®·Ñ Ŭ·¡½º¿¡¼­ °è½ÂÇÒ »ÓÀÔ´Ï´Ù.
CSampleCtrl.h ÀÇ Å¬·¡½º Á¤ÀÇÀÇ °è½ÂÇϴ Ŭ·¡½º¸¦ ±â¼úÇÏ´Â ºÎºÐ¿¡
public IObjectSafetyImpl<CSampleCtrl, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>
¸¦ Ãß°¡ÇÕ´Ï´Ù. ¿©±â¿¡¼­´Â , ½ºÅ©¸³Æ®ÀÇ ¾ÈÀü¼º°ú ÃʱâÈ­½ÃÀÇ µ¥ÀÌÅÍÀÇ ¾ÈÀü¼ºÀ» º¸ÁõÇÏ°í ÀÖ½À´Ï´Ù.
class ATL_NO_VTABLE CSampleCtrl : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public IDispatchImpl<ISampleCtrl, &IID_ISampleCtrl, &LIBID_ATLCTRLSAMPLELib>,
    public CComControl<CSampleCtrl>,
    public IPersistStreamInitImpl<CSampleCtrl>,
    public IOleControlImpl<CSampleCtrl>,
    public IOleObjectImpl<CSampleCtrl>,
    public IOleInPlaceActiveObjectImpl<CSampleCtrl>,
    public IViewObjectExImpl<CSampleCtrl>,
    public IOleInPlaceObjectWindowlessImpl<CSampleCtrl>,
    public ISupportErrorInfo,
    public IConnectionPointContainerImpl<CSampleCtrl>,
    public IPersistStorageImpl<CSampleCtrl>,
    public ISpecifyPropertyPagesImpl<CSampleCtrl>,
    public IQuickActivateImpl<CSampleCtrl>,
    public IDataObjectImpl<CSampleCtrl>,
    public IProvideClassInfo2Impl<&CLSID_SampleCtrl, &DIID__ISampleCtrlEvents, &LIBID_ATLCTRLSAMPLELib>,
    public IPropertyNotifySinkCP<CSampleCtrl>,
    public CComCoClass<CSampleCtrl, &CLSID_SampleCtrl>,
    public IPersistPropertyBagImpl<CSampleCtrl>,    // ÇÁ·ÓÆÛƼ¸¦ Ãë±ÞÇÏ´Â
    public IObjectSafetyImpl<CSampleCtrl, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>
{
public:
    CSampleCtrl()
    {
°Ô´Ù°¡ Ŭ·¡½º Á¤ÀÇÁßÀÇ °Í BEGIN_COM_MAP(CSampleCtrl) À¸·ÎºÎÅÍ END_COM_MAP() ÀÇ »çÀÌ¿¡
COM_INTERFACE_ENTRY(IObjectSafety)
¸¦ Ãß°¡ÇÕ´Ï´Ù.
    COM_INTERFACE_ENTRY(IConnectionPointContainer)
    COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
    COM_INTERFACE_ENTRY(IQuickActivate)
    COM_INTERFACE_ENTRY(IPersistStorage)
    COM_INTERFACE_ENTRY(IDataObject)
    COM_INTERFACE_ENTRY(IProvideClassInfo)
    COM_INTERFACE_ENTRY(IProvideClassInfo2)
    COM_INTERFACE_ENTRY(IPersistPropertyBag)
    COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()
ÇÁ·ÓÆÛƼ ÆäÀÌÁöÀÇ Ãß°¡
ÇÁ·ÓÆÛƼ ÆäÀÌÁö¿Í´Â VB µî¿¡¼­ ÄÁÆ®·ÑÀ» ÀÌ¿ëÇÒ ¶§¿¡ , ÇÁ·ÓÆÛƼġ¸¦ ´ÙÀ̾ó·Î±×·ÎºÎÅÍ ÀÔ·ÂÇÒ ¼ö ÀÖµµ·Ï(µíÀÌ) ÇÑ °ÍÀÔ´Ï´Ù.
¾Æ·¡´Â VB À¸·Î Ķ¸°´õ ÄÁÆ®·ÑÀÇ ÇÁ·ÓÆÛƼ ÆäÀÌÁö¸¦ Ç¥½ÃÇÑ ¿¹ÀÔ´Ï´Ù.

Ķ¸°´õ ÄÁÆ®·ÑÀÇ ÇÁ·ÓÆÛƼ ÆäÀÌÁö

¸Þ´º·ÎºÎÅÍ [»ðÀÔ] - [ATL ¿ÀºêÁ§Æ®ÀÇ ½Å±Ô ÀÛ¼º] À» ¼±ÅÃÇØ [ATL ¿ÀºêÁ§Æ® À§Àúµå] ¸¦ Ç¥½ÃÇÕ´Ï´Ù.
[Ä«Å×°í¸®] ¿¡ ÄÁÆ®·Ñ ,[¿ÀºêÁ§Æ®] ¿¡ ÇÁ·ÓÆÛƼ ÆäÀÌÁö¸¦ ¼±ÅÃÇØ ,[´ÙÀ½¿¡] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

ATL ¿ÀºêÁ§Æ® À§Àúµå

Ç¥½ÃµÇ´Â [ATL ¿ÀºêÁ§Æ® À§ÀúµåÀÇ ÇÁ·ÓÆÛƼ] ÀÇ [À̸§] ÅÇÀ¸·Î [¼îÆ® ³×ÀÓ] À» Àû´çÇÏ°Ô (¿©±â¿¡¼­´Â SampleCtrlPropPage À¸·Î Çß´ø) ÀÔ·ÂÇØ ,[string] ÅÇÀ¸·Î [ŸÀÌƲ] ¿¡ »ùÇà ÇÁ·ÓÆÛƼ ,[¹®¼­ÀÇ ¹®ÀÚ] ¿¡ »ùÇÃÀÇ ÇÁ·ÓÆÛƼ ÆäÀÌÁö , [ÇïÇÁ ÆÄÀÏ] À» Çϴ÷Π¼³Á¤ÇØ ,[OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.
¡Ø[¾ÖÆ®¸®ºäÆ®(attribute)] ´Â µðÆúÆ®ÀΠäÀÔ´Ï´Ù.

ATL ¿ÀºêÁ§Æ® À§ÀúµåÀÇ ÇÁ·ÓÆÛƼ - À̸§

ATL ¿ÀºêÁ§Æ® À§ÀúµåÀÇ ÇÁ·ÓÆÛƼ - string

ÇÁ·ÎÁ§Æ®¿¡ ÇÁ·ÓÆÛƼ ÆäÀÌÁö¿ëÀÇ ´ÙÀ̾ó·Î±×¿Í Ŭ·¡½º°¡ »ðÀԵ˴ϴÙ.
»ðÀÔµÈ ´ÙÀ̾ó·Î±×¸¦ º¸°Ú½À´Ï´Ù. [ResourceView] ±×¸®°í [Dialog] Æ®¸®¾Æ·¡ÀÇ °Í IDD_SAMPLECTRLPROPPAGE À» ¿­¾î ÁÖ¼¼¿ä.
ÇÁ·ÓÆÛƼ ÆäÀÌÁö¿ëÀÇ ´ÙÀ̾ó·Î±×°¡ Ãß°¡µÇ°í ÀÖ½À´Ï´Ù. µ¡ºÙ¿©¼­ , ÇÁ·ÓÆÛƼ ÆäÀÌÁö¿¡¼­´Â 1 °³ÀÇ ´ÙÀ̾ó·Î±×°¡ ½ÇÇà½Ã¿¡ Ç¥½ÃµÇ´Â ÇÁ·ÓÆÛƼ ÆäÀÌÁöÀÇ 1 °³ ÅÇ¿¡ »ó´çÇÕ´Ï´Ù. ¿¹¸¦ µé¸é , À§ÀÇ Ä¶¸°´õ ÄÁÆ®·ÑÀÇ ÇÁ·ÓÆÛƼ ÆäÀÌÁö¿Í °°ÀÌ [Àü¹Ý],[ÆùÆ®],[»ö] ÀÇ 3 »ìÀÇ ÅÇÀ» ÀÛ¼ºÇÏ°í ½ÍÀº °æ¿ì´Â ,3 °³ÀÇ ÇÁ·ÓÆÛƼ ÆäÀÌÁö (´ÙÀ̾ó·Î±×) ¸¦ ÀÛ¼ºÇÒ ÇÊ¿ä°¡ ÀÖ½À´Ï´Ù.

´ÙÀ̾˰í±× ¿¡µðÅÍ¿¡¼­ÀÇ Ç¥½Ã

ÀÌ°ÍÀ» ÆíÁýÇØ ,DisplayString ¿ë¹«ÀÇ ÅؽºÆ® ¹Ú½º¸¦ ÀÛ¼ºÇÕ´Ï´Ù.
ÀÛ¼ºÇÑ ÅؽºÆ® ¹Ú½ºÀÇ °Í ID Àº IDC_DISPLAY_STRING À¸·Î Çß½À´Ï´Ù.

ÅؽºÆ® ¹Ú½º¿Í ÇÁ·ÓÆÛƼ

´ÙÀ½¿¡ ÇÁ·ÓÆÛƼ DisplayString ÀÇ ³»¿ëÀ» ´ÙÀ̾ó·Î±×·ÎºÎÅÍ ÆíÁýÇÒ ¼ö ÀÖµµ·Ï(µíÀÌ) Äڵ带 ¾¹´Ï´Ù.
[ClassView] (À¸)·ÎºÎÅÍ CSampleCtrlPropPage ¸¦ ¿À¸¥ÂÊ Å¬¸¯ÇØ , Ç¥½ÃµÇ´Â pop-up menu·ÎºÎÅÍ [Windows ¸Þ¼¼Áö Çڵ鷯ÀÇ Ãß°¡] ¸¦ ¼±ÅÃÇÕ´Ï´Ù.

Windows ¸Þ¼¼Áö Çڵ鷯ÀÇ Ãß°¡

Ç¥½ÃµÈ [CSampleCtrlPropPage Ŭ·¡½º¿¡ ½Å±Ô À©µµ¿ì ¸Þ¼¼Áö¿Í À̺¥Æ® Çڵ鷯¸¦ Ãß°¡] ´ÙÀ̾ó·Î±×·Î , [Ŭ·¡½º¿¡¼­ »ç¿ë °¡´ÉÇÏ°Ô ÇÏ´Â ¸Þ¼¼ÁöÀÇ ÇÊÅÍ] ¿¡ ´ÙÀ̾ó·Î±× ¸¦ ¼±ÅÃÇØ ,[½Å±Ô À©µµ¿ì ¸Þ¼¼Áö/À̺¥Æ®] ·Î WM_INITDIALOG ¸¦ ´õºí Ŭ¸¯ ÇØ [±âÁ¸ÀÇ ¸Þ¼¼Áö/À̺¥Æ® Çڵ鷯] ¿¡ À̵¿½ÃÄÑ,[OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

CSampleCtrlPropPage Ŭ·¡½º¿¡ ½Å±Ô À©µµ¿ì ¸Þ¼¼Áö¿Í À̺¥Æ® Çڵ鷯¸¦ Ãß°¡

Ãß°¡µÇ¾ú´Ù OnInitDialog() ¸¦ ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇÕ´Ï´Ù.
    LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());

        if (m_nObjects <= 0) {
            // ´ç ÇÁ·ÓÆÛƼ ÆäÀÌÁö¿¡ °ü·ÃÁþ°í µÇ°í ÀÖ´Â ¿ÀºêÁ§Æ®°¡ ¾ø´Â °æ¿ì ,
            return 0;
        }

        // ÇÁ·ÓÆÛƼÀÇ °ªÀ» CSampleCtrl ·ÎºÎÅÍ ÃëµæÇØ ,
        // ´ÙÀ̾ó·Î±×»óÀÇ ÄÁÆ®·Ñ¿¡ ¹Ý¿µÇÑ´Ù. 
        CComQIPtr<ISampleCtrl, &IID_ISampleCtrl> pSampleCtrl(m_ppUnk[0]);

        CComBSTR displayString;

        if (SUCCEEDED(pSampleCtrl->get_DisplayString(&displayString.m_str))) {
            SetDlgItemText(IDC_DISPLAY_STRING, CString(displayString));
        }

        // º¯°æ Ç÷¡±×¸¦ ÃʱâÈ­ÇØ µÐ´Ù. 
        SetDirty(FALSE);

        return 0;
    }
´ÙÀ½¿¡ ÇÁ·ÓÆÛƼ ÆäÀÌÁö·Î [Àû¿ë] ¶Ç´Â [OK] ÀÌ Å¬¸¯µÇ¾úÀ» ¶§ÀÇ Çڵ鷯 Apply() ¸¦ ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇÕ´Ï´Ù.
    STDMETHOD(Apply)(void)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
        
        // ´ÙÀ̾ó·Î±× ÄÁÆ®·ÑÀÇ °ªÀ» , ´ç ÇÁ·ÓÆÛƼ ÆäÀÌÁö¿¡
        // °ü·ÃÁöÀ» ¼ö ÀÖ°í ÀÖ´Â CSampleCtrl ¿ÀºêÁ§Æ® ¸ðµÎ¿¡°Ô ¹Ý¿µÇÑ´Ù. 
        BOOL bFailure = FALSE;

        for (UINT i = 0; i < m_nObjects; i++) {

            CComQIPtr<ISampleCtrl, &IID_ISampleCtrl> pSampleCtrl(m_ppUnk[i]);

            CComBSTR displayString;

            GetDlgItemText(IDC_DISPLAY_STRING, displayString.m_str);
            if (FAILED(pSampleCtrl->put_DisplayString(displayString))) {
                bFailure = TRUE;
            }
        }

        if (bFailure) {
            // ½ÇÆа¡ ÀÖ¾úÀ» ¶§´Â , ¿¡·¯ Á¤º¸¸¦ ÃëµæÇØ Ç¥½ÃÇÑ´Ù. 
            CComPtr<IErrorInfo> pError;
            CComBSTR strError;
            GetErrorInfo(0, &pError);
            pError->GetDescription(&strError);
            MessageBox(CString(strError), _T("ÇÁ·ÓÆÛƼÀÇ º¸Á¸¿¡ ½ÇÆÐÇß½À´Ï´Ù. "), MB_OK | MB_ICONEXCLAMATION);
            return E_FAIL;
        }

        m_bDirty = FALSE;
        return S_OK;
    }
ÅؽºÆ® ¹Ú½º°¡ º¯°æµÇ¾úÀ» ¶§¿¡ º¯°æ Ç÷¡±×¸¦ ¼³Á¤Çϵµ·Ï(µíÀÌ) Äڵ带 Ãß°¡ÇÕ´Ï´Ù.
[ClassView] (À¸)·ÎºÎÅÍ CSampleCtrlPropPage ¸¦ ¿À¸¥ÂÊ Å¬¸¯ÇØ , Ç¥½ÃµÇ´Â pop-up menu·ÎºÎÅÍ [Windows ¸Þ¼¼Áö Çڵ鷯ÀÇ Ãß°¡] ¸¦ ¼±ÅÃÇÕ´Ï´Ù.
Ç¥½ÃµÇ´Â [CSampleCtrlPropPage Ŭ·¡½º¿¡ ½Å±Ô À©µµ¿ì ¸Þ¼¼Áö¿Í À̺¥Æ® Çڵ鷯¸¦ Ãß°¡] ´ÙÀ̾ó·Î±×·Î , [Ŭ·¡½º ¶Ç´Â ¿ÀºêÁ§Æ®] ·ÎºÎÅÍ IDC_DISPLAY_STRING ¸¦ ¼±ÅÃÇØ ,[½Å±Ô À©µµ¿ì ¸Þ¼¼Áö/À̺¥Æ®] ¿¡ ÅؽºÆ® ¹Ú½º¿ëÀÇ ¸Þ¼¼Áö°¡ Ç¥½ÃµÇ¸é(ÀÚ) , ±× Áß¿¡¼­ EN_CHANGE ¸¦ ´õºí Ŭ¸¯ ÇÕ´Ï´Ù.
[¸â¹ö ÇÔ¼öÀÇ Ãß°¡] ´ÙÀ̾ó·Î±×°¡ Ç¥½ÃµÇ¹Ç·Î ,[¸â¹ö ÇÔ¼ö¸í] ¿¡ OnChangeDisplayString ¶ó°í ÀÔ·ÂÇØ , [OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

¸â¹ö ÇÔ¼öÀÇ Ãß°¡

[±âÁ¸ÀÇ ¸Þ¼¼Áö/À̺¥Æ® Çڵ鷯] ¿¡ EN_CHANGE °¡ À̵¿ÇϹǷΠ, ±×´ë·Î [OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

CSampleCtrlPropPage Ŭ·¡½º¿¡ ½Å±Ô À©µµ¿ì ¸Þ¼¼Áö¿Í À̺¥Æ® Çڵ鷯¸¦ Ãß°¡

Ãß°¡µÇ¾ú´Ù OnChangeDisplayString() ¸¦ ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇÕ´Ï´Ù.
    LRESULT OnChangeDisplayString(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
        SetDirty(TRUE);
        return 0;
    }
CSampleCtrl ÀÇ ÇÁ·ÓÆÛƼ¿Í ÀÌ ÇÁ·ÓÆÛƼ ÆäÀÌÁö¸¦ °ü·ÃÁþ±â À§Çؼ­(¶§¹®¿¡) ,CSampleCtrl ÀÇ Å¬·¡½º Á¤ÀÇÀÇ °Í BEGIN_PROP_MAP() À¸·ÎºÎÅÍ END_PROP_MAP ÀÇ »çÀÌÀÇ °Í
PROP_ENTRY("DisplayString", 1, GetObjectCLSID())
À» ,
PROP_ENTRY("DisplayString", 1, CLSID_SampleCtrlPropPage)
°ú °°ÀÌ °íÃÄ ¾¹´Ï´Ù. °íÃÄ ¾²°í°¡ ³¡³ª¸é(ÀÚ) ºôµå ÇØ ÁÖ¼¼¿ä.
ºôµå°¡ ³¡³ª¸é(ÀÚ) , Áï½Ã ÄÁÆ®·ÑÀ» Å×½ºÆ®ÇØ º¸°Ú½À´Ï´Ù. ¿©±â¿¡¼­´Â ,VB À» »ç¿ëÇÏ°í ÀÖ½À´Ï´Ù.
ÀÛ¼ºÇÑ ÄÁÆ®·ÑÀ» Æû¿¡ ½Ç¾î ÇÁ·ÓÆÛƼ ÆäÀÌÁö¸¦ Ç¥½ÃÇØ ,DisplayString ÀÇ °ªÀ» º¯°æÇØ , Àû¿ëÀ» Ŭ¸¯ÇØ º¸¼¼¿ä. ÄÁÆ®·Ñ·Î ¼³Á¤ÇÑ Ä³¸¯ÅÍ ¶óÀÎÀÌ º¯°æµÇ´Â °ÍÀÌ È®ÀÎÇÒ ¼ö ÀÖ´Ù°í »ý°¢ÇÕ´Ï´Ù.
ÇÁ·ÓÆÛƼ ÆäÀÌÁö VB µ¥ÀÚÀ̳ª¿¡¼­ÀÇ Ç¥½Ã
Á¢¼Ó Æ÷ÀÎÆ®ÀÇ Ãß°¡
ÃÖÃÊ·Î Á¢¼Ó Æ÷ÀÎÆ®¸¦ »ç¿ëÇØ À̺¥Æ® ÅëÁöÇÒ ¶§¿¡ »ç¿ëÇÏ´Â ATL ¿ÀºêÁ§Æ®¸¦ ¿Ï¼º½Ãŵ´Ï´Ù.
À̺¥Æ® ÅëÁö·Î »ç¿ëÇÏ´Â ¿ÀºêÁ§Æ®¶õ , ¸ÕÀúÄÁÆ®·ÑÀÇ ÀÛ¼º À¸·Î Á¤ÀǸ¸ µÇ¾î ÀÖ¾ú´Ù SampleParam ÀÔ´Ï´Ù.
SampleParam ÀÇ ÇÁ·ÓÆÛƼ·Î¼­ À̺¥Æ® ÅëÁö·Î ÅëÁöÇÏ°í ½ÍÀº ³»¿ëÀ» Á¤ÀÇÇÕ´Ï´Ù. ¹¹µçÁö ÁÁ½À´Ï´Ù¸¸ , ¿©±â¿¡¼­´Â , ij¸¯ÅÍ ¶óÀÎÀ» °Ç³×ÁÖµµ·Ï(µíÀÌ) ÇÏ°í ½Í´Ù°í »ý°¢Çϱ⠶§¹®¿¡ , ij¸¯ÅÍ ¶óÀÎÀ» º¸°ü À¯ÁöÇÏ´Â Msg ÇÁ·ÓÆÛƼ¸¦ Ãß°¡ÇÕ´Ï´Ù.
[ClassView] ±×¸®°í ISampleParam ¸¦ ¿À¸¥ÂÊ Å¬¸¯ÇØ , Ç¥½ÃµÇ´Â pop-up menu·ÎºÎÅÍ [ÇÁ·ÓÆÛƼÀÇ Ãß°¡] ¸¦ ¼±ÅÃÇÕ´Ï´Ù. [ÀÎÅÍÆäÀ̽º¿¡ ÇÁ·ÓÆÛƼ¸¦ Ãß°¡] ´ÙÀ̾ó·Î±×°¡ Ç¥½ÃµÇ¹Ç·Î ,[ÇÁ·ÓÆÛƼÀÇ Á¾·ù] ¿¡ BSTR,[ÇÁ·ÓÆÛƼ¸í¿¡] Msg ¼³Á¤ÇØ ,[OK] ¸¦ Ŭ¸¯ÇØ ÁÖ¼¼¿ä.

ÀÎÅÍÆäÀ̽º¿¡ ÇÁ·ÓÆÛƼ¸¦ Ãß°¡

CSampleParam ÀÇ Å¬·¡½º Á¤ÀÇ¿¡ ÇÁ·ÓÆÛƼ Msg ÀÇ ³»¿ëÀ» º¸°ü À¯ÁöÇÏ´Â ¸â¹ö m_Msg ¸¦ Á¤ÀÇÇÕ´Ï´Ù.
    // ÇÁ·ÓÆÛƼ Msg ÀÇ ³»¿ëÀ» º¸°ü À¯ÁöÇÑ´Ù. 
    CString m_Msg;
};

#endif //__SAMPLEPARAM_H_
À§Àúµå¿¡ ÀÇÇØ Ãß°¡µÈ get_Msg,put_Msg ÀÇ ³»¿ëÀ» ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇÕ´Ï´Ù.
STDMETHODIMP CSampleParam::get_Msg(BSTR *pVal)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState())

    *pVal = m_Msg.AllocSysString();

    return S_OK;
}

STDMETHODIMP CSampleParam::put_Msg(BSTR newVal)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState())

    m_Msg = newVal;

    return S_OK;
}
ÀÌ°ÍÀ¸·Î ,SampleParam ´Â ¿Ï¼ºÀÔ´Ï´Ù.
´ÙÀ½¿¡ Á¢¼Ó Æ÷ÀÎÆ®¸¦ Ãß°¡ÇÕ´Ï´Ù. [ClassView] ±×¸®°í _ISampleCtrlEvents ¸¦ ¿À¸¥ÂÊ Å¬¸¯ÇØ , Ç¥½ÃµÇ´Â pop-up menu·ÎºÎÅÍ [¸Þ¼ÒµåÀÇ Ãß°¡] ¸¦ ¼±ÅÃÇÕ´Ï´Ù.
Ç¥½ÃµÇ´Â [ÀÎÅÍÆäÀ̽º¿¡ ¸Þ¼Òµå¸¦ Ãß°¡] ·Î [¸Þ¼Òµå¸í] ¿¡ SampleMethod, ÆĶó¹ÌÅÍ¿¡ [in] ISampleParam* sampParam ¸¦ ¼³Á¤ÇØ ,[OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

ÀÎÅÍÆäÀ̽º¿¡ ¸Þ¼Òµå¸¦ Ãß°¡

Ãß°¡Çϸé(ÀÚ) , ºôµå ÇØ ÁÖ¼¼¿ä. ¿¡·¯°¡ ¾øÀ¸¸é ,[ClassView] ±×¸®°í CSampleCtrl ¸¦ ¿À¸¥ÂÊ Å¬¸¯ÇØ , Ç¥½ÃµÇ´Â pop-up menu·ÎºÎÅÍ [Á¢¼Ó Æ÷ÀÎÆ®ÀÇ ÀÎÇø®¸ÇÆ®] ¸¦ ¼±ÅÃÇÕ´Ï´Ù.
[connection Æ÷ÀÎÆ®ÀÇ ÀÎÇø®¸ÇÆ®] ´ÙÀ̾ó·Î±×°¡ Ç¥½ÃµÇ¹Ç·Î , [ÀÎÅÍÆäÀ̽º] ¿¡ Ç¥½ÃµÇ°í ÀÖ´Â _ISampleCtrlEvents ¿¡ üũ¸¦ ³Ö¾î[OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

connection Æ÷ÀÎÆ®ÀÇ ÀÎÇø®¸ÇÆ®

Ãß°¡°¡ ³¡³ª¸é(ÀÚ) , ÀçÂ÷ ºôµå ÇØ ÁÖ¼¼¿ä. ȯ°æ¿¡ ÀÇÇÑÀÏÁöµµ ¸ð¸¨´Ï´Ù¸¸ , ¿©±â¼­
c:\documents and settings\bono\my documents\visual studio projects\atlctrlsample\samplectrl.h(83) :
 error C2065: 'IID__ISampleCtrlEvents' : Á¤ÀǵǾî ÀÖÁö ¾ÊÀº ½Äº°ÀÚÀÔ´Ï´Ù. 
c:\documents and settings\bono\my documents\visual studio projects\atlctrlsample\samplectrl.h(83) :
 error C2440: 'static_cast' : 'class CSampleCtrl *' (À¸)·ÎºÎÅÍ 'class ATL::_ICPLocator *' ·Î º¯È¯ÇÒ ¼ö ¾ø½À´Ï´Ù. 
 (»õ·Î¿î µ¿ÀÛ ; ÍÙÌßÀ» ÂüÁ¶)
        Áö½Ã¹ÞÀº ÇüÅ´ °ü·ÃÀÌ ¾ø½À´Ï´Ù; º¯È¯¿¡´Â reinterpret_cast, C ½À²Ù ·¬½Ä¶Ç´Â ÇÔ¼ö½À²ÙÀÇ °Í·¬½ÄÀÌ ÇÊ¿äÇÕ´Ï´Ù. 
c:\documents and settings\bono\my documents\visual studio projects\atlctrlsample\samplectrl.h(83) :
 fatal error C1903: Á÷ÀüÀÇ °Í´×°À� ¼öº¹ÇÒ ¼ö ¾ø½À´Ï´Ù; ºÝÊß²Ù¸¦ ÁßÁöÇÕ´Ï´Ù. 
(¿Í)°ú °°Àº ¿¡·¯°¡ ³ª¿À´Â °æ¿ì ,CSampleCtrl Ŭ·¡½ºÀÇ Á¤Àdz»ÀÇ °Í
BEGIN_CONNECTION_POINT_MAP(CSampleCtrl)
    CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
    CONNECTION_POINT_ENTRY(IID__ISampleCtrlEvents)
END_CONNECTION_POINT_MAP()
À»
BEGIN_CONNECTION_POINT_MAP(CSampleCtrl)
    CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
    CONNECTION_POINT_ENTRY(DIID__ISampleCtrlEvents)
END_CONNECTION_POINT_MAP()
°ú °°ÀÌ (IID__ISampleCtrlEvents ÀÇ ¸Ó¸®¿¡ D ¸¦ ºÎ°¡ÇÏ´Â) ÆíÁýÇØ ÁÖ¼¼¿ä. ºôµå ÇÒ ¼ö ÀÖ°Ô µË´Ï´Ù.
µ¡ºÙ¿©¼­ , ÀÌ°ÍÀº À§ÀúµåÀÇ ¹®Á¦¿Í °°Àº »ý°¢µµ µì´Ï´Ù¸¸ , ³ªÀÇ Ã£´Â ¹æ¹ýÀÌ ³ª»Û °ÍÀÎÁö , ¸¶ÀÌÅ©·Î¼ÒÇÁÆ®ÀÇ ¼­Æ÷Æ® ±â¼ú Á¤º¸¿¡¼­ÀÇ º¸°í¸¦ ã¾Æ³¾ ¼ö°¡ ¾ø¾ú½À´Ï´Ù.
¸Þ¼ÒµåÀÇ Ãß°¡
Á¢¼Ó Æ÷ÀÎÆ®ÀÇ Å×½ºÆ®¸¦ °âÇØ , ÄÁÆ®·Ñ¿¡ ¸Þ¼Òµå¸¦ Ãß°¡ÇØ , ¸Þ¼ÒµåÀÇ ÄÚµå·ÎºÎÅÍ Á¢¼Ó Æ÷ÀÎÆ®¸¦ »ç¿ëÇØ À̺¥Æ®¸¦ ¹ß»ý½Ãŵ´Ï´Ù.
¿ì¼± , ÄÁÆ®·Ñ¿¡ ¸Þ¼Òµå¸¦ Ãß°¡ÇÕ´Ï´Ù.
[ClassView] ±×¸®°í ISampleCtrl ¸¦ ¿À¸¥ÂÊ Å¬¸¯ÇØ , pop-up menu·ÎºÎÅÍ ¸Þ¼ÒµåÀÇ Ãß°¡¸¦ ¼±ÅÃÇÕ´Ï´Ù.
[ÀÎÅÍÆäÀ̽º¿¡ ¸Þ¼Òµå¸¦ Ãß°¡] ´ÙÀ̾ó·Î±×°¡ Ç¥½ÃµÇ¹Ç·Î ,[¸Þ¼Òµå¸í] ¿¡ MyCallMethod ¼³Á¤ÇØ , [OK] ¸¦ Ŭ¸¯ÇÕ´Ï´Ù.

ÀÎÅÍÆäÀ̽º¿¡ ¸Þ¼Òµå¸¦ Ãß°¡

´ÙÀ½¿¡ , À̺¥Æ® ÅëÁöÇÒ ¶§¿¡ »ç¿ëÇÏ´Â ISampleParam ÀÎÅÍÆäÀ̽º Æ÷ÀÎÅ͸¦ »ý¼º/ÆıâÇÏ´Â Äڵ带 Ãß°¡ÇÕ´Ï´Ù.
CSampleCtrl ÀÇ Å¬·¡½º Á¤ÀÇ¿¡
    ISampleParam* m_pSampleParam;
¸¦ Ãß°¡ÇÕ´Ï´Ù.
    // ISampleParam (À»)¸¦ º¸°ü À¯ÁöÇÑ´Ù. 
    ISampleParam* m_pSampleParam;
};

#endif //__SAMPLECTRL_H_
CSampleCtrl ÀÇ constructor¡¡ ¡¡ À» ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇÕ´Ï´Ù.
    CSampleCtrl() :
        m_pSampleParam(0)
    {
    }
CComObjectRootEx::FinalConstruct() (À»)¸¦ ¿À¹ö¶óÀ̵å(override) ÇØ , ÀÌÇÏ¿Í °°ÀÌ Ãß°¡ÇÕ´Ï´Ù.
    HRESULT FinalConstruct()
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());

        // À̺¥Æ® ÅëÁö¿¡ »ç¿ëÇÏ´Â ÀÎÅÍÆäÀ̽º¸¦ ÀÛ¼ºÇÑ´Ù. 
        HRESULT hr;
        hr = CoCreateInstance(CLSID_SampleParam,
                         0,
                         CLSCTX_INPROC_SERVER,
                         IID_ISampleParam,
                         (void **) &m_pSampleParam);
        if (FAILED(hr)) {
            TRACE("FAILURE: FinalConstruct() - CoCreateInstance(): IID_ISampleParam\n");
        }

        return hr;
    }
CComObjectRootEx::FinalRelease() (À»)¸¦ ¿À¹ö¶óÀ̵å(override) ÇØ , ÀÌÇÏ¿Í °°ÀÌ Ãß°¡ÇÕ´Ï´Ù.
    void FinalRelease()
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());

        // À̺¥Æ® ÅëÁö¿¡ »ç¿ëÇÏ´Â ÀÎÅÍÆäÀ̽º¸¦ ÇعæÇÑ´Ù.
        if (m_pSampleParam) {
            m_pSampleParam->Release();
        }
    }
À§Àúµå¿¡ ÀÇÇØ CSampleCtrl ¿¡ Ãß°¡µÇ¾ú´Ù MyCallMethod ¸¦ ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇÕ´Ï´Ù.
STDMETHODIMP CSampleCtrl::MyCallMethod()
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState())

    CString msg = _T("¡ª");
    if (m_pSampleParam) {
        m_pSampleParam->put_Msg(msg.AllocSysString());
        Fire_SampleMethod(m_pSampleParam);
    }

    return S_OK;
}
ÆíÁýÀÌ ³¡³ª¸é(ÀÚ) , ºôµå ÇØ ÁÖ¼¼¿ä.
ºôµå°¡ ³¡³ª¸é(ÀÚ) , ¶Ç ´Ù½Ã VB ¸¦ »ç¿ëÇØ Å×½ºÆ®ÇØ º¸°Ú½À´Ï´Ù. Æû¿¡ ÄÁÆ®·Ñ (SampleCtrl1) °ú ¹öÆ° (Command1) À» Ãß°¡ÇÕ´Ï´Ù. ¹öÆ°À» ´õºí Ŭ¸¯ ÇØ Command1_Click À̺¥Æ®¸¦ , ÄÁÆ®·ÑÀ» ´õºí Ŭ¸¯ ÇØ SampleCtrl1_SampleMethod À̺¥Æ®¸¦ Ãß°¡ÇØ , ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇÕ´Ï´Ù.
Private Sub Command1_Click()
    SampleCtrl1.MyCallMethod
End Sub

Private Sub SampleCtrl1_SampleMethod(ByVal sampParam As ATLCTRLSAMPLELibCtl.ISampleParam)
    MsgBox sampParam.Msg
End Sub
½ÇÇàÇØ Command1 ¸¦ Ŭ¸¯ÇØ ,"¡ª" (¿Í)°ú ¸Þ½ÃÁö ¹Ú½º¿¡ Ç¥½ÃµÇ¸é OK ÀÔ´Ï´Ù.

VB ¿¡¼­ÀÇ ½ÇÇ࿹

threadÀÇ ½ÇÀå
ÄÁÆ®·ÑÀÇ ¸Þ¼Òµå Áß(¾È)¿¡¼­ ½Ã°£ÀÌ °É¸®´Â 󸮸¦ ½ÇÇàÇÏ°í ½ÍÀº °ÍÀÌ ÀÖ½À´Ï´Ù.
¸Þ¼Òµå³»¿¡¼­ ½Ã°£ÀÌ °É¸®´Â 󸮸¦ ½Ç½ÃÇϸé , ÄÁÅ×À̳ÊÃø (Å×½ºÆ®·Î »ç¿ëÇß´Ù VB ³ª IE µî ÄÁÆ®·ÑÀÇ ºÎ¸ð°¡ µÇ´Â ¾îÇø®ÄÉÀ̼Ç) ÀÇ ¸Þ½ÃÁö ·çÇÁ°¡ µ¹Áö ¾Ê°Ô µÇ¾î ,UI °¡ ±»¾îÁ® ¹ö¸³´Ï´Ù.
½ÃÇè»ï¾Æ ,CSampleCtrl::MyCallMethod() ÀÇ ¾È¿¡ Àû´çÇÑ Sleep() À» ³Ö¾î , Á¶±Ý ÀüÀÇ "¡ª" (À»)¸¦ Ç¥½Ã½ÃÅ°´Â Å×½ºÆ® ÇÁ·Î±×·¥À» ½ÇÇàÇØ º¸¸é ¾Ð´Ï´Ù. MyCallMethod() (À»)¸¦ È£ÃâÇÏÀÚ ¸¶ÀÚ UI °¡ ÀÀ´äÇÏÁö ¾Ê°Ô µÇ´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù°í »ý°¢ÇÕ´Ï´Ù.

MyCallMethod() Áß(¾È)¿¡¼­ ¸Þ½ÃÁö ·çÇÁ¸¦ µ¹¸®´Â °ÍÀ¸·Î , ÀÀ´äÇÏÁö ¾Ê°Ô µÇ´Â °ÍÀ» ¸·À» ¼öµµ ÀÖ½À´Ï´Ù¸¸ , ¿¹¸¦ µé¸é MyCallMethod() ÀÌ UI ¸ØÃá ±¸ °ü°è¾ø´Â 󸮸¦ ÇÏ´Â ¸Þ¼Òµå¿´´ø °æ¿ì , ÄÚµå¾È¿¡ UI ¸¦ À§ÇÑ ¸Þ½ÃÁö ·çÇÁ°¡ ¼¯¿© ¿À´Â °ÍÀº ³Ê¹« ¾Æ¸§´äÁö ¾Ê°í , ±â»Û °ÍÀº ¾Æ´Ï´Ù°í »ý°¢ÇÕ´Ï´Ù.

±×·¸´Ù°í ÇÏ´Â °ÍÀ¸·Î , threadÈ­ÇØ º¸°Ú½À´Ï´Ù. threadÈ­Çϱ⿡ ÁîÀ½ÇØ ÁÖÀÇÇÏ´Â °ÍÀº ,
  • threadÀÇ ½ÃÀÛÀ¸·Î CoInitialize() ¸¦ ºÒ·¯ , ¸¶Áö¸·À¸·Î CoUninitialize() ¸¦ ºÎ¸£´Â °Í.
  • thread¿¡ ÀÎÅÍÆäÀ̽º Æ÷ÀÎÅ͸¦ °Ç³×ÁÙ ¶§´Â ¸¶¼£¸µ ÇÏ´Â °Í.
  • ÄÁÅ×ÀÌ³Ê (ÄÁÆ®·ÑÀÇ ºÎ¸ð°¡ µÇ´Â ¾îÇø®ÄÉÀ̼Ç) ÀÌ Á¾·áµÇ¾úÀ» ¶§¿¡ thread¸¦ Á¤»óÀûÀ¸·Î Á¾·áÇÒ ¼ö ÀÖµµ·Ï(µíÀÌ) ÇØ µÎ´Â °Í.
ÀÇ 3 Á¡ÀԴϱî.
µ¡ºÙ¿© ÀÌÇÏÀÇ »ùÇÿ¡¼­´Â ½Ã°£ÀÌ °É¸®´Â ó¸® ´ë½Å¿¡ Sleep() ¸¦ »ç¿ëÇÏ°í ÀÖ½À´Ï´Ù.

¿ì¼± , thread·Î¼­ µ¿ÀÛÇÏ´Â Á¤Àû ¸Þ¼Òµå¸¦ Ŭ·¡½º¿¡ Ãß°¡ÇÕ´Ï´Ù. [ClassView] ±×¸®°í CSampleCtrl ¸¦ ¿À¸¥ÂÊ Å¬¸¯ÇØ , pop-up menu·Î ,[¸â¹ö ÇÔ¼öÀÇ Ãß°¡] ¸¦ ¼±ÅÃÇÕ´Ï´Ù. [¸â¹ö ÇÔ¼öÀÇ Ãß°¡] ´ÙÀ̾ó·Î±×·Î ,[ÇÔ¼öÀÇ ÇüÅÂ] ¿¡ UINT,[ÇÔ¼öÀÇ ¼±¾ð] ¿¡ TestThread(VOID *pParam), [Static] ¿¡ üũ¸¦ ³Ö¾î[OK] ¸¦ Ŭ¸¯ÇØ ÁÖ¼¼¿ä.
¡Ø¿©±â¿¡¼­´Â ,AfxBeginThread() À» »ç¿ëÇØ thread¸¦ ÀÛ¼ºÇϱâ À§ÇØ(¶§¹®¿¡) , thread ÇÔ¼öÀÇ prototype´Â
UINT MyControllingFunction(LPVOID pParam);
°ú °°ÀÌ µË´Ï´Ù.

¸â¹ö ÇÔ¼öÀÇ Ãß°¡

´ÙÀ½¿¡ , thread Ãø¿¡ °Ç³×ÁÖ´Â ÀÎÅÍÆäÀ̽º¸¦ ¸¶¼£¸µ Çϴµ¥ »ç¿ëÇÏ´Â IStream ¿¡ÀÇ Æ÷ÀÎÅÍ º¯¼ö¸¦ CSampleCtrl ÀÇ ¸â¹ö º¯¼ö·Î¼­ Ãß°¡ÇÕ´Ï´Ù.
    // ISampleParam ¸¶¼£¸µ¿ë
    IStream* m_IStreamSampleParam;
    // Á¢¼Ó Æ÷ÀÎÆ® ¸¶¼£¸µ¿ë
    CArray<IStream*, IStream*> m_IStreamDispatchArray;
};

#endif //__SAMPLECTRL_H_
±×¸®°í ,CArray ¸¦ »ç¿ëÇϱâ À§Çؼ­ StdAfx.h ¿¡
#include <afxtempl.h>
¸¦ Ãß°¡ÇÕ´Ï´Ù.
#include <atlcom.h>
#include <atlctl.h>
#include <afxtempl.h>

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ (Àº)´Â ÀüÇàÀÇ Á÷Àü¿¡ Ãß°¡ÀÇ ¼±¾ðÀ» »ðÀÔÇÕ´Ï´Ù. 

#endif // !defined(AFX_STDAFX_H__55503BB6_11A0_4AE2_ABC9_C341A38E43F7__INCLUDED)
´ÙÀ½¿¡ , ÄÁÅ×ÀÌ³Ê Á¾·á½Ã¿¡ thread°¡ ¾ÆÁ÷ µ¿ÀÛÇÏ°í ÀÖ¾úÀ» °æ¿ì , threadÀÇ Á¾·á¸¦ Áö½ÃÇÏ´Â Ç÷¡±×¿Í threadÀÇ Á¾·á¸¦ ¸¸³ª°í Çϱâ À§Çؼ­ , thread ÇÚµéÀ» ÅðÇÇÇØ µÎ´Â º¯¼ö¸¦ CSampleCtrl ÀÇ ¸â¹ö º¯¼ö·Î¼­ Ãß°¡ÇÏ´Â
    // Á¾·á Ç÷¡±×
    BOOL m_bAbort;
    // thread Á¾·á ¸¸³ª°í °¨½Ã¿ë
    HANDLE m_hThread;
};

#endif //__SAMPLECTRL_H_
»ó±â·Î Ãß°¡ÇÑ ¸â¹ö º¯¼öÀÇ ÃʱâÈ­¸¦ CSampleCtrl ÀÇ constructor¡¡ ¡¡ ¿¡ Ãß°¡ÇÕ´Ï´Ù.
    CSampleCtrl() :
        m_pSampleParam(0),
        m_IStreamSampleParam(0),
        m_bAbort(FALSE),
        m_hThread(0)
    {
MyCallMethod (À»)¸¦ ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇÕ´Ï´Ù.
STDMETHODIMP CSampleCtrl::MyCallMethod()
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState())

    HRESULT hr;
    IStream* pStream;

    try {

        if (m_hThread) {
            // ÀÌÀü¿¡ ÅðÇÇÇÑ thread ÇÚµéÀÌ ³²¾Æ ÀÖÀ¸¸é »èÁ¦ÇÑ´Ù. 
            CloseHandle(m_hThread);
            m_hThread = 0;
        }

        //
        // Á¢¼Ó ÀÎÅÍÆäÀ̽º¸¦ ¸¶¼£¸µ ÇØ ,m_IStreamDispatchArray ¿¡ °Ý³³ÇÑ´Ù. 
        //
        m_IStreamDispatchArray.RemoveAll();

        CProxy_ISampleCtrlEvents<CSampleCtrl>* pT = static_cast<CProxy_ISampleCtrlEvents<CSampleCtrl>*>(this);
        int nConnectionIndex;
        int nConnections = pT->m_vec.GetSize();

        // Á¢¼Ó ÀÎÅÍÆäÀ̽º¸¦ ¸ðµÎ ÃëµæÇØ , ¸¶¼£¸µ ÈÄ , ¹è¿­¿¡ °Ý³³ÇÑ´Ù. 
        for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) {
            Lock();
            CComPtr<IUnknown> sp = pT->m_vec.GetAt(nConnectionIndex);
            Unlock();
            IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
            if (pDispatch != NULL) {
                // ÃëµæÇß´Ù IDispatch ¸¦ IStream ¿¡ º¯È¯ÇØ °Ý³³ÇÑ´Ù. 
                pStream = 0;
                hr = CoMarshalInterThreadInterfaceInStream(IID_IDispatch,
                            pDispatch, (IStream**) &pStream);
                if (FAILED(hr)) {
                    TRACE("FAILURE: CSampleCtrl::MyCallMethod() - CoMarshalInterThreadInterfaceInStream(): IID_IDispatch\n");
                } else {
                    ASSERT(pStream);
                    m_IStreamDispatchArray.Add(pStream);
                }
            }
        }    

        //
        // ISampleParam ÀÎÅÍÆäÀ̽º¸¦ ¸¶¼£¸µ ÇØ , °Ý³³ÇÑ´Ù. 
        //
        m_IStreamSampleParam = 0;
        
        if (m_pSampleParam) {
            // ¸¶¼£¸µ ÇØ °Ý³³ÇÑ´Ù. 
            pStream = 0;
            hr = CoMarshalInterThreadInterfaceInStream(IID_ISampleParam,
                        m_pSampleParam, (IStream**) &pStream);
            if (FAILED(hr)) {
                TRACE("FAILURE: CSampleCtrl::MyCallMethod() - CoMarshalInterThreadInterfaceInStream(): IID_ISampleParam\n");
            } else {
                ASSERT(pStream);
                m_IStreamSampleParam = pStream;
            }
        }

        //
        // thread¸¦ ÀÛ¼ºÇØ , °³½ÃÇÑ´Ù. 
        //

        // thread¸¦ ÀÛ¼ºÇÑ´Ù. 
        CWinThread* pThread = AfxBeginThread(
                        TestThread,
                        this,
                        THREAD_PRIORITY_NORMAL,
                        0,
                        CREATE_SUSPENDED,
                        0);
        if (!pThread) {
            return Error(_T("thread¸¦ ÀÛ¼ºÇÒ ¼ö ¾ø¾ú½À´Ï´Ù. "));
        }

        // thread Á¾·á ¸¸³­ °Í , thread ÇÚµéÀ» º¹Á¦ÇÑ´Ù. 
        DuplicateHandle(
            GetCurrentProcess(),    // ¿ø ÇÁ·Î¼¼½º
            pThread->m_hThread,        // ¿À¸®Áö³¯ ÇÚµé
            GetCurrentProcess(),    // ó ÇÁ·Î¼¼½º
            &m_hThread,                // º¹Á¦ÇÑ ÇÚµéÀÌ Ä«ÇǵǴÂ
            0,                        // ¾×¼¼½º±Ç(¹«½ÃµÇ´Â)
            FALSE,                    // °è½ÂÇÏÁö ¾Ê´Â
            DUPLICATE_SAME_ACCESS    // º¹Á¦Ã³ ÇÚµéÀº , º¹Á¦¿ø ÇÚµé°ú °°Àº ¾×¼¼½º±ÇÀ» °¡Áø´Ù
        );

        m_bAbort = FALSE;

        // thread¸¦ °³½ÃÇÑ´Ù. 
        pThread->ResumeThread();


    } catch (CException* e) {
        e->Delete();
        return Error(_T("Ä¡¸íÀûÀÎ ¿¡·¯°¡ ¹ß»ýÇß½À´Ï´Ù. "));
    }

    return S_OK;
}
¿À¹ö¶óÀ̵å(override) ÇÑ FinalRelease() ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇÕ´Ï´Ù.
    void FinalRelease()
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());

        // threadÀÇ Á¾·á »óÅ ¸¸³ª°í ¿ë¹«ÀÇ
        // º¹Á¦µÈ thread ÇÚµéÀÌ ÀÖÀ¸¸é ,
        // ¸¸³ª°í¸¦ ½Ç½ÃÇÑ µÚ , »èÁ¦ÇÑ´Ù. 
        try {
            m_bAbort = TRUE;
            if (m_hThread) {
                // NOTE: ŸÀÓ ¾Æ¿ôÀ» INFINITE ·Î ÇÏ´Â ¿ë±â°¡ ¾ø±â ¶§¹®¿¡ ,
                //       Àû´çÇÑ ½Ã°£À» ¼³Á¤ÇØ ÀÖ´Ù. 
                WaitForSingleObject(m_hThread, 10000);
                CloseHandle(m_hThread);
            }
        } catch (CException* e) {
            e->Delete();
        }

        // À̺¥Æ® ÅëÁö¿¡ »ç¿ëÇÏ´Â ÀÎÅÍÆäÀ̽º¸¦ ÇعæÇÑ´Ù. 
        if (m_pSampleParam) {
            m_pSampleParam->Release();
        }
    }
¸¶Áö¸·¿¡ TestThread() ¸¦ ÀÌÇÏ¿Í °°ÀÌ ÆíÁýÇÕ´Ï´Ù.
UINT CSampleCtrl::TestThread(VOID *pParam)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    // COM ¶óÀ̺귯¸®¸¦ ÃʱâÈ­ÇØ , »õ·Î¿î ¾ÆÆÄÆ®¸ÕÆ®½º·¿µå¿¡ µé¾î°£´Ù. 
    if (FAILED(CoInitialize(0))) {
        return 1;
    }

    // Ŭ·¡½º ÀνºÅϽº¿¡ÀÇ Æ÷ÀÎÅ͸¦ ²¨³½´Ù. 
    CSampleCtrl* pSampleCtrl = (CSampleCtrl*) pParam;
    if (!pSampleCtrl) {
        return 1;
    }

    // ½Ã°£ÀÌ °É¸®´Â 󸮸¦ ÇÑ´Ù. 
    for (int i = 0; i < 10; ++i) {
        if (pSampleCtrl->m_bAbort) {
            break;
        }
        Sleep(1000);
    }

    if (!pSampleCtrl->m_bAbort) {
        // ÄÁÅ×ÀÌ³Ê Á¾·á½Ã ÀÌ¿Ü´Â ÅëÁöÇÑ´Ù. 
        HRESULT hr;
        IStream* pStream;
        int i;

        //
        // ÄÁÅ×À̳ʿ¡ À̺¥Æ® ÅëÁöÇÑ´Ù. 
        //
        // ¾È ¸¶¼£¸µ ÈÄÀÇ Á¢¼Ó Æ÷ÀÎÆ®¸¦ °Ý³³ÇÑ´Ù. 
        CArray<IDispatch*, IDispatch*> dispatchArray;

        // ¾È ¸¶¼£¸µ ÈÄÀÇ ISampleParam ÀÎÅÍÆäÀ̽º¸¦ °Ý³³ÇÑ´Ù. 
        ISampleParam* pSampleParam = 0;

        //
        // Á¢¼Ó ÀÎÅÍÆäÀ̽º¸¦ ¾È ¸¶¼£¸µ ÇØ ¹è¿­¿¡ °Ý³³ÇÑ´Ù. 
        //
        for (i = 0; i < pSampleCtrl->m_IStreamDispatchArray.GetSize(); ++i) {
            pStream = pSampleCtrl->m_IStreamDispatchArray[i];
            IDispatch* pDispatch = 0;
            hr = CoGetInterfaceAndReleaseStream(pStream,
                    IID_IDispatch, (void**) &pDispatch);
            if (FAILED(hr)) {
                TRACE("FAILURE: CSampleCtrl::TestThread() - CoGetInterfaceAndReleaseStream(): IID_IDispatch\n");
            } else {
                ASSERT(pDispatch);
                dispatchArray.Add(pDispatch);
            }
        }

        //
        // ISampleParam ÀÎÅÍÆäÀ̽º¸¦ ¾È ¸¶¼£¸µ ÇØ , °Ý³³ÇÑ´Ù. 
        //
        pSampleParam = 0;

        pStream = pSampleCtrl->m_IStreamSampleParam;
        hr = CoGetInterfaceAndReleaseStream(pStream,
                    IID_ISampleParam, (void**) &pSampleParam);
        if (FAILED(hr)) {
            TRACE("FAILURE: CSampleCtrl::TestThread() - CoGetInterfaceAndReleaseStream(): IID_IResultEndPrint\n");
        } else {
            ASSERT(pSampleParam);
        }


        // ISampleParam ÀÎÅÍÆäÀ̽º¿¡ °ªÀ» ¼³Á¤ÇØ À̺¥Æ®¸¦ ¹ß»ýÇÑ´Ù. 
        if (pSampleParam) {
            CComVariant varResult;
            CString msg = _T("Çï·Î");
            pSampleParam->put_Msg(msg.AllocSysString());

            CComVariant* pvars = new CComVariant[1];
            for (i = 0; i < dispatchArray.GetSize(); ++i) {
                VariantClear(&varResult);
                IDispatch* pDispatch = dispatchArray[i];
                pvars[0] = pSampleParam;
                DISPPARAMS disp = { pvars, NULL, 1, 0 };
                pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
            }
            delete[] pvars;
            // varResult.scode ÀÇ °ªÀº ¹ö¸°´Ù. 
        }
    }

    // COM ¶óÀ̺귯¸®¸¦ ÇعæÇÑ´Ù. 
    CoUninitialize();

    return 0;
}
ÄÁÅ×ÀÌ³Ê Á¾·á½Ã¿¡ ÅëÁöÇÏÁö ¾Ê°Ô ÇÏ°í ÀÖ´Â °ÍÀº , ŸÀֿ̹¡ µû¶ó¼­´Â , Ä£ÃøÀÇ ÀνºÅϽº°¡ ¼Ò¸êÇÏ°í ÀÖÀ» °¡´É¼ºÀÌ ÀÖ¾î , ÅëÁö¸¦ ½Ç½ÃÇÏ´Â °Í¿¡ ÀÇÇØ ¾×¼¼½º À§¹ÝÀÌ ÀϾ±â (À§ÇØ)¶§¹®ÀÔ´Ï´Ù.
ÆíÁýÀÌ ³¡³ª¸é(ÀÚ) , ºôµå ÇØ Á¶±Ý Àü°ú °°ÀÌ VB µî¿¡¼­ Å×½ºÆ®ÇØ º¸¼¼¿ä.
UI ÀÇ ÀÀ´äÀÌ ±»¾îÁú °Íµµ ¾ø°í , ÇÑÆí , thread 󸮰¡ Á¾·áÇϸé(ÀÚ) , À̺¥Æ®°¡ ¹ß»ýÇÏ´Â °ÍÀÌ È®ÀÎÇÒ ¼ö ÀÖ´Ù°í »ý°¢ÇÕ´Ï´Ù.

µ¡ºÙ¿© ÀÌ »ùÇÿ¡¼­´Â thread³»ÀÇ Ç÷¡±×ÀÇ ¹èŸÀû ¿¬»êÀ̳ª threadÀÇ ÀÌÁß ±âµ¿µî¿¡´Â ¸ðµÎ ´ëóÇÏ°í ÀÖÁö ¾Ê½À´Ï´Ù. ½ÇÁ¦·Î ¾÷¹«·Î »ç¿ëÇÏ´Â °æ¿ì´Â , ±×°ÍµéÀ» °í·ÁÇÒ ÇÊ¿ä°¡ ÀÖ´Ù°í »ý°¢µÇ±â ¶§¹®¿¡ , Á¶½ÉÇØ ÁÖ¼¼¿ä.

¡ØÀ§ÀÇ »ùÇÃÀ» HTML ¿¡ ¹¯¾î , thread·ÎºÎÅÍ ¹ß»ý½ÃŲ À̺¥Æ® ÅëÁö Áß(¾È)¿¡¼­ javascript µî¿¡¼­ window.close() ¸¦ ½Ç½ÃÇϸé , °¡²û , ÀÌ»óÁ¾·á(ABEND) ÇØ ¹ö¸®´Â °ÍÀ» È®ÀÎÇÏ°í ÀÖ½À´Ï´Ù.
¿øÀÎÀº Àß ¸ð¸¨´Ï´Ù¸¸ , ¾×¼¼½º À§¹ÝÀÌ ¿øÀÎ °°¹Ç·Î , thread Á¾·áÀü¿¡ , thread¸¦ ±âµ¿ÇÑ ÃøÀÇ ÀνºÅϽº°¡ ¹«È¿°¡ µÇ¾î ÀÖ´Â °ÍÀ̶ó°í »ý°¢ÇÕ´Ï´Ù.
javascript ÀÇ setTimeout() ¸¦ »ç¿ëÇØ ,setTimeout("exitfunc", 2000) ¿Í °°ÀÌ ÇØ , À̺¥Æ® Çڵ鷯ÀÇ Á¦¾î¸¦ ÄÁÆ®·Ñ¿¡ µÇµ¹¸®°í ³ª¼­ ,exitfunc() ¾È¿¡¼­ window.close() Çϵµ·Ï Çϸé , thread¸¦ ¾î¶»°Ôµç Á¤»ó Á¾·á½Ãų ¼ö°¡ ÀÖ´Â °Í °°¾Æ , ¾×¼¼½º À§¹ÝÀº ÀϾÁö ¾Ê°Ô µË´Ï´Ù. ´Ù¸¸ ÀÌ°ÍÀº , threadÀÇ Á¾·á ŸÀֿ̹¡ ÀÇÁ¸ÇÑ È¸ÇÇÃ¥À̹ǷΠ¿ÏÀüÇÑ °ÍÀº ¾Ê°í , º»·¡´Â ÄÁÆ®·ÑÃø¿¡¼­ ´ëóÇØ¾ß ÇÏ´Â °ÍÀÔ´Ï´Ù¸¸ , ±Ùº»ÀûÀÎ ÇØ°áÃ¥À» ã¾Æ³¾ ¼ö ÀÖ°í ÀÖÁö ¾Ê½À´Ï´Ù. ¸¸¾à ,HTML ¿¡ ¹¯¾î ÀÌ¿ëÀÌ µÇ´Â °æ¿ì´Â ÃæºÐÈ÷ ÁÖÀÇÇØ ÁֽʽÿÀ.
»ùÇà ¼Ò½º
atlctrlsample.zip (36,072 ¾Æ¸£¹ÙÀÌÆ®)

À⵿»ç´Ï ½ÃÀå¿¡