Is it possible to change the background color of a read only edit control
Asked Answered
P

1

9

enter image description hereI've been trying to find a simple solution to change the color of an edit control that has the ES_READONLY flag. The code I have (sort of) works when the edit control is editable, however has no effect on my edit control that has the read only flag.

case WM_CTLCOLOREDIT:
{
  HDC hdc = (HDC)wParam;
  //if (GetDlgItem(hwnd, IDC_EDIT_IN) == (HWND)lParam)
  //{
      SetTextColor(hdc, RGB(255, 255, 255)); // Set text color to white
      SetBkColor(hdc, RGB(255, 255, 255)); // Set background color to black
  //}
  return 0;
}
break;

I have the comment there just to check if my code worked, and it does on the edit control that's not read only. If i take out ES_READONLY on my other edit control, it does work on it. I'm creating a chat program and don't want the user to be able to type in the chatbox area. And when its read only, it makes it a gray-ish color, but I want a white color. Is there another way to do this? Also The color only colors the area where text is, not the entire height of the edit control. What am I doing wrong?

Pietrek answered 1/1, 2015 at 18:43 Comment(2)
I recommend you look at WM_CTLCOLORSTATICNoncommittal
Read the MSDN article, it tells you to return a brush.Escharotic
A
11

You need to create a brush and keep track of it. Then you return this brush instead of return 0 in your code snippet. Once brush is no longer needed you must delete it. This is usually done in response to WM_DESTROY message.

In your case you could dodge the bullet by using stock brush, which is what I would recommend.

When in readonly mode, edit controls respond to WM_CTLCOLORSTATIC instead of WM_CTLCOLOREDIT, so you must properly handle this message:

case WM_CTLCOLORSTATIC:
{
    if( (HWND)lParam == GetDlgItem(hwnd, IDC_EDIT_IN) )
    {
        SetBkMode( (HDC)wParam, TRANSPARENT );  
        SetTextColor(hdc, RGB(255, 255, 255));
        return (LRESULT)( (HBRUSH)GetStockObject(BLACK_BRUSH) );  
        // if edit control is in dialog procedure change LRESULT to INT_PTR
    }
    else  // this is some other static control, do not touch it!!
        return DefWindowProc( hwnd, message, wParam, lParam );
}

When painting edit/static control, you have 3 parts available for painting:

  • text color
  • text background
  • control's background

In order to paint entire control into desired color you must return brush with desired color ( return (LRESULT)someBrush for window procedure, or return (INT_PTR)someBrush for dialog box ).

Your call to SetBkColor sets the color of text background, which is different from control's background color. That is why we call SetBkMode with TRANSPARENT parameter, to "say" that we want text background to match control's background.

In your case I have used stock brush, because you do not need to keep track of it, nor do you need to delete it after it is not needed anymore.

Still, there might be cases when you will want some other color. In that case here is what you will have to do:

  • Create global HBRUSH variable or static HBRUSH variable in your window/dialog procedure.
  • Initialize this variable in response to WM_CREATE if in window procedure. If in dialog procedure initialize the brush in WM_INITDIALOG. Something like someBrush = CreateSolidBrush( RGB( 255, 0, 255 ) ); See documentation for more info and examples.
  • return this brush, like I showed you in example above ( return (LRESULT)someBrush for window procedure, or return (INT_PTR)someBrush for dialog box ).
  • Delete the brush when no longer needed. This is usually done in WM_DESTROY with DeleteObject(someBrush); call.

I strongly advise you to do the deletion in response to WM_DESTROY instead of WM_CLOSE because this is the message your window will always receive, while WM_CLOSE can sometimes be skipped ( search the Internet to find examples for this scenario ).

Hope this helps, if you have further questions leave a comment and I will try to help. Best regards.

Alecalecia answered 2/1, 2015 at 1:42 Comment(3)
Quote from MSDN: "It is not necessary (but it is not harmful) to delete stock objects by calling DeleteObject".Wyn
How are you getting hdc?Bamboo
@Bamboo It is usually a global or static variable as explained in the answer.Alecalecia

© 2022 - 2024 — McMap. All rights reserved.