changing a modal dialog to modalless - VC2008

Hi Experts,

I have inherited some code that creates a modal dialog box.

	//In the menu event handler

	if( m_pCDialogDerivedDlg == NULL  )
	{		
		m_pCDialogDerivedDlg = new CDialogDerivedDlg(this);
		m_pCDialogDerivedDlg->SetShellReference( m_pShell ); 
		m_pCDialogDerivedDlg->Create(CBMTDonorRecipHLAMatchDlg::IDD);
		m_pCDialogDerivedDlg->ShowWindow(SW_SHOW);         
		
	}

Open in new window


This was done using VC++/MFC in VS2006 and ported to VS2008.

Now I have a requirement to make the dialog modalless, so users could intereact with the initiating application while the dialog is still open. What is the easiset way to make the dialog modalless?

thanks in advance.
LVL 1
ol muserTechnology GeneralistAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

AndyAinscowFreelance programmer / ConsultantCommented:
Very interesting question.
The following code will do what you ask for - create and display a modeless dialog.

      if( m_pCDialogDerivedDlg == NULL  )
      {            
            m_pCDialogDerivedDlg = new CDialogDerivedDlg(this);
            m_pCDialogDerivedDlg->SetShellReference( m_pShell );
            m_pCDialogDerivedDlg->Create(CBMTDonorRecipHLAMatchDlg::IDD);
            m_pCDialogDerivedDlg->ShowWindow(SW_SHOW);        
            
      }

Look very carefully - there is NO change made whatsoever.

If your main app isn't responding then it is something else that is stopping it.  Maybe look into the function SetShellReference and see if there is some code which disables the main app window.
0
sarabandeCommented:
to add to Andy's comment:

modal dialog boxes would have no dlg.Create() call and would be started by dlg.DoModal().

none of the statements you posted does wait. so your current message loop remains responsive (menus, buttons, background formview). if the dialog covers all background you should make it smaller or let the user minimize it.

Sara
0
ol muserTechnology GeneralistAuthor Commented:
you both are right, I think I was confused by the behaviour that the main application does not come to the front if the child dialog is bloking the view, even though minimizing the child does the trick. Is there a way to do that? Bring the parent to the fore groundwithout mimimizing the child? thanks!
0
Become a CompTIA Certified Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

AndyAinscowFreelance programmer / ConsultantCommented:
Is this what you want?

 if( m_pCDialogDerivedDlg == NULL  )
      {            
            m_pCDialogDerivedDlg = new CDialogDerivedDlg();   <<---- No this
            m_pCDialogDerivedDlg->SetShellReference( m_pShell );
            m_pCDialogDerivedDlg->Create(CBMTDonorRecipHLAMatchDlg::IDD);
            m_pCDialogDerivedDlg->ShowWindow(SW_SHOW);        
           
      }
0
sarabandeCommented:
you could handle the WM_ACTIVATE messsage which would be sent twice in your case. once for the old dialog (window) with wParam is WA_INACTIVE and after for the new dialog (clicked on by the user) with wParam is WA_ACTIVE.

Sara
0
AndyAinscowFreelance programmer / ConsultantCommented:
Another point to remember.  The user has performed an action to display this dialog.  If you automatically hide the dialog (eg. by bringing the main window in front of it) then it is likely the user will think the dialog has not been shown and will try again (and again) to show the dialog - eventually saying this program is c**p, it doesn't work properly.

If the dialog completely hides the main window of the app you could consider opening the dialog so it only partially covers the main window.  (look at GetWindowRect and SetWindowPos in help for more info on how you could do that.)
0
ol muserTechnology GeneralistAuthor Commented:
Good point Andy. Could I not check if the dialog has been instantiated already and if so bring it to the foreground if the user my mistake tries to open it again?

thanks both
0
AndyAinscowFreelance programmer / ConsultantCommented:
>>Could I not check if the dialog has been instantiated already and if so bring it to the foreground if the user my mistake tries to open it again?

To be honest I thought you were doing that already - because it was a modeless dialog and you had the if statement:
if( m_pCDialogDerivedDlg == NULL  )

Does this do what you want?
if( m_pCDialogDerivedDlg == NULL  )
{
//your code to create the dialog stays here
}
else
  m_pCDialogDerivedDlg->SetFocus();
0
AndyAinscowFreelance programmer / ConsultantCommented:
ps.  If you did intercept the WM_ACTIVATE as suggested by Sara then you would need extra code in that function as well.
0
AndyAinscowFreelance programmer / ConsultantCommented:
pps.
I hope you have prevented the user destroying this modeless dialog (without resetting the pointer m_pCDialogDerivedDlg to null) , otherwise you have no way to create it a second time.
0
sarabandeCommented:
to handle deletion//destroying of the modeless dialog properly you could/should handle the WM_NCDESTROY message in that dialog. that message is the last message handled by the derived CDialog object what means you savely could do

void MyModelessDlg::OnNcDestroy()
{
       // send user message to parent dialog 
       GetParent()->PostMessage(MY_WM_USER_MODELESS_DLG_DESTROYED, 0, 0);
       delete this;   // don't do that in another handler but in OnNcDestroy
}

Open in new window


The parent dialog of course needs to pass 'this' as parent argument if you do so. it also would handle the user message (which was defined as a const integer in the range from WM_USER +1 through WM_USER + 0x7ffff) and would set the pointer member to 0 in the handler (do not delete it!!!) .

Sara
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.