Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 906
  • Last Modified:

MFC Dialog Application with Splash Dialog Box

Application:  MFC Dialog base program with no Main Window.
Before I display the Main Dialog Box, I am doing some processing and displaying a Splash Message Dialog Box to user using a thread.

CMsgDlg  m_MsgDlg;                  // Message CDialog
AfxBeginThread(MessageProc,&m_MsgDlg);      // Start Message
m_MsgDlg.EndDialog(0);                  // Terminate Message

UINT MessageProc (LPVOID pParam)
      {
      CMsgDlg* pDlg = (CMsgDlg*) pParam;      
      pDlg->DoModal();    // Execute Splash Message Dialog
      return 0;          // Terminal Thread
      }

Problem:
If I display a "AfxMessageBox" after terminating the thread "EndDialog", the Message Title Bar of the Message Box is grayed out and not Top Most Window.

If I display my Application Dialog, I get same result until
I select "Set Foreground" in dialog properties.
How can I correct this so it behaves correctly??? Thank You
J Jones...
0
JJONES
Asked:
JJONES
1 Solution
 
JJONESAuthor Commented:
Edited text of question
0
 
q2guoCommented:
I think the problem here is that after line

m_MsgDlg.EndDialog(0); // Terminate Message

the thread doesn't terminate right away.

So, solution would be to wait till the thread actually terminates

try adding this do loop after the endDialog

LPDWORD exitcode == STILL_ACTIVE;
do {
      ::GetExitCodeThread(PASSIN_HANDTOTHETHREAD, &exitcode);
}while (exitcode == STILL_ACTIVE);

If the specified thread has not terminated, the termination status returned is STILL_ACTIVE

So this loop would make sure that the thread ends before you go on.
0
 
JJONESAuthor Commented:
I try your solution but did not work. The Thread is terminated,
but the AfxMessagebox Dialog is gray out and not top most window.

If I issue a AfxMessageBox before starting the my Splash Dialog,
it works great.

The Problem is after splash screen is removed the next window  brought up is not at the top of the Z Order.
SetForegroundWindow() does not work since there is no active
window before AfxMessageBox message is display.

I appreciate your answer, but is there another solution?....
Thank You...

0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
mikeblasCommented:
This code:

CMsgDlg m_MsgDlg; // Message CDialog
AfxBeginThread(MessageProc,&m_MsgDlg); // Start Message
m_MsgDlg.EndDialog(0); // Terminate Message

is wrong. You shouldn't close the window asyncronously from another thread. Instead, you should post a WM_CLOSE message to the dialog box.

The way you're handling the box is confusing MFC about the owner of the box and the state of the main thread's message pump.

.B ekiM

PS: q2guo's suggstion is bogus; the correct way to wait for the termination of a thread is to use WaitForSingleObject(). Using a relentless loop as he suggested wastes CPU time that the running thread needs, and it isn't a reliable method.
0
 
JJONESAuthor Commented:
What's m_pMainWnd at the time you create the thread?

.B ekiM


0
 
mikeblasCommented:
mikeblas...
m_pMainWnd = 0x00000000 {CWnd hWnd=0xc8000000}

I execute my Splash Message Thread before I create my Main Dialog
Object and DO NOT set "m_pMainWnd" in "InitInstance".
If I set "m_pMainWnd", what would I set it to???

Here is my Code....

BOOL CLoan32App::InitInstance()
{
CMsgDlg m_MsgDlg;       // Splash Message CDialog
AfxBeginThread(MessageProc,&m_MsgDlg);
.
.
EndMessageThread();     // End of Thread
AfxMessageBox.....      // Could Issue an Error Message [Here]
.
CLoan32Dlg  MainDlg;    // Main Dialog Object
int nReturn = MainDlg.DoModal();
.
.
return FALSE;
}

void CLoan32App::EndMessageThread()
{
m_pThread->SuspendThread();  
m_pThread->SetThreadPriority(THREAD_PRIORITY_TIME_CRITICAL);
m_pThread->ResumeThread();

// Put this code here to check for Validate m_MsgDlg Windows
// I have discovered that sometimes this code may execute before
// Thread fully created...

if (IsWindow (m_MsgDlg) ==0)      // Dialog a Valid Window?
    SleepEx (20, TRUE);            // No - Sleep for 20 MilliSeconds

if (IsWindow (m_MsgDlg) ==0)      // Dialog Still Invalid?
    SleepEx (20, TRUE);            // No - Sleep for another 20 ms

m_MsgDlg.SendMessage(WM_CLOSE);
WaitForSingleObject(m_pThread, INFINITE);
}

Thanks again for your Help ....      
0
 
JJONESAuthor Commented:
First of all do not pass CWnd derived class pointers across thread boundaries, only variable of type HWND can be passsed. Then I don't understand why you need to display splash screen using another thread, it can be implemented in the main thread without a problem. If you still need create splash screen using multithreading create it in the main htread but other background calculations do in another worker thread. Also use global Win#@ API functions PostMessage and SendMessage to communicate from worker thread to main UI thread.
0
 
galkinCommented:
Thank you for your help.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now