Прерывание модальности в Диалоге
От: SirAlex Россия  
Дата: 17.04.02 11:01
Оценка:
Привет All!
Есть такая задача:

Из какого либо оконного приложения запущен модальный диалог.
Хотелось бы что бы при нажатии на кнопку его модальность прерывалась и можно было вернуться в приложение и выпонить какие либо действия, (например селектировать что либо и т.п.).
Ну и по окончании продолжить диалог.

Простое решение выходить с каким либо кодом потом запускать диалог заново только кажется простым . Было уже опробовано.

Хтоелось бы написать свой класс наследованный от CDialog в котором есть 2 метода — прервать модальность, продолжить ее.
Посмотрел исходники CDialog. Вроде все понятно, т.е. можно прервать текущий ModalLoop, потом запустить новый. Но хотелось именно продолжить старый... Вобщем есть варианты этого кода но в итоге есть проблемы.

Такое возможно, есть библиотека где это реализовано, но ее к сожелению по определенным причинам везде с собой не поташишь...

С уважением Александр.
Re: Прерывание модальности в Диалоге
От: Dutchman Беларусь http://blogs.rsdn.org/ikemefula
Дата: 17.04.02 13:39
Оценка:
Здравствуйте SirAlex, Вы писали:

SA>Хтоелось бы написать свой класс наследованный от CDialog в котором есть 2 метода — прервать модальность, продолжить ее.


Такое частично уже написано, EndModalLoop . Только нет продолжения и тд.

SA>Посмотрел исходники CDialog. Вроде все понятно, т.е. можно прервать текущий ModalLoop, потом запустить новый. Но хотелось именно продолжить старый... Вобщем есть варианты этого кода но в итоге есть проблемы.



Есть способ — делаешь немодальный диалог, вешаешь хук AfxHookWindowCreate(this);
Он устанавливает m_pWndInit на твой диалог. Потом вызываешь RunModalLoop,и у тебя появляется модальность. По нажатию на батон или еще как вызываешь EndModalLoop — . Теперь немодалныйснова и сообщения получаем от глобального цикла. Потом снова запускаешь в своем диалоге RunModalLoop и все.


Другой способ. В DoModal выполняется CWnd::RunModalLoop — он выбирает сообщения из очереди, а паренту посылает WM_ENTERIDLE, WM_KICKIDLE и тд. Тебе нужно это заменить. Переписывая DoModal, PreModal,PostModal — они виртуальные. Нужно будет кучу проверок делать. Но это несколько неудобный способ. Все из-за того, что DoModal должен ожидать результата.
Re[2]: Прерывание модальности в Диалоге
От: SirAlex Россия  
Дата: 18.04.02 08:52
Оценка: 10 (1)
Здравствуйте Dutchman, Вы писали:


D>Другой способ. В DoModal выполняется CWnd::RunModalLoop — он выбирает сообщения из очереди, а паренту посылает WM_ENTERIDLE, WM_KICKIDLE и тд. Тебе нужно это заменить. Переписывая DoModal, PreModal,PostModal — они виртуальные. Нужно будет кучу проверок делать. Но это несколько неудобный способ. Все из-за того, что DoModal должен ожидать результата.


Написал переопределив DoModal

там вместо

...
RunModalLoop
...

написал (это упрощенный пример):

do{
if(m_bModeless){
....
bModelessSeted = true;
::SendMessage(m_hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
....
} else {
bModelessSeted = false;
RunModalLoop
}

}while(m_bModeless || bModelessSeted);

+ 2 метода — BeginModeless, CompleteModeless где соответсвенно EndModalLoop,EnableModalless и т.п.
В результате DoModal ждет результата....


С уважением Александр.
Re[3]: Прерывание модальности в Диалоге
От: Dutchman Беларусь http://blogs.rsdn.org/ikemefula
Дата: 18.04.02 09:12
Оценка:
Здравствуйте SirAlex, Вы писали:

SA>Написал переопределив DoModal


SA> + 2 метода — BeginModeless, CompleteModeless где соответсвенно EndModalLoop,EnableModalless и т.п.

SA>В результате DoModal ждет результата....



Так я не понял, тебе нравится твой способ или нет ?
Re[3]: Прерывание модальности в Диалоге
От: Dutchman Беларусь http://blogs.rsdn.org/ikemefula
Дата: 18.04.02 09:28
Оценка: 12 (1)
Здравствуйте SirAlex, Вы писали:

SA>Здравствуйте Dutchman, Вы писали:


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

Q257812

D>>Другой способ. В DoModal выполняется CWnd::RunModalLoop — он выбирает сообщения из очереди, а паренту посылает WM_ENTERIDLE, WM_KICKIDLE и тд. Тебе нужно это заменить. Переписывая DoModal, PreModal,PostModal — они виртуальные. Нужно будет кучу проверок делать. Но это несколько неудобный способ. Все из-за того, что DoModal должен ожидать результата.


SA>Написал переопределив DoModal


SA>там вместо


SA>...

SA>RunModalLoop
SA>...

SA>написал (это упрощенный пример):


SA>do{

SA> if(m_bModeless){
SA> ....
SA> bModelessSeted = true;
SA> ::SendMessage(m_hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
SA> ....
SA> } else {
SA> bModelessSeted = false;
SA> RunModalLoop
SA> }
SA>
SA>}while(m_bModeless || bModelessSeted);

SA> + 2 метода — BeginModeless, CompleteModeless где соответсвенно EndModalLoop,EnableModalless и т.п.

SA>В результате DoModal ждет результата....


SA>С уважением Александр.
Re: Прерывание модальности в Диалоге
От: Dutchman Беларусь http://blogs.rsdn.org/ikemefula
Дата: 18.04.02 10:17
Оценка:
Здравствуйте SirAlex, Вы писали:

Вот решение без всяких переопределений DoModal, и тд.

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
    CAboutDlg(CWnd*);

// Dialog Data
    //{{AFX_DATA(CAboutDlg)
    enum { IDD = IDD_ABOUTBOX };
    //}}AFX_DATA

    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CAboutDlg)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //}}AFX_VIRTUAL

// Implementation
protected:
    //{{AFX_MSG(CAboutDlg)
    virtual void OnOK();
    virtual BOOL OnInitDialog();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
protected:

    CWnd* m_pWndParent2;
};

CAboutDlg::CAboutDlg(CWnd* pParent) : CDialog(CAboutDlg::IDD,pParent)
{
    //{{AFX_DATA_INIT(CAboutDlg)
    //}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CAboutDlg)
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    //{{AFX_MSG_MAP(CAboutDlg)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

// App command to run the dialog
void CTestApp::OnAppAbout()
{
    CAboutDlg aboutDlg(AfxGetMainWnd());
    aboutDlg.DoModal();
}

/////////////////////////////////////////////////////////////////////////////
// CTestApp message handlers


void CAboutDlg::OnOK() 
{
    // TODO: Add extra validation here

    if(m_pWndParent2->IsWindowEnabled())
        m_pWndParent2->EnableWindow(FALSE);
    else
        m_pWndParent2->EnableWindow(TRUE);
    EnableWindow(TRUE);}

BOOL CAboutDlg::OnInitDialog() 
{
    CDialog::OnInitDialog();
    
    m_pWndParent2 = FromHandle(CWnd::GetSafeOwner_(m_pParentWnd->GetSafeHwnd(), &m_hWndTop));    
    return TRUE;  // return TRUE unless you set the focus to a control
                  // EXCEPTION: OCX Property Pages should return FALSE
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.