I have tried using SetTextColor but I must be doing something wrong. Here is my code:
#include <windows.h>
#include <stdio.h>
#define ID_MYBUTTON 101
#define ID_TAB 201
#define WM_CTLCOLORDLG 0x0136
LPSTR szClassName = "MyClass";
HINSTANCE hInstance;
LRESULT CALLBACK MyWndProc(HWND, UINT, WPARAM, LPARAM);
HWND hwndText[3];
FILE *fp;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
{
WNDCLASS wnd;
MSG msg;
HWND hwnd;
HWND hWndBtn1;
hInstance = hInst;
wnd.style = CS_HREDRAW | CS_VREDRAW; //we will explain this later
wnd.lpfnWndProc = MyWndProc;
wnd.cbClsExtra = 0;
wnd.cbWndExtra = 0;
wnd.hInstance = hInstance;
wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION); //default icon
wnd.hCursor = LoadCursor(NULL, IDC_ARROW); //default arrow mouse cursor
wnd.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wnd.lpszMenuName = NULL; //no menu
wnd.lpszClassName = szClassName;
if(!RegisterClass(&wnd)) //register the WNDCLASS
{
MessageBox(NULL, "This Program Requires Windows NT",
"Error", MB_OK);
return 0;
}
hwnd = CreateWindow(szClassName,
"Window Title",
WS_OVERLAPPEDWINDOW, //basic window style
CW_USEDEFAULT,
CW_USEDEFAULT, //set starting point to default value
CW_USEDEFAULT,
CW_USEDEFAULT, //set all the dimensions to default value
NULL, //no parent window
NULL, //no menu
hInstance,
NULL); //no parameters to pass
// create a text box and store the handle
hwndText[0] = CreateWindow(
TEXT("edit"), // The class name required is edit
TEXT("Enter text here"), // Default text.
WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP, // the styles
100,100, // the left and top co-ordinates
300,30, // width and height
hwnd, // parent window handle
(HMENU) ID_TAB, // the ID of your combobox
hInstance, // the instance of your application
NULL
); // extra bits you dont really need
hwndText[1] = CreateWindow(
TEXT("edit"), // The class name required is edit
TEXT("2nd field"), // Default text.
WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP | ES_PASSWORD, // the styles
100,200, // the left and top co-ordinates
300,30, // width and height
hwnd, // parent window handle
NULL, // the ID of your combobox
hInstance, // the instance of your application
NULL
); // extra bits you dont really need
SetWindowText(hwndText[0],"revised");
SetFocus(hwndText[0]);
CreateWindow(TEXT("STATIC"), TEXT("Text1:"), WS_CHILD|WS_VISIBLE, 25, 100, 55, 22, hwnd, 0, hInstance, 0);
hWndBtn1 = CreateWindow(TEXT("BUTTON"), TEXT("Update"), WS_CHILD|WS_VISIBLE, 5, 5, 55, 22, hwnd, (HMENU) ID_MYBUTTON, hInstance, 0);
HDC hdc = GetDC(hwndText[0]);
SetTextColor(hdc, RGB(255,0,0)); // red
SetBkColor(hdc, RGB(255,255,0)); // yellow
ShowWindow(hwnd, iCmdShow); //display the window on the screen
UpdateWindow(hwnd); //make sure the window is updated correctly
while(GetMessage(&msg, NULL, 0, 0)) //message loop
{
if (!IsDialogMessage(hwnd, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
char data[256];
HDC hdc;
switch(msg)
{
case WM_CTLCOLORDLG:
hdc = GetDC(hwndText[0]);
SetTextColor(hdc, RGB(255,0,0)); // red
SetBkColor(hdc, RGB(255,255,0)); // yellow
break;
case WM_CTLCOLOREDIT: // Never use this code in WM_PAINT.
hdc = GetDC(hwndText[0]);
SetTextColor(hdc, RGB(255,0,0)); // red
SetBkColor(hdc, RGB(255,255,0)); // yellow
break;
case WM_COMMAND:
if(ID_MYBUTTON == LOWORD(wParam))
{
if (BN_CLICKED==HIWORD(wParam)) {
GetWindowText(hwndText[0],data,255);
MessageBox(hwnd,data,"notice",MB_OK);
if ((fp=fopen("tom","w"))==NULL)
MessageBox(hwnd,"could not open wikiwin.txt","error",MB_OK);
fprintf(fp,"%s\n",data);
fclose(fp);
ShowWindow(hwndText[1],SW_HIDE); // hide the window
ShowWindow(hwndText[1],SW_SHOW); // show the hidden window again
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
You need to respond to the WM_CTLCOLOREDIT message....
The procedure...
// colour control
LRESULT SetColors(HDC dc,HWND win)
{ SetTextColor(dc,GetSysColor(COLOR_WINDOWTEXT));
SetBkMode(dc,OPAQUE);
SetBkColor(dc,GetSysColor(COLOR_WINDOW));
return (LRESULT)CreateSolidBrush(GetSysColor(COLOR_WINDOW)); }
and In the message handler...
case WM_CTLCOLOREDIT :
return SetColors((HDC)wparm,(HWND)lparm);
For that example:
case WM_CTLCOLOREDIT:
hdc = (HDC)wParam;
SetTextColor(hdc, RGB(255, 0, 0)); // red
SetBkColor(hdc, RGB(255, 255, 0)); // yellow
return (LRESULT)CreateSolidBrush(RGB(255, 255, 0));
That worked. Thanks. But it changed all my text boxes. How can I change just one?
Quote from: tpekar on June 24, 2011, 03:30:35 PM
That worked. Thanks. But it changed all my text boxes. How can I change just one?
You have to make it sensitive to the window handle... If you note my example function includes HWND in it's parameters and it is passed out of the switch() by the function call. Inside the function you can just do this...
// colour control
LRESULT SetColors(HDC dc,HWND win)
{ if (win != MyChangeHandle)
return 0;
SetTextColor(dc,GetSysColor(COLOR_WINDOWTEXT));
SetBkMode(dc,OPAQUE);
SetBkColor(dc,GetSysColor(COLOR_WINDOW));
return (LRESULT)CreateSolidBrush(GetSysColor(COLOR_WINDOW)); }
This, btw is why I suggested you not put code in switch() statements... it's just so much easier to alter and maintain when it's compartmentalized as function calls...
A similar question came up a short while ago. I posted a demo on that thread that shows a technique for changing the color of the text box that has the focus.
http://forum.pellesc.de/index.php?topic=3713.msg13789#msg13789 (http://forum.pellesc.de/index.php?topic=3713.msg13789#msg13789)
Quote from: DMac on June 24, 2011, 04:34:49 PM
A similar question came up a short while ago. I posted a demo on that thread that shows a technique for changing the color of the text box that has the focus.
http://forum.pellesc.de/index.php?topic=3713.msg13789#msg13789 (http://forum.pellesc.de/index.php?topic=3713.msg13789#msg13789)
Interresting... gotta try that one out. Thanks!
Thanks. I was able to get the GetFocus example to work. Sorry for my code being so messy. I am trying to learn the Windows API. I have an IBM AS/400 background. I have found the Microsoft documentation hard to follow. What I am trying to do is change a field to red if the user makes an invalid entry. However, in some cases like a state code and a zip code may disagree. One of the two is wrong. In this case I want to make both text boxes red and set the focus to the first one. Also, I am wanting to equate the escape key to clicking the red X in the upper right hand corner (to close the window).
I was able to get my program to set the color for a text box that was not the focus as follows:
case WM_CTLCOLOREDIT:
if (lParam==(long)hwndText[0] && update>0) {
hdc = (HDC)wParam;
SetTextColor(hdc, RGB(0, 0, 0)); // black
SetBkColor(hdc, RGB(255, 0, 0)); // red
return (LRESULT)CreateSolidBrush(RGB(255, 0, 0)); // red
}
case WM_COMMAND:
if(ID_MYBUTTON == LOWORD(wParam)) {
if (BN_CLICKED==HIWORD(wParam)) {
if ((fp=fopen("wikiwin.txt","w"))==NULL)
MessageBox(hwnd,"could not open wikiwin.txt","error",MB_OK);
fprintf(fp,"%s\n",data);
fclose(fp);
update=1; // this is what I want to trigger color change to text field
}
}
My problem is that the text field does not change color till I click into it or tab into it. How can I make it happen as soon as the button is clicked?
Quote from: tpekar on June 24, 2011, 07:38:12 PM
case WM_CTLCOLOREDIT:
if (lParam==(long)hwndText[0] && update>0) {
hdc = (HDC)wParam;
SetTextColor(hdc, RGB(0, 0, 0)); // black
SetBkColor(hdc, RGB(255, 0, 0)); // red
return (LRESULT)CreateSolidBrush(RGB(255, 0, 0)); // red
}
Although this is not related to your question I spotted a red flag in the above code. The function CreateSolidBrush() allocates resources that you must free when you are finished with them. You now have a memory leak that can be easily avoided by using the following handy function (borrowed from BCX the Basic to C compiler.)
static HBRUSH SetColor(HDC hdc, COLORREF TxtColr, COLORREF BkColr)
{
static HBRUSH ReUsableBrush;
DeleteObject(ReUsableBrush);
ReUsableBrush = CreateSolidBrush(BkColr);
SetTextColor(hdc, TxtColr);
SetBkColor(hdc, BkColr);
return ReUsableBrush;
}
It is implemented as follows:
case WM_CTLCOLOREDIT:
if (lParam==(long)hwndText[0] && update>0) {
hdc = (HDC)wParam;
return SetColor(hdc, 0, RGB(255, 0, 0)); //black and red
}
Quote from: DMac on June 24, 2011, 09:18:26 PM
Although this is not related to your question I spotted a red flag in the above code. The function CreateSolidBrush() allocates resources that you must free when you are finished with them.
I believe the DefWindProc() expects a brush handle and disposes of it itself when finished drawing...
That is to say when checking my code, I've never seen a memory leak because of this...
http://msdn.microsoft.com/en-us/library/bb761691 (http://msdn.microsoft.com/en-us/library/bb761691)
QuoteRemarks
If the application returns a brush that it created (for example, by using the CreateSolidBrush or CreateBrushIndirect function), the application must free the brush. If the application returns a system brush (for example, one that was retrieved by the GetStockObject or GetSysColorBrush function), the application does not need to free the brush.
Quote from: timovjl on June 25, 2011, 07:53:07 AM
http://msdn.microsoft.com/en-us/library/bb761691 (http://msdn.microsoft.com/en-us/library/bb761691)
QuoteRemarks
If the application returns a brush that it created (for example, by using the CreateSolidBrush or CreateBrushIndirect function), the application must free the brush. If the application returns a system brush (for example, one that was retrieved by the GetStockObject or GetSysColorBrush function), the application does not need to free the brush.
Thanks Timo.... I guess I've got a little updating to do... The good news is that I haven't used these messages very often, preferring to stay with the windows default colors.