Solved

MFC, C++: continuing execution in a block of code that calls a dialog's DoModal(), without closing the dialog to the user

Posted on 2007-11-19
15
400 Views
Last Modified: 2013-12-14
I'm having a small MFC related problem I hoped one of you could help me with.

I'm writing a database front-end.

The first thing the user sees is an authentication dialog. This is done in my main application class:

BOOL MyApp::InitInstance()
{
      
      CAuthenticate Login;
start:
      Login.DoModal();
      if(Login.m_bTerminate) // if the user pressed cancel (actually, he'd still call OnOK(), but change this bool)
            return FALSE;

// (try/ catch block for database connectivity). if it fails, we goto "start".
      Login.DestroyWindow(); // we have our connection, lets destroy the dialog



How this appears to the user is:

1. He enters his authentication details.
2. He presses OK, and waits up to a few seconds without it being immediately evident that anything is happening - you can't see anything that relates to my application - not the authentication dialog, because it's OnOK() has been called, and not the main window (yet), because it has yet to be initialised.

I'd like to only have the authentication dialog disappear only when the database object has been successfully instantiated, so the user isn't left hanging for several seconds, wondering where the program has gone.

How can this be done?

I thought I could call  Login's OnOK() after the database connection was established, but I'm not aware of any way to make execution continue in the main application block without making the dialog disappear.

While the DB connection object is instantiated on the heap, I'd still rather do this within my main application class, because I've already implemented an assessor method within that class, which is already used extensively in many other views and dialogs.

What should I do?

Regards,
Sternocera
0
Comment
Question by:sternocera
  • 5
  • 5
  • 5
15 Comments
 
LVL 11

Expert Comment

by:DeepuAbrahamK
Comment Utility
The call should be like this:

if(myDlg.DoModal()==ID_OK)
{
..
..
}

Best Regards,
DeepuAbrahamK
0
 
LVL 44

Expert Comment

by:AndyAinscow
Comment Utility
First
Login.DestroyWindow(); // we have our connection, lets destroy the dialog

The DoModal will exit AND DESTROY THE DIALOG as part of that.  You probably have some artefact as the main dialog isn't yet shown in place of the other dialog.


The simplest is to launch your main dialog then the authenticate dialog.  After the authenticate dialog returns then start a timer and set some values.
In the OnTimer first kill the timer then check what is to be done and do it.
0
 
LVL 11

Expert Comment

by:DeepuAbrahamK
Comment Utility
f(Login.DoModal()==ID_CANCEL)
{
...
...
//Exit
}
else if(Login.DoModal()==ID_OK)
{
...
...
...
}

In CAuthenticate::OnOk you should handle the try catch of db connection rather than in the Initinstance here.

CAuthenticate::OnOk ()
{

/ /close the dialog only if you have the db conection
}

Best Regards,
Deepu Abraham K

0
 

Author Comment

by:sternocera
Comment Utility
"The simplest is to launch your main dialog then the authenticate dialog.  After the authenticate dialog returns then start a timer and set some values.
In the OnTimer first kill the timer then check what is to be done and do it."

Andy,

Nice to hear from you again.

I'm not sure what you mean by this.

Because connecting to the database my happen almost immediately, or may take a few seconds, (depending on variables outside my control that cannot be predicted) I cannot know in advance how long it will take.

Here's an idea:

put the try/catch block through which database connectivity is established into a CMyApp bool member function, say, "MakeConnection".

do something like this within the dialog:
CMyApp* pApp = (CMyApp*) AfxGetApp();
if( pApp->MakeConnection())
    CDialog::OnOK()

Do you think this is a good idea?

Thanks

0
 
LVL 11

Expert Comment

by:DeepuAbrahamK
Comment Utility
Is it inside CAuthenticate::OnOk () then it should be alright?

Best Regards,
DeepuAbrahamK

0
 
LVL 11

Assisted Solution

by:DeepuAbrahamK
DeepuAbrahamK earned 100 total points
Comment Utility
I mean it should be fine if you are calling  as follows:

CAuthenticate::OnOk ()
{
CMyApp* pApp = (CMyApp*) AfxGetApp();
if( pApp->MakeConnection())
    CDialog::OnOK()
else
  // do some thing

}

0
 
LVL 44

Accepted Solution

by:
AndyAinscow earned 400 total points
Comment Utility
:-)
Your main dialog is not going to appear until after the OnInitDialog of that dialog has finished and exited.  The DoModal loop (authenticate dialog) when exited will destroy the window objects of that dialog.  So because you still see it on screen means that for some reason the screen has not yet been redrawn there - very likely because windows is waiting for the OnInitDialog to finish.
So, remove the lengthy (database interrogation) code from the OnInitDialog so that will finish, the main dialog is shown and then perform the actions that where in the onInitDialog that took time.  eg in response to a timer message.

Much neater however would be the following logic

authenticate dialog display
check results
main dialog display
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 

Author Comment

by:sternocera
Comment Utility
Andy,

You're right, it makes sense for database interrogation to actually occur within the authentication dialog, and no where else - you're also right about the database stuff delaying display of the main window (I understood that, but hoped to somehow put off the CDialog disapearing until the connection was established).

I should just instantiate it on the heap within the dialog, then copy a pointer to it to the main app object.

I'll let you know how I get on.

Thanks

and thank you DeepuAbrahamK
0
 

Author Comment

by:sternocera
Comment Utility
Andy, DeepuAbrahamK,

That's gone nicely, thank you both very much.

I hope you'll consider the way I've aportioned points fair,

Regards,
Sternocera
0
 
LVL 11

Expert Comment

by:DeepuAbrahamK
Comment Utility
Cool all the best !
0
 
LVL 44

Expert Comment

by:AndyAinscow
Comment Utility
:-)
0
 

Author Comment

by:sternocera
Comment Utility
One other follow-up question: Now my connect button appears "pushed-down" for as long as it takes to connect to the DB. Is it possible to have it "come up" before the db connection occurs, so it won't get stuck (If not, I'll live with it)?

Thanks,
Sternocera
0
 
LVL 44

Expert Comment

by:AndyAinscow
Comment Utility
If the button 'comes up' and the user sees nothing happening then often the button will be clicked again in desperation.
0
 

Author Comment

by:sternocera
Comment Utility
Yeah, that's an interesting perspective. I was going to do a little "connecting..." animation, but perhaps what you've suggested in more consistent with the expectations of windows' users.

Thanks
0
 
LVL 44

Expert Comment

by:AndyAinscow
Comment Utility
An animation would of course reenforce that.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
Jaspersoft Studio is a plugin for Eclipse that lets you create reports from a datasource.  In this article, we'll go over creating a report from a default template and setting up a datasource that connects to your database.
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

763 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now