api: change edit background color

i'm trying to change the background color of an edit control with api..

i'm trying this..

SetBkColor(GetDC(GetDlgItem(prefs_detail,USER_EDIT)),RGB(255,0,0));

but it doesn't seem to be working? any ideas?

i'm trying to duplicate the VCL Edit1.Color := clRed; not font properties.
gwarguitarAsked:
Who is Participating?
 
Slick812Connect With a Mentor Commented:
?? maybe this code, but it seems that the code I gave at first, has all of the methods to do an edit change color? I now use a Handle for the Edit Identifier instead of an ID, now in the  OK button click it test for the hEditC as 0 and will get the Edit handle (for red color) or set  hEditC to zero for normal color

var   {global variables}
  hBrush1: Integer;
  hEditC: Integer = 0;



function DialogProc(hWnd, Msg, wParam, lParam: Integer): Integer; stdcall;
var
i: Integer;
begin
Result := Zero {False};
case Msg of
  WM_INITDIALOG: begin
    hBrush1 := CreateSolidBrush($FF);
    end;

  WM_CLOSE:
    begin
    DeleteObject(hBrush1);
    EndDialog(hWnd, IDCANCEL);
    Result := 1 {True};
    end;

  WM_COMMAND: if LOWORD(wParam) = IDOK then
    begin
      if hEditC = 0 then
        begin
        hEditC := GetDlgItem(hWnd,USER_EDIT)
        InvalidateRect(hEditC, nil, True);;
        end  else
        begin
        i := hEditC;
        hEditC := 0;
        InvalidateRect(i, nil, True);
        end;
     
      Exit;
      end;
   // DeleteObject(hBrush1);
   // EndDialog(hWnd, IDOK);
   // Result := 1;
    end;

  WM_CTLCOLOREDIT: {pre Paint message for Edits = WM_CTLCOLOREDIT}
    if lParam = Integer(GetDlgItem(hWnd,hEditC)) then
    begin
    SetTextColor(wParam,$CFCF00);
    SetBkColor(wParam,$FF);
    Result := hBrush1;
    end;
  end;

end;




 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
 I do not think I can do less than that. . .


and the code

for i := 300 to 302 do // there are 3 Edits ID from 300 to 302
    if GetWindowTextLength(GetDlgItem(hWnd, i)) < 2 then

is whatI used to get the first edit without text
0
 
Eddie ShipmanAll-around developerCommented:
"i'm trying to duplicate the VCL Edit1.Color := clRed"

Why? What you are doing is trying to override the VCL's painting of the Edit but
it isn't working because you are not actuallu overriding it, you are painting and
then the VCL is repainting because it needs to be.

Why are you using the API to do this anyway?
0
 
gwarguitarAuthor Commented:
because i'm not using the vcl. i'm using dialogs designed in visual studio and controlling them with api messages.

i was just giving an example of the vcl, when you set that property it changes the whole control color, not just the text background.
0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
Eddie ShipmanAll-around developerCommented:
That was definately not clear in your original post.

Did you set the background mode to OPAQUE first?
0
 
gwarguitarAuthor Commented:
no, i did set it to transparent? how do you set to opaque?
0
 
gwarguitarAuthor Commented:
oh, SetBkMode...

set to opaque.. now what? seems like i need to respond to a notification, was hoping just to do this with a simple message.. :)
0
 
Slick812Commented:
hello  gwarguitar, ?? you seem to think that Device Contexts are persistant, but they are not, your code

GetDC(GetDlgItem(prefs_detail,USER_EDIT))

does not get the DC the system uses to draw an Edit, to change the system DC colors used for an Edit drawing, you will need to process the  WM_CTLCOLOREDIT  message in it's parents Window Proc, I guess it's Dialog Window Proc. .


maybe something like this -


