Получение текста окна редактирования из модального диалогового окна MFC после его закрытия

#visual-c #mfc #modal-dialog

#visual-c #mfc #modal-dialog

Вопрос:

Из модального диалогового окна MFC я хочу извлечь текст из окна редактирования после закрытия диалогового окна. Я попытался это:

 CPreparationDlg Dlg;
CString m_str;

m_pMainWnd = amp;Dlg;
Dlg.DoModal();
CWnd *pMyDialog=AfxGetMainWnd();
CWnd *pWnd=pMyDialog->GetDlgItem(IDC_EDIT1);
pWnd->SetWindowText("huha max");
return TRUE;
  

Это не работает.

Ответ №1:

Диалоговое окно и его элементы управления не создаются до тех пор, пока вы не вызовете DoModal(), и, как уже указывалось, к моменту возврата DoModal() они уже будут уничтожены. Из-за этого вы не можете вызвать GetDlgItem() ни до, ни после DoModal(). Решение для передачи или извлечения данных в элемент управления заключается в использовании переменной в классе. Вы можете задать его при создании экземпляра класса, перед вызовом DoModal(). В OnInitDialog() вы вводите в элемент управления значение переменной. Затем, когда окно уничтожается, вы получаете значение из элемента управления и помещаете его в переменную. Затем вы считываете переменную из контекста вызова.

Что-то вроде этого (обратите внимание, я ввел это непосредственно в браузере, поэтому могут быть ошибки):

 class CMyDialog : CDialog
{
  CString m_value;
public:  
  CString GetValue() const {return m_value;}
  void SetValue(const CStringamp; value) {m_value = value;}

  virtual BOOL OnInitDialog();
  virtual BOOL DestroyWindow( );
}

BOOL CMyDialog::OnInitDialog()
{
  CDialog::OnInitDialog();

  SetDlgItemText(IDC_EDIT1, m_value);

  return TRUE;
}

BOOL CMyDialog::DestroyWindow()
{
  GetDlgItemText(IDC_EDIT1, m_value);

  return CDialog::DestroyWindow();
}
  

Затем вы можете использовать его следующим образом:

 CMyDialog dlg;

dlg.SetValue("stackoverflow");

dlg.DoModal();

CString response = dlg.GetValue();
  

Комментарии:

1. @abhinav там есть галочка, которую вы можете щелкнуть, чтобы выразить это мнение

Ответ №2:

  1. Откройте свой ресурс диалога, щелкните правой кнопкой мыши на текстовом поле и выберите «Добавить переменную», выберите тип значения и CString
  2. В диалоговом классе: перед закрытием вызовите UpdateData(TRUE)
  3. Вне диалогового окна:

     CPreparationDlg dlg(AfxGetMainWnd());
    
    dlg.m_myVariableName = "my Value"; 
    
    dlg.DoModal();
      

    // новое значение по-прежнему находится в dlg.m_myVariableName

Ответ №3:

DoModal() диалоговое окно уничтожается до его возврата, и поэтому значение больше недоступно.

Трудно сказать, почему вы устанавливаете m_pMainWnd для своего диалогового окна. Честно говоря, я не совсем уверен, что вы пытаетесь там сделать. Это неизбежно вызовет проблемы, поскольку сейчас AfxGetMainWnd() не работает.

В любом случае, вы не сможете получить управляющие значения диалогового окна после того, как диалоговое окно было уничтожено.

Комментарии:

1. спасибо за ваш комментарий, я очень новичок в этом vc mfc, я удалил эту строку, даже если она не запущена, можете ли вы указать другой способ извлечения данных из поля

2. отсюда не выполняется ASSERT(::IsWindow(m_hWnd));

3. он не запускается из-за этой ошибки ASSERT(::IsWindow(m_hWnd));

Ответ №4:

