dynamic_cast of CWnd to CComboBox 在 OnSize 函数中产生一个空指针
dynamic_cast of CWnd to CComboBox is yeilding a null pointer in OnSize function
代码:
void CChristianLifeMinistryEditorDlg::OnSize(UINT nType, int cx, int cy)
{
CResizingDialog::OnSize(nType, cx, cy);
const CWnd* pFocus = GetFocus();
CComboBox* pFocusCombo = nullptr;
if (pFocus != nullptr)
{
if (pFocus->GetParent()->IsKindOf(RUNTIME_CLASS(CComboBox)))
{
pFocusCombo = dynamic_cast<CComboBox*>(GetFocus()->GetParent());
}
}
for (CWnd* pWnd = GetWindow(GW_CHILD); pWnd != nullptr; pWnd = pWnd->GetNextWindow(GW_HWNDNEXT))
{
if (pWnd == pFocusCombo)
{
// TODO: Sadly, by now, the control has already got all the text selected.
//pFocusCombo->SetEditSel(LOWORD(dwEditSel), HIWORD(dwEditSel));
}
else if (pWnd->IsKindOf(RUNTIME_CLASS(CComboBox)))
{
// This only works for combo boxes that are bound to controls
auto* pCombo = dynamic_cast<CComboBox*>(pWnd);
pCombo->SetEditSel(-1, -1);
}
else
{
CString strClassName;
if (::GetClassName(pWnd->GetSafeHwnd(), strClassName.GetBuffer(_MAX_PATH), _MAX_PATH))
{
if (strClassName == _T("ComboBox"))
{
auto* pCombo = (CComboBox*)pWnd;
//auto* pCombo = dynamic_cast<CComboBox*>(pWnd);
pCombo->SetEditSel(-1, -1);
}
}
strClassName.ReleaseBuffer();
}
}
if (m_pHtmlPreview != nullptr)
{
m_lblHtmlPreview.GetWindowRect(m_rctHtmlPreview);
ScreenToClient(m_rctHtmlPreview);
m_pHtmlPreview->MoveWindow(m_rctHtmlPreview);
}
}
我显示上下文的整个函数。但我对这一点特别感兴趣:
CString strClassName;
if (::GetClassName(pWnd->GetSafeHwnd(), strClassName.GetBuffer(_MAX_PATH), _MAX_PATH))
{
if (strClassName == _T("ComboBox"))
{
auto* pCombo = (CComboBox*)pWnd;
//auto* pCombo = dynamic_cast<CComboBox*>(pWnd);
pCombo->SetEditSel(-1, -1);
}
}
strClassName.ReleaseBuffer();
在代码分析更新期间,我遇到过很多不得不更新 C 风格转换的情况。很多时候我可以使用 static_cast
,但在某些情况下,编译器会告诉我应该使用 dynamic_cast
.
然后我发现我的应用程序没有正常工作,在调试模式下将它隔离到这个位:
//auto* pCombo = (CComboBox*)pWnd;
auto* pCombo = dynamic_cast<CComboBox*>(pWnd);
事实证明,转换指针 pCombo
是 null
。然而,当我使用 C-Style cast 时,这从未发生过。结果我又回到了 C-Style 阵容。我看到了这个讨论()但是我看不出是这个原因(临时指针)。
在这种情况下我应该使用什么演员可以依靠?
C-style casting会尝试不同的c++ casting,可能会选择reinterpret_cast
static_cast
。这是将 CWnd*
转换为 CComboBox*
,例如:
CWnd* wnd = GetDlgItem(IDC_COMBO1);
CComboBox* combo = (CComboBox*)wnd;
一般来说,父 class 不能“总是”转换为子。这取决于是否为该 ID 创建了 CComboBox m_combobox;
。
A) m_combobox
确实存在:
在这种情况下,我们的 wnd
可以引用 m_combobox
。
CWnd::GetDlgItem
等将 &m_combobox
转换为 CWnd*
,他们传递它。
dynamic_cast
检查它并转换回 CComboBox*
.
MFC 的 IsKindOf
将确认是否已创建 m_combobox
。
B) m_combobox
不存在:
在这种情况下,我们的 wnd
是 CWnd*
对象。 MFC 从未为该控件创建 CComboBox
。
dynamic_cast
测试,无法转换为 CComboBox*
如果 wnd
的 class 名称是 "ComboBox"
,static_cast
有效
下面的代码应该没问题。在这种情况下,您可以根据需要跳过dynamic_cast
,依靠static_cast
。但如果可能,最好使用dynamic_cast
。
CComboBox* ptr = nullptr;
if (wnd->IsKindOf(RUNTIME_CLASS(CComboBox)))
ptr = dynamic_cast<CComboBox*>(wnd);
if(!ptr)
{
CString classname;
::GetClassName(wnd->m_hWnd, classname.GetBuffer(_MAX_PATH), _MAX_PATH);
classname.ReleaseBuffer();
if(classname == L"ComboBox")
ptr = static_cast<CComboBox*>(wnd);
}
代码:
void CChristianLifeMinistryEditorDlg::OnSize(UINT nType, int cx, int cy)
{
CResizingDialog::OnSize(nType, cx, cy);
const CWnd* pFocus = GetFocus();
CComboBox* pFocusCombo = nullptr;
if (pFocus != nullptr)
{
if (pFocus->GetParent()->IsKindOf(RUNTIME_CLASS(CComboBox)))
{
pFocusCombo = dynamic_cast<CComboBox*>(GetFocus()->GetParent());
}
}
for (CWnd* pWnd = GetWindow(GW_CHILD); pWnd != nullptr; pWnd = pWnd->GetNextWindow(GW_HWNDNEXT))
{
if (pWnd == pFocusCombo)
{
// TODO: Sadly, by now, the control has already got all the text selected.
//pFocusCombo->SetEditSel(LOWORD(dwEditSel), HIWORD(dwEditSel));
}
else if (pWnd->IsKindOf(RUNTIME_CLASS(CComboBox)))
{
// This only works for combo boxes that are bound to controls
auto* pCombo = dynamic_cast<CComboBox*>(pWnd);
pCombo->SetEditSel(-1, -1);
}
else
{
CString strClassName;
if (::GetClassName(pWnd->GetSafeHwnd(), strClassName.GetBuffer(_MAX_PATH), _MAX_PATH))
{
if (strClassName == _T("ComboBox"))
{
auto* pCombo = (CComboBox*)pWnd;
//auto* pCombo = dynamic_cast<CComboBox*>(pWnd);
pCombo->SetEditSel(-1, -1);
}
}
strClassName.ReleaseBuffer();
}
}
if (m_pHtmlPreview != nullptr)
{
m_lblHtmlPreview.GetWindowRect(m_rctHtmlPreview);
ScreenToClient(m_rctHtmlPreview);
m_pHtmlPreview->MoveWindow(m_rctHtmlPreview);
}
}
我显示上下文的整个函数。但我对这一点特别感兴趣:
CString strClassName;
if (::GetClassName(pWnd->GetSafeHwnd(), strClassName.GetBuffer(_MAX_PATH), _MAX_PATH))
{
if (strClassName == _T("ComboBox"))
{
auto* pCombo = (CComboBox*)pWnd;
//auto* pCombo = dynamic_cast<CComboBox*>(pWnd);
pCombo->SetEditSel(-1, -1);
}
}
strClassName.ReleaseBuffer();
在代码分析更新期间,我遇到过很多不得不更新 C 风格转换的情况。很多时候我可以使用 static_cast
,但在某些情况下,编译器会告诉我应该使用 dynamic_cast
.
然后我发现我的应用程序没有正常工作,在调试模式下将它隔离到这个位:
//auto* pCombo = (CComboBox*)pWnd;
auto* pCombo = dynamic_cast<CComboBox*>(pWnd);
事实证明,转换指针 pCombo
是 null
。然而,当我使用 C-Style cast 时,这从未发生过。结果我又回到了 C-Style 阵容。我看到了这个讨论(
在这种情况下我应该使用什么演员可以依靠?
C-style casting会尝试不同的c++ casting,可能会选择reinterpret_cast
static_cast
。这是将 CWnd*
转换为 CComboBox*
,例如:
CWnd* wnd = GetDlgItem(IDC_COMBO1);
CComboBox* combo = (CComboBox*)wnd;
一般来说,父 class 不能“总是”转换为子。这取决于是否为该 ID 创建了 CComboBox m_combobox;
。
A) m_combobox
确实存在:
在这种情况下,我们的 wnd
可以引用 m_combobox
。
CWnd::GetDlgItem
等将 &m_combobox
转换为 CWnd*
,他们传递它。
dynamic_cast
检查它并转换回 CComboBox*
.
MFC 的 IsKindOf
将确认是否已创建 m_combobox
。
B) m_combobox
不存在:
在这种情况下,我们的 wnd
是 CWnd*
对象。 MFC 从未为该控件创建 CComboBox
。
dynamic_cast
测试,无法转换为 CComboBox*
wnd
的 class 名称是 "ComboBox"
,static_cast
有效
下面的代码应该没问题。在这种情况下,您可以根据需要跳过dynamic_cast
,依靠static_cast
。但如果可能,最好使用dynamic_cast
。
CComboBox* ptr = nullptr;
if (wnd->IsKindOf(RUNTIME_CLASS(CComboBox)))
ptr = dynamic_cast<CComboBox*>(wnd);
if(!ptr)
{
CString classname;
::GetClassName(wnd->m_hWnd, classname.GetBuffer(_MAX_PATH), _MAX_PATH);
classname.ReleaseBuffer();
if(classname == L"ComboBox")
ptr = static_cast<CComboBox*>(wnd);
}