【问题标题】:C++/MFC Error accessing control's variableC++/MFC 访问控件变量时出错
【发布时间】:2012-01-17 22:08:18
【问题描述】:

我为 CEdit 创建了一个控件的变量:

class CGateDlg : public CDialog
{
    ...
    public:
        // here is my control's variable
        CEdit m_edit_a;
        // here I map variable to control
        virtual void DoDataExchange(CDataExchange* pDX);
}

这就是我将变量映射到控件的方式:

void CGateDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT_A, m_edit_a);
}

它是这样工作的:用户在编辑框中键入一些文本。然后他按下清除编辑框的“重置”按钮。这是一段代码,负责在点击重置按钮后清除编辑框:

void CGateDlg::OnBnClickedReset()
{
    // clear edit box 
    m_edit_a.SetWindowTextW(L"");
}

应用程序启动时没有任何错误。我在 EditBox 中输入一些文本并点击“重置”按钮。然后我收到一个错误,导致我进入 winocc.cpp,第 245 行(ENSURE(this)):

void CWnd::SetWindowText(LPCTSTR lpszString)
{
    ENSURE(this);
    ENSURE(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL));

    if (m_pCtrlSite == NULL)
            ::SetWindowText(m_hWnd, lpszString);
    else
            m_pCtrlSite->SetWindowText(lpszString);
}

我认为问题出在 hWnd:

this    0x0030fa54 {CEdit hWnd=0x00000000}  CWnd * const

但是如何解决呢?

当我使用这个访问我的控件的值时一切正常:

CEdit *m_edit_a;
m_edit_a = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_A));
m_edit_a->SetWindowTextW(L"");

我做错了什么?

【问题讨论】:

  • 你能贴出全班的代码吗?
  • 如何创建CGateDlg?如果您不是从资源 id 创建它,那么 DDX_Control 可能对您不起作用,您可能需要在 OnCreate 重载中显式调用 m_edit_a.Create 以获取 CGateDlg,然后才能使用 CEdit
  • “从资源 id 创建”到底是什么意思?您能否给我发一个链接或样本,让我可以看到它的外观?我现在正在工作,但我会在回家后尝试您的所有想法,并在必要时将整个标题和类粘贴在这里。

标签: c++ mfc


【解决方案1】:

我可以看到两种可能性:

  1. 对话框启动时控件不存在。 CDialog::OnInitDialog 要做的第一件事就是调用 DoDataExchange,所以如果你在初始化过程的后期创建控件就太晚了。

  2. 您自己的 OnInitDialog 未调用 CDialog::OnInitDialog,因此未调用 DoDataExchange。

【讨论】:

  • 看起来解决方案没有我预期的那么复杂。我没有在我的 CGateDlg::OnInitDialog 中调用 CDialog::OnInitDialog。但是我还是要远离向导,这样我才能以正确的方式学习 MFC :)
【解决方案2】:

我认为你不应该直接使用你的控制成员(在这种情况下m_edit_a)。相反,你应该使用一个成员变量,比如说CStrimg m_edit_data,你应该将它链接到控件:

DDX_Text(pDX, IDC_EDIT_A, m_edit_data); // as you did it in DDC_Cotrol

现在您可以直接使用该变量,但是为了更新控件,您应该在使用它之前使用以下代码:

UpdateData(true); // unlocks the control in a sense
m_edit_data = "this is my test";
UpdateData(false); // locks the control again (in a sense)

这是 MFC 中的正常程序 :),希望对我有所帮助...

哦...您还应该将控件添加到字符串表...(如果您不知道,请告诉我)

【讨论】:

    【解决方案3】:

    我找不到你的问题。我使用 VC6.0 创建一个新项目,并将一个变量关联到编辑,只需链接你做的。 exe运行正常。

    class CEditTestDlg : public CDialog
    {
    // Construction
    public:
    CEditTestDlg(CWnd* pParent = NULL); // standard constructor
    
    // Dialog Data
    //{{AFX_DATA(CEditTestDlg)
    enum { IDD = IDD_EDITTEST_DIALOG };
    CEdit   m_Edit;
    //}}AFX_DATA
    
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CEditTestDlg)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //}}AFX_VIRTUAL
    

    ......

    .cpp

    void CEditTestDlg::DoDataExchange(CDataExchange* pDX)
    {
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CEditTestDlg)
        DDX_Control(pDX, IDC_EDIT1, m_Edit);
        //}}AFX_DATA_MAP
    }
    void CEditTestDlg::OnBnClickedReset() 
    {
        // TODO: Add your control notification handler code here
        m_Edit.SetWindowText("tttt");
    }
    

    所以,我认为这不是代码问题。你最好再试一次。

    【讨论】:

      【解决方案4】:

      如果您的对话框开始调用 CDialog::OnInitDialog() 并且您的 DoDataExchange 开始调用 CDialog::DoDataExchange 但仍然有空 hWnd 指针并获得 CNotSupportedException,请确保您的资源 (rc) 文件的对话框模板包含所有控件(IDC_) 等您在 DoDataExchange 中拥有的。

      如果使用还提供资源的 DLL,请检查覆盖定义。

      【讨论】:

        猜你喜欢
        • 2019-06-30
        • 2016-09-18
        • 2017-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多