MFC OnEnChange handler function - infinite loop
Hi,
(I'm using VS++2005)
I put edit box control (with ID - ID_edit_box) on my dialog, and associate (with handler wizard) two varibles for it: control (c_editbox) and value (v_editbox) variable. Also I associate handler function OnEnChangeedit_box with that edit box control. Suppose that we may enter just one digit in edit box, and that digit can be 0 or 1. If we enter some other value - what I want is that content of that edit box is automaticaly cleared, so user can't see that he type anything (in other words user can not enter anything except 0/1 in edit box). I do that check in onEnChangeedit_box function. Here is the code:
void CSDRDlg::OnEnChangeedit_box()
{
CWnd* pWnd;
CString edit_box_temp;
pWnd = GetDlgItem(ID_edit_box);
pWnd->GetWindowText(edit_box_temp);
if ((edit_box_temp == "0" || edit_box_temp == "1")
{...do something - i.e. setfocus on some other edit box }
else
{
pWnd->SetWindowText(""); // clear the content of edit box
//... any other statement below will not be executed because the
//above line cause again call of this function
}
}
I debug and discover that line: "pWnd->SetWindowText("");" cause infinite loop because we change control content in this function which truggers again her call.
But I change above code like this:
void CSDRDlg::OnEnChangeedit_box()
{
UpdateData(TRUE);
if ((v_editbox == "0" || v_editbox== "1")
{...do something - i.e. setfocus on some other edit box }
else
{
v_editbox = "";
UpdateData(FALSE);
}
}
and that works what I want but can someone explain to me why when we call
v_editbox = "";
UpdateData(FALSE);
that dont cause infinite loop.
Best regards
Re: MFC OnEnChange handler function - infinite loop
The answer can be found in UpdateData source code:
Code:
BOOL CWnd::UpdateData(BOOL bSaveAndValidate)
{
ASSERT(::IsWindow(m_hWnd)); // calling UpdateData before DoModal?
CDataExchange dx(this, bSaveAndValidate);
// prevent control notifications from being dispatched during UpdateData
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
HWND hWndOldLockout = pThreadState->m_hLockoutNotifyWindow;
ASSERT(hWndOldLockout != m_hWnd); // must not recurse
pThreadState->m_hLockoutNotifyWindow = m_hWnd;
BOOL bOK = FALSE; // assume failure
TRY
{
DoDataExchange(&dx);
bOK = TRUE; // it worked
}
CATCH(CUserException, e)
{
// validation failed - user already alerted, fall through
ASSERT(!bOK);
// Note: DELETE_EXCEPTION_(e) not required
}
AND_CATCH_ALL(e)
{
// validation failed due to OOM or other resource failure
e->ReportError(MB_ICONEXCLAMATION, AFX_IDP_INTERNAL_FAILURE);
ASSERT(!bOK);
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
pThreadState->m_hLockoutNotifyWindow = hWndOldLockout;
return bOK;
}
According to the notes, line
pThreadState->m_hLockoutNotifyWindow = m_hWnd;
prevents notifications. Since they use undocumented functions, we cannot do the same in our own code, and need to use some flag which must be checked in notification handler:
Code:
void CSDRDlg::OnEnChangeedit_box()
{
if ( m_bNotificationDisabled )
return;
m_bNotificationDisabled = TRUE;
pWnd->SetWindowText("");
m_bNotificationDisabled = FALSE; // return to defaut
}
Another way is clearing editbox asynchronously. You can post user-defined message to the dialog (PostMessage, not SendMessage), and clear editbox in the message handler.
Re: MFC OnEnChange handler function - infinite loop
Another solution would be to check the length of the string:
Code:
pWnd = GetDlgItem(ID_edit_box);
pWnd->GetWindowText(edit_box_temp);
if (strlen(edit_box_temp)>0)
{
if ((edit_box_temp == "0" || edit_box_temp == "1")
{
...do something - i.e. setfocus on some other edit box
}
else
{
pWnd->SetWindowText(""); // clear the content of edit box
//... any other statement below will not be executed because the
//above line cause again call of this function
}
}
Hope that helps.
Re: MFC OnEnChange handler function - infinite loop
Quote:
Originally Posted by
melinda123
Suppose that we may enter just one digit in edit box, and that digit can be 0 or 1. If we enter some other value - what I want is that content of that edit box is automaticaly cleared, so user can't see that he type anything (in other words user can not enter anything except 0/1 in edit box).
If this is really the case, and not just to explain the question, would it not be much clearer to the user to dispay a check box, instead of an edit box?