일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- node.js
- ibsheet
- JDOM
- JSON
- 전자정부프레임워크
- Eclipse
- jsr 296
- Struts
- appspresso
- swingx
- Android
- 선택적조인
- 가우스
- PHP
- MFC
- dock
- GPS
- phonegap
- MySQL
- tomcat
- Spring
- WebLogic
- Google Map
- iBATIS
- Ajax
- oracle
- sencha touch
- jQuery
- rowspan
- PLSQL
- Today
- Total
Where The Streets Have No Name
GetDlgItem()의 잘못된 사용습관 본문
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;
}