function DialogProc(hWnd, Msg, wParam, lParam: Integer): Integer; stdcall;
begin
Result := Zero {False};
case Msg of
  WM_INITDIALOG: WhatEverCode;

  WM_CTLCOLOREDIT: if lParam = Integer(GetDlgItem(prefs_detail,USER_EDIT)) then
    {pre Paint message for Edits = WM_CTLCOLOREDIT}
    begin
    {this can set the colos used for hEdit1
     the wParam is the DC for the edit}
    SetTextColor(wParam,$0000FF);
    SetBkColor(wParam,GetSysColor(COLOR_BTNHIGHLIGHT));
    Result := GetSysColorBrush(COLOR_BTNHIGHLIGHT);
    {Result is the brush used to paint NON-Text areas,
     for your colors you will need to create your brush object of that color}
     end;
  end;

end;


for some information about API Dialogs in Delphi you might look at this web page -

http://www.angelfire.com/hi5/delphizeus/dialogs.html

ask questions if you need more information
0
 
gwarguitarAuthor Commented:
that's getting closer, i get a rangecheck error on settext color..

anyhow, i'm still confused... here's what i want to do.

i have a dialog with several edit controls, they're all default color.
when the user click "OK" if an edit control is empty (i already do the check for this...) i want it to turn red.
if they click ok and the text has been filled in, i want it to go back to default..

so it's just like visual error checking is what i want to accomplish.

raised the points on this one :)
0
 
Slick812Commented:
I really do not understand your Error, how can you get a rangeCheck error on a call for SetTextColor(wParam, $CFCF00); ?
maybe
SetTextColor(Cardinal(wParam), $CFCF00);

here is my version of Fill in the Edits, this will flash the first empty (less than 2 charaters) Edit in the Dialog with 3 edits -

var   {global variables}
  hBrush1, Flash, EditID: Integer;
  ColorID: Integer = 0;



function DialogProc(hWnd, Msg, wParam, lParam: Integer): Integer; stdcall;
var
i: Integer;
begin
Result := Zero {False};
case Msg of
  WM_INITDIALOG: begin
    hBrush1 := CreateSolidBrush($FF);
    SendMessage(hWnd, WM_SETICON, 1, LoadIcon(hInstance,'MainIcon'));
    SetDlgItemText(hWnd,300,'Fill in this Edit');
    end;

  WM_CLOSE:
    begin
    EndDialog(hWnd, IDCANCEL);
    Result := 1 {True};
    end;

  WM_TIMER: if WParam = 117 then
    begin
    if Flash > 5 then
    KillTimer(hWnd,117);
    Inc(Flash);
    if ColorID = 0 then
      begin
      SetDlgItemText(hWnd,201,'ALL EDITS MUST BE FILLED');
      ColorID := EditID;
      end else
      begin
      SetDlgItemText(hWnd,201,'all edits must be filled');
      ColorID := 0;
      end;
    InvalidateRect(GetDlgItem(hWnd,EditID), nil, True);
    end;

  WM_COMMAND: if LOWORD(wParam) = IDOK then
    begin
    for i := 300 to 302 do
    if GetWindowTextLength(GetDlgItem(hWnd, i)) < 2 then
      begin
      SetTimer(hWnd, 117,700, nil);
      EditID := i;
      ColorID := i;
      Flash := 0;
      InvalidateRect(GetDlgItem(hWnd,EditID), nil, True);
      SetDlgItemText(hWnd,201,'ALL EDITS MUST BE FILLED');
      Exit;
      end;
    DeleteObject(hBrush1);
    EndDialog(hWnd, IDOK);
    Result := 1;
    end;

  WM_CTLCOLOREDIT: {pre Paint message for Edits = WM_CTLCOLOREDIT}
    if lParam = Integer(GetDlgItem(hWnd,ColorID)) then
    begin
    SetTextColor(wParam,$CFCF00);
    SetBkColor(wParam,$FF);
    Result := hBrush1;
    end;
  end;

end;


 = = = = = = = = = = = = = = = = = = = = = = = = = = =

here is the EditDlg1.rc  resource creation code for the Dialog


EditDlg DIALOG  12, 10, 116, 80
     STYLE WS_POPUP | WS_DLGFRAME | WS_CAPTION | WS_SYSMENU
     CAPTION " Fill in the Edits"
     FONT 10, "MS Sans Serif"
     {
     CTEXT "This is an EDIT Dialog"     200, 10, 1, 102, 10
     LTEXT "Please Fill ALL Edits"  201, 5, 12, 196, 10
     EDITTEXT      300, 4, 23, 108, 10
     EDITTEXT      301, 4, 34, 108, 10
     EDITTEXT      302, 4, 45, 108, 10
     DEFPUSHBUTTON "&OK"   IDOK, 43, 62, 32, 12, WS_GROUP
     }


