c++winapieditcontrol

Difficulties in changing the background color of edit control


I have edit control in a dialog box which input is checked for validity.

I should indicate validity by changing the background color of an edit control if input is invalid, otherwise I should do nothing.

I am checking the input in EN_CHANGE handler and if input is invalid I store the handle of the edit control in a vector. In the end I call InvalidateRect( (HWND)lParam, NULL, TRUE ); so edit control can be repainted with proper color.

To repaint edit control I am handling WM_CTLCOLOREDIT like this:

case WM_CTLCOLOREDIT:
    {
        bool IsInvalid = false;  // does this edit control hold invalid text ?

        // vector InvalidInput contains handles of edit controls
        // with invalid input, so we check if our window is stored there
        for( vector<HWND>::size_type i = 0; 
            !IsInvalid && ( i < InvalidInput.size() ); i++ )
        {
            if( InvalidInput[i] == (HWND)lParam )
                IsInvalid = true;
        }

        // if input is invalid change background color to light gray
        if( IsInvalid )
        {
            // Needed SetBkMode for text background transparency 
            SetBkMode( (HDC)wParam, TRANSPARENT ); 
            // return light gray brush 
            return (INT_PTR)( (HBRUSH)GetStockObject( LTGRAY_BRUSH ) );
        }
        else     
            return FALSE;   // say we didn't handle it 
                            // so dialog procedure can do that for us
    }

After I start the program edit control is painted properly.

After I type valid entry edit control is painted properly.

After I type invalid character immediately after, background is colored into light gray and everything seems to work fine.

If I delete the invalid character then the background stays gray instead of returning to default system color.

What am I doing wrong and how should I fix this ?

EDIT:

If I put InvalidateRect() in my WM_COMMAND handler for IDC_MYEDIT then the problem seems to disappear:

case WM_COMMAND:
    {
        switch( LOWORD(wParam) )
        {
        case IDC_MYEDIT:
            {
                if( HIWORD(wParam) == EN_CHANGE )
                {
                    //do your validation stuff
                }
                InvalidateRect(...);
            }
            break;
        // the rest of the code...

Solution

  • The error is here

        else     
            return FALSE;   // say we didn't handle it 
                            // so dialog procedure can do that for us
    

    The WM_CTLCOLOREDIT message is listed as one of the special exceptions to the rule that returning FALSE means "not handled". It must be handled. If you don't want to handle it, you can pass the message to DefWindowProc.