Where The Streets Have No Name

GetDlgItem()의 잘못된 사용습관 본문

Developement/C, C++, C#

GetDlgItem()의 잘못된 사용습관

highheat 2008. 5. 22. 11:51
출처 : http://box.co.kr/raymondjeon/index.php/741

CWnd* pWnd = GetDlgItem( IDC_MYBUTTON ); // OK

CButton* pBtn = (CButton*)pWnd;                    // WRONG, its not a CButton

pBtn->SetCheck(0);                                            // Should fail

 

GetDlgItem() uses CWnd::FromHandle() to return the temporary pointer.

 

class CMyDialog : public CDialog

{

    CButton m_btn;

    // ...

    virtual BOOL OnInitDialog();

}

 

BOOL CMyDialog::OnInitDialog()

{

    // ...

    m_btn.SubclassDlgItem( IDC_MYBUTTON, this );

    // ...

}

or

{

    CButton* pBtn = new CButton;

    HWND hWnd = ::GetDlgItem(this->m_hWnd, IDC_MYBUTTON);

    pBtn->Attach( hWnd );

 

    pBtn->SetCheck(0); // it's safe to use call this as pBtn is an actual CButton object

 

    pBtn->Detach();

    delete pBtn;

}

 

 

 

 

CObject* CHandleMap::FromHandle(HANDLE h)

{

    if ( h == NULL ) return NULL; // Invalid handle, return

 

    // Lookup in the permanent map first

    CObject* pObject = LookupPermanent(h);

 

    if ( pObject != NULL ) return pObject; // return permanent one, and be glad

 

    else if ( (pObject = LookupTemporary(h)) != NULL ) // in temp map

    {

        // The pair is already there in the temporary map

        // So just set the handle(s) in the existing object

        // the handle is at m_nOffset bytes offset after CObject

        HANDLE* ph = (HANDLE*)((BYTE*)pTemp + m_nOffset);

        ph[0] = h;

        if ( m_nHandles == 2 ) ph[1] = h; // Some (CDC) may have 2 handles

 

        return pObject; // return current temporary one

    }

 

    // Couldn't find the handle either in permanent or temporary map

    // probably, this handle wasn't created by us, so we must create a temporary C++ object to wrap it.

    CObject* pTemp = NULL;

 

    // Use the runtime class associated to this type of handle to create the object of the Wrapper class

    pTemp = m_pClass->CreateObject();

 

    // Object is temporary, so make an entry in temp map

    m_temporaryMap.SetAt( (LPVOID)h, pTemp );

 

    // now set the handle in the object

    HANDLE* ph = (HANDLE*)((BYTE*)pTemp + m_nOffset); // after CObject

    ph[0] = h;

    if ( m_nHandles == 2 ) ph[1] = h; // Some class (CDC) may have 2 handles

 

    return pTemp; // return the created temporary object

}

 

CWnd* PASCAL CWnd::FromHandle(HWND hWnd)

{

    // Get the global handle map, create if not exist

    CHandleMap* pMap = afxMapHWND(TRUE);

 

    // Call the FromHandle function of the returned CHandleMap

    //  to get the corresponding MFC object pointer

    CWnd* pWnd = (CWnd*)pMap->FromHandle(hWnd);

 

    return pWnd;

}

 

CHandleMap* PASCAL afxMapHWND(BOOL bCreate)

{

    AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();

 

    if ( pState->m_pmapHWND == NULL && bCreate )

        pState->m_pmapHWND = new CHandleMap( RUNTIME_CLASS(CTempWnd), offsetof(CWnd, m_hWnd );

 

    return pState->m_pmapHWND;

}

 

class CTempWnd : public CWnd

{

    DECLARE_DYNCREATE(CTempWnd)

    DECLARE_FIXED_ALLOC(CTempWnd);

};

 

#define offsetof(s, m)    (size_t)&(((s*)0)->m)

 

BOOL CWnd::Attach(HWND hWndNew)

{

    // create map if not exist

    CHandleMap* pMap = afxMapHWND(TRUE);

    pMap->SetPermanent( m_hWnd = hWndNew, this );

    return TRUE;

}