Click here to Skip to main content
14,970,418 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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:

C++
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:
C++
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...

END OF EDIT

Thank you.

Best regards.
Posted
Updated 27-Apr-14 14:38pm
v2

Look again at the what the function is supposed to return

http://msdn.microsoft.com/en-us/library/windows/desktop/bb761691%28v=vs.85%29.aspx[^]

At no stage does it ask you to return FALSE so this is wrong. The bit about returning false is for a dialog box handler that is coloring it's child windows backgrounds which you are not doing.

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


It says "By default, the DefWindowProc function selects the default system colors for the edit control."

So what you are supposed to do is simply pass the message to the default window handler if you want the normal background color.

return (DefWindowProc(hwnd, uMsg, wParam, lParam));
   
v4
Comments
AlwaysLearningNewStuff 27-Apr-14 23:41pm
   
From that same documentation:

"If the dialog box procedure returns FALSE, then default message handling is performed."

Please notice that my edit control is in a dialog box.
Perhaps read the next line

The DWL_MSGRESULT value set by the SetWindowLong function is ignored.


Want to guess whats in the DWL_MSGRESULT that is now going to be ignored when you return false????

Yes the default handler gets called but there is no valid brush.

I have no idea what microsoft's intention was with this but the simple solution from where you are is to simply call the default handler yourself manually while DWL_MSGRESULT is still valid.

It has been like that for a very very long time, perhaps it's a bug or oversight I just know it works.

Realistically for commercial products most of us subclass the standard edit box for types of entries with the edit boxes handling there own validation, tabbing etc. It means far more reusable code and much less playing around with dialog handlers in many cases you can just use the standard dialog handler.
   
v6
Comments
AlwaysLearningNewStuff 28-Apr-14 21:35pm
   
I have tired your approach and it did work. Still, edit control's borders get thicker/darker in certain cases. Picture can explain this better and I have already documented this behavior here: http://stackoverflow.com/questions/23378938/edit-control-not-repainted-entirely-with-chosen-brush

Do you have any idea how to fix it? Other than that everything works fine. Thank you for your help.

As for subclassing edit control to accept only floating numbers, I have tried it myself but if you have any suggestions you could post the as an answer to this question: http://www.codeproject.com/Questions/728310/Locale-aware-edit-control-subclassing-for-decimal

I will gladly take a look at it.

Best regards until next time.
leon de boer 29-Apr-14 14:12pm
   
The thicker border is caused because the gray from the old background still remains when you delete the letter r.

Simply invalidate the whole window to force the window to redraw to fix it by using

InvalidateRect(hWnd, NULL, TRUE);


I am currently preparing a full article to put on codeproject to show you a much more elegant way to do all that with a subclass and it works in a dialog or standard window without change and automatically calls a validate procedure if you require.
AlwaysLearningNewStuff 29-Apr-14 21:15pm
   
Tried with InvalidateRect( (HWND)lParam, NULL, TRUE ); but it did not help... <br>
 <br>
Thank you for the article, please notify me with a comment when you finish. Can't wait. Good luck!

Since this is a new problem I have accepted your answers and 5ed them.

Thanks again!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900