kpcnatraj
Hello,
We have created a VC++ application that has 2 menu options.
- submenu 1 opens the VBA IDE
- submenu 2 opens a Modal Dialog to execute a functionality (say FUNC1)
Whenever we directly select submenu 2 the application executes properly.
But the application hangs whenever we select submenu 1 (opening the VBA
IDE) and then select submenu 2 (having the VBA IDE still open)
On debugging we find that in the problematic case (in which the
application hangs), the control fails to come out of an infinite loop
inside the mfc source code wincore.cpp
The details of the code flow are given below for this problematic case:
The modal dialog is created using the function INT_PTR
CDialog::DoModal() (present in mfc source code dlgcore.cpp)
which inturn calls int CWnd::RunModalLoop(DWORD dwFlags) present
in the mfc source code wincore.cpp (elaborated at the end of this
message). The control gets struck in this function (which has an
infinite loop inside it) thereby causing the application to hang.
We are unable to understand the reason for this code behaviour and
would like to clarify whether there is any bug in the MFC source due to
which this occurs.
Has anyone faced such similar problems while creating Modal
Dialogs . If there is any work around to tackle this problem we
would be glad to know.
Thanks in advance,
Ravi.
---------------------------------------------------------------
(source code details of function RunModalLoop present in wincore.cpp,
Courtesy : Microsoft corp.)
int CWnd::RunModalLoop(DWORD dwFlags)
{
ASSERT(::IsWindow(m_hWnd)); // window must be created
ASSERT(!(m_nFlags & WF_MODALLOOP)); // window must not already be in modal state
// for tracking the idle time state
BOOL bIdle = TRUE;
LONG lIdleCount = 0;
BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);
HWND hWndParent = ::GetParent(m_hWnd);
m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);
MSG *pMsg = AfxGetCurrentMessage();
// acquire and dispatch messages until the modal state is done
for (;;) <---- (the application fails to exit this infinite loop)
{
ASSERT(ContinueModal());
// phase1: check to see if we can do idle work
while (bIdle &&
!::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
{
ASSERT(ContinueModal());
// show the dialog when the message queue goes idle
if (bShowIdle)
{
ShowWindow(SW_SHOWNORMAL);
UpdateWindow();
bShowIdle = FALSE;
}
// call OnIdle while in bIdle state
if (!(dwFlags
& MLF_NOIDLEMSG) && hWndParent != NULL &&
lIdleCount == 0)
{
// send WM_ENTERIDLE to the parent
::SendMessage(hWndParent, WM_ENTERIDLE,
MSGF_DIALOGBOX, (LPARAM)m_hWnd);
}
if ((dwFlags & MLF_NOKICKIDLE) ||
!SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX,
lIdleCount++))
{
// stop idle processing next time
bIdle = FALSE;
}
}
// phase2: pump messages while available
do
{
ASSERT(ContinueModal());
// pump message, but quit on WM_QUIT
if (!AfxPumpMessage())
{
AfxPostQuitMessage(0);
return -1;
}
// show the window when certain special messages rec'd
if (bShowIdle &&
(pMsg->message == 0x118 || pMsg->message ==
WM_SYSKEYDOWN))
{
ShowWindow(SW_SHOWNORMAL);
UpdateWindow();
bShowIdle = FALSE;
}
if (!ContinueModal())
goto ExitModal;
// reset "no idle" state after pumping "normal" message
if (AfxIsIdleMessage(pMsg))
{
bIdle = TRUE;
lIdleCount = 0;
}
} while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
}
ExitModal:
m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
return m_nModalResult;
}
--------------------------------------------------------------