= = = = = = = = = = = = = = = = = = = = = = = = = = =

and the call to shoe the dialog

if DialogBox(hInstance, 'EditDlg', hForm1, @DialogProc) = IDOK then

 = = = = = = = = = = = = = = = = = = =  = =

this code works for me
0
 
Slick812Commented:
forgot the deleteObject, , change the close code to -

  WM_CLOSE:
    begin
    DeleteObject(hBrush1);
    EndDialog(hWnd, IDCANCEL);
    Result := 1 {True};
    end;
0
 
gwarguitarAuthor Commented:
hmm... still not quite working...

sorry to be a pain in the ass :)

could you maybe write a function like this...

procedure ChangeControlColor(hDlg : hwnd; nIDDlgItem : Integer, color: cardinal);
begin
 change the color of GetDlgItem(hdlg,nIDDlgItem) to color
end;

severe psuedo code :)

increased points again since i suck. hehe
0
 
Slick812Commented:
no I can not, there is no API to just change the color of Edit controls, that I know of, sorry. . .
many (most) standard API system controls do not have a "Color" attribute, I wonder why you think they would?
0
 
Slick812Commented:
let me state that in API, if you want to change an Edits color in the system draw you will need to handle the WM_CTLCOLOREDIT message in it's parent's Window Proc as in the code below


WM_CTLCOLOREDIT: {pre Paint message for Edits = WM_CTLCOLOREDIT}
    if lParam = Integer(GetDlgItem(hWnd,ColorID)) then
    begin
    SetTextColor(wParam,$CFCF00);
    SetBkColor(wParam,$FF);
    Result := hBrush1;
    end;

the background color is the handle of a Brush that you send back in the Result of the Window Proc, if you want to change the text color then you do it with the wParam, which is the hDC used to draw the Edit

I have not seen any methods as you want, to just call a function to change a color for an edit
0
 
gwarguitarAuthor Commented:
yeah, i know there is no color property, but you're clearly able to write to code to do it :)

i was just saying, using your previous code, just making it more of a procedure, without the timer and stuff.
0
 
Slick812Commented:
if you have more than One Edit, then you will need to come up with your own code for the -

 if lParam = Integer(GetDlgItem(hWnd,ColorID)) then

I use the ColorID to identify the Edit to change to color for, I set the ColorID in the button click message of

 if LOWORD(wParam) = IDOK then

with the for loop of

 for i := 300 to 302 do // there are 3 Edits ID from 300 to 302
    if GetWindowTextLength(GetDlgItem(hWnd, i)) < 2 then
      begin
     // SetTimer(hWnd, 117,700, nil); leave out timer
     // EditID := i;
      ColorID := i; set the ColorID to your Edit ID number
      //Flash := 0;
      InvalidateRect(GetDlgItem(hWnd,ColorID), nil, True); // must redraw the edit to show change
      //SetDlgItemText(hWnd,201,'ALL EDITS MUST BE FILLED');
      Exit;
      end

 = = = = = = =

maybe less is more easy


if LOWORD(wParam) = IDOK then
  begin
   ColorID := 301; set the ColorID to your Edit ID number
   InvalidateRect(GetDlgItem(hWnd,ColorID), nil, True); // must redraw the edit to show change
    Exit;
    end;

but this is a one time set, it does not go back
0
 
gwarguitarAuthor Commented:
yeah i have about 8 edit's that need the ability to change color :)

thanks Slick, i'll try the lesser code and see what i can do there!
0
 
Slick812Commented:
I really wonder, why are you using an API Dialog at all, if you are not familar with using one? Wouldn't a TForm be easier for you?
0
 
gwarguitarAuthor Commented:
i'm familiar with api dialogs, just not the WM_CTLCOLOREDIT message and changing colors and such.
0
 
Slick812Commented:
I did not get this line correct -

 if lParam = Integer(GetDlgItem(hWnd,hEditC)) then

should be

 if lParam = hEditC then
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.