Anyway to stop a CView from being closed?
-
VC6, MFC, XP Hi - I need to prevent a CView from being closed before a thread operation is complete. The mainframe also has a secondary thread and I've handled that situation by reacting to the WM_CLOSE message. The view, which has it's own worker thread, doesn't seem to get the WM_CLOSE message (even if I put the code in) and reacting to WM_DESTROY in the view is too late to stop it from being closed. Any suggestions? Thank you, Paul
-
VC6, MFC, XP Hi - I need to prevent a CView from being closed before a thread operation is complete. The mainframe also has a secondary thread and I've handled that situation by reacting to the WM_CLOSE message. The view, which has it's own worker thread, doesn't seem to get the WM_CLOSE message (even if I put the code in) and reacting to WM_DESTROY in the view is too late to stop it from being closed. Any suggestions? Thank you, Paul
Paul Belikian wrote:
Hi - I need to prevent a CView from being closed before a thread operation is complete.
One way would be to use a
CEvent
object. When the view is being closed, callWaitForSingleObject()
to wait for the event to become signaled. When the thread operation is complete, signal the event."One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
-
Paul Belikian wrote:
Hi - I need to prevent a CView from being closed before a thread operation is complete.
One way would be to use a
CEvent
object. When the view is being closed, callWaitForSingleObject()
to wait for the event to become signaled. When the thread operation is complete, signal the event."One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
Thanks David, that is a good suggestion. I think my issue is that I'm not sure which (or what) message to hook in the view in order to wait for the event. :-O The messages I've tried do not stop the view from being closed; for example, if I put a Sleep(5000) call in the view's WM_DESTROY handler, the window is still closed instantly. I need a place where the view will remain open if I delay the WM_xxxxxx message. I'm doing this in case the user kills the app with the upper 'X' in the application's window ...perhaps I should look into that aspect. This is the only thread related thing I need to clean up. If the user doesn't kill the app while the background process is running (i.e. in the middle of loading a large database), all is well (but when do users wait for anything ? :laugh: ), however if they do kill the app, I need to stop the views from being closed before the thread is dead. The threads can be stopped in an orderly manner at any time. Thanks for your suggestion. Paul
-
Thanks David, that is a good suggestion. I think my issue is that I'm not sure which (or what) message to hook in the view in order to wait for the event. :-O The messages I've tried do not stop the view from being closed; for example, if I put a Sleep(5000) call in the view's WM_DESTROY handler, the window is still closed instantly. I need a place where the view will remain open if I delay the WM_xxxxxx message. I'm doing this in case the user kills the app with the upper 'X' in the application's window ...perhaps I should look into that aspect. This is the only thread related thing I need to clean up. If the user doesn't kill the app while the background process is running (i.e. in the middle of loading a large database), all is well (but when do users wait for anything ? :laugh: ), however if they do kill the app, I need to stop the views from being closed before the thread is dead. The threads can be stopped in an orderly manner at any time. Thanks for your suggestion. Paul
Paul Belikian wrote:
I think my issue is that I'm not sure which (or what) message to hook in the view in order to wait for the event.
Have you tried responding to
WM_CLOSE
(i.e., returning0
) in the frame class?"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
-
Paul Belikian wrote:
I think my issue is that I'm not sure which (or what) message to hook in the view in order to wait for the event.
Have you tried responding to
WM_CLOSE
(i.e., returning0
) in the frame class?"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
Mainframe seems to work fine and stops the thread running in the mainframe. However I need to stop the view from closing before the view's thread is stopped (each view has it's own thread and the mainframe has another thread):
void CMainFrame::OnClose()
{
#ifdef _USE_BACKGROUND_THREAD_
DWORD dwExitCode;
m_pBackThread->Stop(dwExitCode, 0);
if(m_pBackThread->GetActivityStatus() != CThread::THREAD_RUNNING)
{
TRACE("Mainframe: Thread Busy, Can't close yet...\n");
PostMessage(WM_CLOSE);
}
else
{
TRACE("Mainframe: Can close now\n");
m_pBackThread->Stop(dwExitCode);// Save the current state for tool bars and menus. SaveCommandBars(\_T("CommandBars")); // Save the current state for docking panes. CXTPDockingPaneLayout layoutNormal(&m\_paneManager); m\_paneManager.GetLayout(&layoutNormal); layoutNormal.Save(\_T("NormalLayout")); CMDIFrameWnd::OnClose();
}
#else
// Save the current state for tool bars and menus.
SaveCommandBars(_T("CommandBars"));// Save the current state for docking panes. CXTPDockingPaneLayout layoutNormal(&m\_paneManager); m\_paneManager.GetLayout(&layoutNormal); layoutNormal.Save(\_T("NormalLayout")); CMDIFrameWnd::OnClose();
#endif
}
-
Mainframe seems to work fine and stops the thread running in the mainframe. However I need to stop the view from closing before the view's thread is stopped (each view has it's own thread and the mainframe has another thread):
void CMainFrame::OnClose()
{
#ifdef _USE_BACKGROUND_THREAD_
DWORD dwExitCode;
m_pBackThread->Stop(dwExitCode, 0);
if(m_pBackThread->GetActivityStatus() != CThread::THREAD_RUNNING)
{
TRACE("Mainframe: Thread Busy, Can't close yet...\n");
PostMessage(WM_CLOSE);
}
else
{
TRACE("Mainframe: Can close now\n");
m_pBackThread->Stop(dwExitCode);// Save the current state for tool bars and menus. SaveCommandBars(\_T("CommandBars")); // Save the current state for docking panes. CXTPDockingPaneLayout layoutNormal(&m\_paneManager); m\_paneManager.GetLayout(&layoutNormal); layoutNormal.Save(\_T("NormalLayout")); CMDIFrameWnd::OnClose();
}
#else
// Save the current state for tool bars and menus.
SaveCommandBars(_T("CommandBars"));// Save the current state for docking panes. CXTPDockingPaneLayout layoutNormal(&m\_paneManager); m\_paneManager.GetLayout(&layoutNormal); layoutNormal.Save(\_T("NormalLayout")); CMDIFrameWnd::OnClose();
#endif
}
The mainframe should know all its child views. Create a function in each view that the mainframe calls from its OnClose which can wait / allow / disallow the close. Judy
Be wary of strong drink. It can make you shoot at tax collectors - and miss. Lazarus Long, "Time Enough For Love" by Robert A. Heinlein
-
The mainframe should know all its child views. Create a function in each view that the mainframe calls from its OnClose which can wait / allow / disallow the close. Judy
Be wary of strong drink. It can make you shoot at tax collectors - and miss. Lazarus Long, "Time Enough For Love" by Robert A. Heinlein
Hello Judy, yes, thank you for the suggestion. I actually did go that route using the DocTemplate to find all the views that I needed to check before closing. I chose this method because I also have multiple types of documents in the app - here is the code: forgive the mess, I'm self-taught :-O
void CMainFrame::OnClose()
{
#ifdef _USE_CMC6INVOICE_THREAD_POSITION pos, posView; pos = theApp.m\_pCmc6InvoiceDocTemplate->GetFirstDocPosition(); while(pos != NULL) { CDocument \*pDoc = theApp.m\_pCmc6InvoiceDocTemplate->GetNextDoc(pos); if(pDoc!= NULL) { posView = pDoc->GetFirstViewPosition(); while(posView != NULL) { CView \* pView = pDoc->GetNextView(posView); if(pView->IsKindOf(RUNTIME\_CLASS(CCMC6InvoiceView))) { CCMC6InvoiceView \* pInv = (CCMC6InvoiceView \*) pView; if(pInv->m\_clsInvoice->m\_pThread != NULL) { if(pInv->m\_clsInvoice->m\_pThread->GetActivityStatus() == THREAD\_NOTPREPARED\_TO\_TERMINATE) { TRACE("Mainframe: OnClose() ->CMC6InvoiceView Thread Busy, Can't close yet...\\n"); Sleep(200); PostMessage(WM\_CLOSE); return; } } } } } }
#endif
#ifdef _USE_BACKGROUND_THREAD_
DWORD dwExitCode;
m_pBackThread->Stop(dwExitCode, 0);
if(m_pBackThread->GetActivityStatus() == THREAD_NOTPREPARED_TO_TERMINATE)
{
TRACE("Mainframe: OnClose() ->BackProcess Thread Busy, Can't close yet...\n");
Sleep(200);
PostMessage(WM_CLOSE);
}
else
{
TRACE("Mainframe: OnClose() ->Can close now\n");
m_pBackThread->Stop(dwExitCode);// Save the current state for tool bars and menus. SaveCommandBars(\_T("CommandBars")); // Save the current state for docking panes. CXTPDockingPaneLayout layoutNormal(&m\_paneManager); m\_paneManager.GetLayout(&layoutNormal); layoutNormal.Save(\_T("NormalLayout")); CMDIFrameWnd::OnClose();
}
#else
// Save the current state for tool bars and menus.
SaveCommandBars(_T("CommandBars"));
// Save the current state for docking panes.
CXTPDockingPaneLayout layoutNormal(&m_paneManager);
m_paneManager.GetLayout(&layoutNormal);
layoutNormal.Save(_T("NormalLayout"));CMDIFrameWnd::OnClose();
#endif
}