Solved

changing a modal dialog to modalless - VC2008

Posted on 2012-03-26
11
318 Views
Last Modified: 2012-04-17
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.
0
Comment
Question by:Mydeen Yussouf
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 3
  • 2
11 Comments
 
LVL 44

Assisted Solution

by:AndyAinscow
AndyAinscow earned 200 total points
ID: 37770167
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
 
LVL 34

Assisted Solution

by:sarabande
sarabande earned 300 total points
ID: 37770478
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
 
LVL 1

Author Comment

by:Mydeen Yussouf
ID: 37777718
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 44

Expert Comment

by:AndyAinscow
ID: 37777819
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
 
LVL 34

Assisted Solution

by:sarabande
sarabande earned 300 total points
ID: 37777890
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
 
LVL 44

Assisted Solution

by:AndyAinscow
AndyAinscow earned 200 total points
ID: 37778001
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
 
LVL 1

Author Comment

by:Mydeen Yussouf
ID: 37778041
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
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 37778070
>>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
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 37778076
ps.  If you did intercept the WM_ACTIVATE as suggested by Sara then you would need extra code in that function as well.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 37778088
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
 
LVL 34

Accepted Solution

by:
sarabande earned 300 total points
ID: 37780482
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

Featured Post

[Webinar] Code, Load, and Grow

Managing multiple websites, servers, applications, and security on a daily basis? Join us for a webinar on May 25th to learn how to simplify administration and management of virtual hosts for IT admins, create a secure environment, and deploy code more effectively and frequently.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
How to repeat the data 4 43
Coding for the first time 9 99
Bitwise and to sum elements 2 52
Disable the weekends on datepicker control 6 51
In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

739 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question