mfc从对话框访问formview项

时间:2012-10-15 09:34:31

标签: c++ mfc

在我的SDI应用程序中,我需要得到这个行为。单击FormView上的按钮后,将打开一个CDialog。当我按下CDialog上的OK按钮时,我调用FormView的一个功能。我不想关闭CDialog。我尝试使用无模式对话框,但是当我从对话框调用formview函数时,我无法访问formview的控件,就像它丢失了hwnd;错误是无法读取m_hwnd的内存,hwnd是???。 这是我的代码: 打开无模式对话框:

CCampiDlg *m_pDialog = NULL;
HWND hCampi = NULL;

// Invoking the Dialog
m_pDialog = new CCampiDlg;

if (m_pDialog != NULL)
{
    BOOL ret = m_pDialog->Create(m_pDialog->IDD, this);
    if (!ret)   //Create failed.
    {
        AfxMessageBox(_T("Error creating Dialog"));
    }
    m_pDialog->ShowWindow(SW_SHOW);
}

当我按下对话框中的确定按钮时:

CEditorTxView pView;
box2 = (CEdit*)(GetDlgItem(IDC_CAMPI_BOX2));
box2->GetWindowTextW(campo);
pView.inserisciCampo(1, campo);

在CEditorTxView(CFormView)中的inserisciCampo函数中,我必须使用我的控件txtCtrl进行操作,但它丢失了hwnd。 txtCtrl的声明在CEditorTxView.h

CTx1 txtCtrl;

并在DoDataExchange函数中初始化它:

void CEditorTxView::DoDataExchange(CDataExchange* pDX)
{
    CFormView::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_TX1, txtCtrl);
}

有人可以帮助我吗?

2 个答案:

答案 0 :(得分:3)

我可以在这里给你两个答案:

  1. 如何做你想要的(从无模式对话框访问CFormView的控件)
  2. 如何解决您的根本问题(将无模式对话框中的更改传达给所有者视图)
  3. 对于第一个,你必须在对话框类中声明一个指向视图的指针,并在视图的构造函数中初始化它:

    class CCampiDlg : public CDialog
    {
    public:
        CCampiDlg(CEditorTxView* pView,  CWnd*pParent = NULL) // Change declaration to add pointer to view
        : m_pView(pView)
        {
        }
    // ... Whatever
    private:
        CEditorTxView* m_pView;
    }
    

    现在在你的按钮处理程序中:

    CEdit* box2 = (CEdit*)(GetDlgItem(IDC_CAMPI_BOX2)); // Why not use a control variable?
    box2->GetWindowTextW(campo);
    m_pView->inserisciCampo(1, campo);
    

    这应该做你要求的。但是,这是错误的做法

    这种方法的问题在于对话框对其父对象知之甚少。它知道它的类型为CEditorTxView,并且它有一个名为inserisciCampo的成员,它带有一个数字和一些文本。

    它不应该知道那么多。事实上,除了CView类型甚至CWnd之外,了解它的任何内容都太过分了。

    如果对话框知道视图,则无法将对话框重新用于其他视图,并且只要视图更改其表示(例如,现在的文本框现在可能是组合框),对话框必须更改相应

    解决方案是向家长发送消息,解释发生了什么。然后父(视图)应该知道如何处理该事件。例如:

    class CCampiDlg : public CDialog
    {
    public:
        CCampiDlg(CWnd*pParent = NULL) {}
    protected:
        OnOk()
        {
            CString campo;
            c_CampiBox2.GetWindowText(campo);
            GetParent()->SendMessage(UWM_CAMPO2_SET, 0, (LPARAM)&campo);
        }
    }
    

    在视图中:

    // It can be ON_REGISTERED_MESSAGE:
    ON_MESSAGE(UWM_CAMPO2_SET, OnCampo2Set)
    
    //...    
    
    LRESULT CEditorTxView::OnCampo2Set(WPARAM, LPARAM lParam)
    {
        CString* s = (CString*) lParam;
        inserisciCampo(1, *campo);
        return 0;
    }
    

    现在,您已将视图和对话框分离。该对话框对视图一无所知。您可以更改其类型,更改表示,甚至使其成为对话框,并且您不必更改对话框中的任何内容。如果您在其他地方需要相同的无模式对话框,只需将其放在那里,在父级中创建一个消息处理程序,然后vo!

    有关进一步说明和更好的示例,请查看以下文章:

答案 1 :(得分:0)

在“确定”按钮上单击以下代码正在运行:

   CEditorTxView pView;
   box2 = (CEdit*)(GetDlgItem(IDC_CAMPI_BOX2));
   box2->GetWindowTextW(campo);
   pView.inserisciCampo(1, campo);

请注意,您正在堆栈中创建新的pView,并且它不会附加到任何窗口。您实际上并未引用已创建的视图并启动了作为父级的对话框。重新访问上面的代码并尝试获取视图:

如果代码无效,请尝试以下代码(Google it)

  CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd);
  CView * pView = pFrame->GetActiveView();