#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:
- Откройте свой ресурс диалога, щелкните правой кнопкой мыши на текстовом поле и выберите «Добавить переменную», выберите тип значения и CString
- В диалоговом классе: перед закрытием вызовите
UpdateData(TRUE)
-
Вне диалогового окна:
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;
}