Я часто использую

 D_SOHINH dsohinh = new D_SOHINH();
    dsohinh.vd_kichthuoc=v_kichthuocDOC;
    dsohinh.vd_sohinh=v_soluongDOC;
    if(dsohinh.DoModal()==IDOK)
    {
        v_soluongDOC=dsohinh.vd_sohinh;
        v_kichthuocDOC=dsohinh.vd_kichthuoc;
    }
    SetModifiedFlag(true);
    UpdateAllViews(NULL);
  

С помощью dsohinh создается диалоговая форма, из которой вы хотите получить данные в mainform.
После получения данных вызовите SetModifiedFlag (true), чтобы обновить данные просмотра.
вызовите UpdateAllViews(NULL), чтобы установить данные в mainform

Ответ №5:

Это решение может показаться длинным, имея в виду, что для этой, казалось бы, небольшой задачи было написано так много кода. Но когда у нас есть список или дерево внутри дочернего окна, где все элементы созданы в дочернем окне и элементы должны быть перемещены в родительское окно, тогда это имеет смысл. Этот исходный код может легко создавать окно и передавать информацию из окна перед закрытием родителям.

     //copy the two functions in your code 

    //1-    bool peek_and_pump(void)

    //      template<class T,class THISCLASS>
    //2-    void TshowWindow(int id,T *amp;pVar,THISCLASS *ths)

    //and make two member variable
    // bool do_exit;
    // bool do_cancel;
    //in child dialog class.
    //set true value in do_exit in child dialog for exit

    CchildDialog *dlg;

    template<class T,class THISCLASS>
    void TshowWindow(int id,T *amp;pVar,THISCLASS *ths)
    {
        T *p=pVar;
        if(!p)
            p= new T;
        if(p->m_hWnd)
        {
            p->SetForegroundWindow();
        }
        else
        {
            delete p;
            p= new T;
            if(!(p->m_hWnd amp;amp; IsWindow(p->m_hWnd)))
            {
                p->Create(id,ths);
                if(IsWindow(p->m_hWnd))
                    p->ShowWindow(TRUE);
            }   
        }
        pVar=p;
    }


    bool peek_and_pump(void)
    {
        MSG msg;

    #if defined(_AFX) || defined(_AFXDLL)
        while(::PeekMessage(amp;msg,NULL,0,0,PM_NOREMOVE))
        {
            if(!AfxGetApp()->PumpMessage())
            {
                ::PostQuitMessage(0);
                return false;
            }
        }
        long lIdle = 0;
        while(AfxGetApp()->OnIdle(lIdle  ))
            ;
    #else
        if(::PeekMessage(amp;msg,NULL,0,0,PM_REMOVE))
        {
            ::TranslateMessage(amp;msg);
            ::DispatchMessage(amp;msg);
        }
    #endif

        return true;
    }

    void CparentPage::OnBnClick1()
    {
        if(dlg)
        {
            dlg->DestroyWindow();   
        }
        TshowWindow<CchildDialog,CparentPage>(IDD_DIALOG_child,dlg,this);
        dlg->GetDlgItem(IDC_EDIT_1)->SetWindowText("");
        dlg->m_temp_window.EnableWindow(FALSE);//enable or disable controls.
        dlg->UpdateData(false);//for to be done enable of disable or else.
        dlg->do_exit=false;
        dlg->do_cancel=false;
        while(dlg->do_exit==false)
        {
            peek_and_pump();//wait for dlg->do_exit set true
        }
        if( dlg->do_cancel==false ) 
        {
            CString str1;
            dlg->GetDlgItem(IDC_EDIT_1)->GetWindowText(str1);
            //or other member variale of CchildDialog
            //after finish all work with dlg then destroy its.
        }
        dlg->DestroyWindow();   
        

    }
    
    void CchildDialog::OnBnClickedOk()
    {
        UpdateData();
        OnOK();
        do_exit=true;
        do_cancel=false;
    }
    void CchildDialog::OnBnClickedCancel()
    {
        OnCancel();
        do_exit=true;
        do_cancel=true;
    }