i build a class for create a static control(label). and i't cool. but why the SetTextColor() and SetBkColor() are ignored?

case WM_PAINT:
{

    PAINTSTRUCT  ps;
    HDC hdc = BeginPaint(inst->hwnd, &ps);
    // TODO: Add any drawing code here...
    SetBkColor(hdc, RGB(0,255,0));
    SetBkMode(hdc,TRANSPARENT);
    SetWindowText(inst->hwnd,"hello");
    EndPaint(inst->hwnd, &ps);
}

the inst is the class(label) pointer instance.
by some reason is ignored and i don't understand why :(
can anyone dvice me, please?

Recommended Answers

All 25 Replies

You need to instantiate a public or static brush so that the colors don't disappear as soon as that function ends.

Happy a new year!!!
can you show me please?
anotherthing: why i can't build a function(inside the class) for change it directly?

i even try these:

case WM_PAINT:
{

    PAINTSTRUCT  ps;
    HDC hdc = BeginPaint(inst->hwnd, &ps);
    static COLORREF backcolor= RGB(0,255,0);
    // TODO: Add any drawing code here...
    SetBkColor(hdc,backcolor);
    SetBkMode(hdc,TRANSPARENT);
    SetWindowText(inst->hwnd,"hello");
    EndPaint(inst->hwnd, &ps);
}
    break;

or the hwnd or even the hdc aren't correct or i don't know :(

Note: I'm working up an example of your question.

or the hwnd or even the hdc aren't correct

that is the case one of the parameters to WinProc() is the HWND of the window that is to be processed. Not a good idea to keep track of it in your own class as it may change every time WinProc() is called. All controls are also considered windows so that will each have their own unique HWND value and WinProc() is called to handle them.

why i can't build a function(inside the class) for change it directly?

What function do you mean? WinProc() can be a static method of a class or just a global function, it must be a global function with that name, just like main() is not part of any class.

sorry... realy.. i continue confuse :(
my problem isn't use your code, the problem is the code that don't do the job :(

heres the Label.h

#include <windows.h>
#include <string>
#include <functional>
#define event(eventname, ... ) std::function<void(__VA_ARGS__ )> eventname

using namespace std;

const char *labelpropname = "Cambalinho";
const char *labelclassprop = "classaddr";

enum MouseButtons
{
    None=-1,
    Left=0,
    Right=1,
    Middle=2,
    X1=3,
    X2=4
};

struct Position
{
    int X;
    int Y;
};

struct Size
{
    int Width;
    int Height;
};

class label
{
private:
    HWND hwnd;
    WNDCLASS wc;
    void TrackMouse(HWND hwnd)
    {
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_HOVER | TME_LEAVE; //Type of events to track & trigger.
        tme.dwHoverTime = 5000; //How long the mouse has to be in the window to trigger a hover event.
        tme.hwndTrack = hwnd;
        TrackMouseEvent(&tme);
    }

    static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        WNDPROC oldproc = (WNDPROC)GetProp(GetParent(hwnd), labelpropname);
        label *inst = (label*)GetProp(GetParent(hwnd), labelclassprop);

        if (oldproc == NULL || inst == NULL)
            MessageBox(NULL, "null", "null", MB_OK);

        static bool TrackingMouse = false;
        static bool WindowStopMoving = NULL;
        static bool WindowStopResize = NULL;
        static const UINT_PTR MouseStopTimerID = 1;
        static HBRUSH hBrush = CreateSolidBrush(RGB(230,230,230));

        switch(msg)
        {

            case WM_CREATE:
            {
                static int xPos = (int)(short) LOWORD(lParam);
                static int yPos = (int)(short) HIWORD(lParam);
                inst->Create(xPos,yPos);
            }
            break;

case WM_PAINT:
{
    HBRUSH pForeground =(HBRUSH) RGB(0,255,0);
HBRUSH pBackground =(HBRUSH) RGB(255,0,0);

    PAINTSTRUCT ps;
HDC hdc = BeginPaint(inst->hwnd, &ps);
static COLORREF backcolor=(COLORREF) pForeground;
// TODO: Add any drawing code here...
SetBkColor(hdc,backcolor);
SetBkMode(hdc,TRANSPARENT);
SetWindowText(inst->hwnd,"hello");
EndPaint(inst->hwnd, &ps);
}
    break;

            case WM_MOVE:
            {
                static int xPos = (int)(short) LOWORD(lParam);
                static int yPos = (int)(short) HIWORD(lParam);
                inst->Move(xPos,yPos);
                WindowStopMoving=false;
                WindowStopResize=true;
            }
            break;
            case WM_SIZE :
            {
                WindowStopResize=false;
                WindowStopMoving=true;
            }
            break;
            case WM_EXITSIZEMOVE:
            {
                if(WindowStopResize==false)
                {
                    WindowStopResize=true;
                    inst->NotResize();
                }
                else if (WindowStopMoving==false)
                {
                    WindowStopMoving=true;
                    inst->Stop();
                }
            }
            break;
            case WM_NCHITTEST:
                return DefWindowProc(hwnd, msg, wParam, lParam);

            case WM_LBUTTONDOWN:
            case WM_RBUTTONDOWN:
            case WM_MBUTTONDOWN:
            case WM_XBUTTONDOWN:
            {
                SetFocus(inst->hwnd);
                static int xPos = (int)(short) LOWORD(lParam);
                static int yPos = (int)(short) HIWORD(lParam);
                bool blControl = ((wParam & MK_CONTROL) == MK_CONTROL);
                bool blshift = ((wParam & MK_SHIFT) == MK_SHIFT);
                MouseButtons MBButtons;
                if((wParam & MK_LBUTTON)!= false)
                    MBButtons=Left;
                else if (wParam & MK_RBUTTON)
                    MBButtons=Right;
                else if (wParam & MK_MBUTTON)
                    MBButtons=Middle;
                else if (wParam & MK_XBUTTON1)
                    MBButtons=X1;
                else if (wParam & MK_XBUTTON2)
                    MBButtons=X2;
                else
                    MBButtons=None;
                inst->MouseDown(MBButtons,blControl,blshift,xPos,yPos);
            }
            break;
            case WM_LBUTTONUP:
            case WM_RBUTTONUP:
            case WM_MBUTTONUP:
            case WM_XBUTTONUP:
            {
                SetFocus(inst->hwnd);
                static int xPos = (int)(short) LOWORD(lParam);
                static int yPos = (int)(short) HIWORD(lParam);
                bool blControl = ((wParam & MK_CONTROL) == MK_CONTROL);
                bool blshift = ((wParam & MK_SHIFT) == MK_SHIFT);
                MouseButtons MBButtons;
                if (msg == WM_LBUTTONUP)
                    MBButtons=Left;
                else if (msg == WM_RBUTTONUP)
                    MBButtons=Right;
                else if (msg == WM_MBUTTONUP)
                    MBButtons=Middle;
                else if (msg == WM_XBUTTONUP)
                {
                    if (wParam & MK_XBUTTON1)
                        MBButtons=X1;
                    else if (wParam & MK_XBUTTON2)
                        MBButtons=X2;
                }
                else
                    MBButtons=None;
                inst->MouseUp(MBButtons,blControl,blshift,xPos,yPos);
            }
            break;

            case WM_MOUSELEAVE :
            {
                TrackingMouse = false;
                inst->MouseLeave();
            }
            break;
            case WM_MOUSEMOVE:
            {
                if (!TrackingMouse)
                {
                    inst->TrackMouse(hwnd);
                    TrackingMouse = true;
                    inst->MouseEnter();
                }
                static int xPos = (int)(short) LOWORD(lParam);
                static int yPos = (int)(short) HIWORD(lParam);
                static bool blControl = ((wParam & MK_CONTROL) == MK_CONTROL);
                static bool blshift = ((wParam & MK_SHIFT) == MK_SHIFT);
                static MouseButtons MBButtons;
                if((wParam & MK_LBUTTON)!= false)
                    MBButtons=Left;
                else if ((wParam & MK_RBUTTON)!= false)
                    MBButtons=Right;
                else if ((wParam & MK_MBUTTON)!= false)
                    MBButtons=Middle;
                else if ((wParam & MK_XBUTTON1)!= false)
                    MBButtons=X1;
                else if ((wParam & MK_XBUTTON2)!= false)
                    MBButtons=X2;
                else
                    MBButtons=None;

                inst->MouseMove(MBButtons,blControl,blshift,xPos,yPos);
                KillTimer(hwnd, MouseStopTimerID);
                SetTimer(hwnd, MouseStopTimerID, 500, NULL);
            }
            break;
            case WM_MOUSEHOVER:
            {
                inst->MouseHover();
            }
            break;
            case WM_TIMER:
            switch(wParam)
            {
                case MouseStopTimerID:
                {
                    KillTimer(hwnd, MouseStopTimerID);
                    inst->MouseStoped();
                }
            }
            break;
            case WM_KEYUP:
                inst->KeyUp(lParam,wParam);
            break;
            case WM_KEYDOWN:
                inst->KeyDown(lParam,wParam);
            break;

            default:
            break;
        }

        return oldproc ? CallWindowProc(oldproc, hwnd, msg, wParam, lParam) : DefWindowProc(hwnd, msg, wParam, lParam);
    }

public:

    //is these 2 lines ok?
    //see the #define on top
    event(NotResize)=[](){;};
    event(Stop)=[](){;};
    event(MouseEnter)=[](){;};
    event(MouseLeave)=[](){;};
    event(Create,(int x, int y))=[](int x, int y){;};
    event(Move,(int x, int y))=[](int x, int y){;};
    event(MouseDown,(MouseButtons Button,bool control, bool shift, int x, int y))=[](int Button, bool alt, bool shift,int x, int y){;};
    event(MouseUp,(MouseButtons Button,bool control, bool shift, int x, int y))=[](int Button, bool alt, bool shift,int x, int y){;};
    event(MouseMove,(MouseButtons Button,bool control, bool shift, int x, int y))=[](int Button, bool alt, bool shift,int x, int y){;};
    event(MouseStoped)=[](){;};
    event(MouseHover)=[](){;};
    event(MouseClick,(MouseButtons Button,bool control, bool shift, int x, int y))=[](int Button, bool alt, bool shift,int x, int y){;};
    event(MouseDoubleClick,(MouseButtons Button,bool control, bool shift, int x, int y))=[](int Button, bool alt, bool shift,int x, int y){;};
    event(MouseWhell,(int Whell, MouseButtons Button,bool control, bool shift, int x, int y))=[](int Whell, int Button, bool alt, bool shift,int x, int y){;};
    event(KeyDown,(int repeat,int Key))=[](int repeat,int Key){;};
    event(KeyUp,(int repeat,int Key))=[](int repeat,int Key){;};

    ~label()
    {
        DestroyWindow(hwnd);
        hwnd = 0;
    }
    label()
    {
        ;
    }

    void setparent(HWND parent)
    {

        HINSTANCE mod = (HINSTANCE)GetModuleHandle(NULL);

        ZeroMemory(&wc, sizeof(WNDCLASS));
        GetClassInfo(mod, "STATIC", &wc);

        wc.hInstance = mod;
        wc.lpszClassName = "CSTATIC";
        wc.hbrBackground =  (HBRUSH)COLOR_WINDOW;

        // store the old WNDPROC of the EDIT window class
        SetProp(parent, labelpropname, (HANDLE)wc.lpfnWndProc);
        SetProp(parent, labelclassprop, (HANDLE)this);

        // replace it with local WNDPROC
        wc.lpfnWndProc = WndProc;

        // register the new window class, "ShEdit"
        if (!RegisterClass(&wc))
            MessageBox(NULL, "error in register", "error", MB_OK);

        hwnd = CreateWindowEx(
            WS_EX_LEFT| WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
            "CSTATIC",
            "label",
            SS_LEFT|WS_CHILD|WS_VISIBLE,
            0, 0, 50, 20,
            parent,
            NULL,
            mod,
            NULL);
        if (hwnd == NULL)
            MessageBox(NULL, "error in create", "error", MB_OK);
    }

    COORD GetSize()
    {
        RECT LabelSize;
        GetWindowRect(hwnd,&LabelSize);
        COORD crdSize = {LabelSize.right-LabelSize.left,LabelSize.bottom-LabelSize.top};
        return crdSize;
    }

    void SetText(string text)
    {
        char* chrText = (char*)text.c_str();
        SetWindowText(hwnd, chrText);
    }

    void SetColor(COLORREF color)
    {
        SetBkColor(GetDC(hwnd),color);
        SetTextColor(GetDC(hwnd),color);
    }

    string GetText()
    {
        char lbltext[256];
        GetWindowText(hwnd,lbltext,256);
        string strtext=lbltext;
        return strtext;
    }

    HWND GetHWND()
    {
        return hwnd;
    }
};

and heres the main.cpp:

#include <windows.h>
#include "Label.h"

using namespace std;



/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[] = "CodeBlocksWindowsApp";

//creating the window
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE, LPSTR lpszArgument, int nCmdShow)
{
HWND hwnd;               /* This is the handle for our window */
MSG messages;            /* Here messages to the application are saved */
WNDCLASSEX wincl;        /* Data structure for the windowclass */

//  DeleteFile(debugname);

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Code::Blocks Template Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);
    UpdateWindow(hwnd);
    label label1;


    label1.Stop=[&label1]()
    {
        label1.SetText("stop");

    };

    label1.Move=[&label1](int x, int y){;};
    {
        label1.SetText("move");

    };
    label1.setparent(hwnd);
    label1.SetColor(RGB(0,255,0));
    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

    switch (message)                  /* handle the messages */
    {
        case WM_CHAR:

            break;

        case WM_LBUTTONDOWN:

            break;

        case WM_MOUSEMOVE:

            break;


        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;

        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

just do me a favor. try execute the code and see what happens :(

From everthing I read the color of the text in window titlebar can't be changed without using SetSysColors(). There is an example program at the end of that link, but you mighgt want to google around for other examples.

sorry??? the SetWindowText() it's the static capion, in these case

if i use SetSysColors() i can't tell it the hwnd or hdc.
sorry, we are 'in same page'?
my class creates the STATIC control. with SetWindowText() i change it's caption(not title bar window). now i need change the backcolor and text color of the STATIC caption

sorry, we are 'in same page'?

Probably not. When I run your original code snippet it put "Hello" in the window's title bar. I'll help work on it after awhile, but not promising any useful results.

ok... thanks
remember the class is in Label.h and the rest is in main.cpp.
i had share the entire code in post 6.

Sorry, I don't think I can help you -- your code has a lot of constructs that are probably from c++11 -- I haven't studied that.

Example: event(NotResize) = [](){; }; I have no clue what that's doing. I know event is a macro, but the rest of that line looks like greek to me.

forget that lines.. and tell me what i realy need to do for change the colors

this changes the colors, but the text is in the center of the window. I don't know if that is where the control is located or not. I made the background color yellow so that I could see that it is doing something. You will probably have to change the coordinates of SetRec() to something else so that it's within the boundries of your static control.

        case WM_PAINT:
        {

                         PAINTSTRUCT ps;
                         HDC hdc = BeginPaint(inst->hwnd, &ps);
                         RECT textRect;
                         SetBkColor(hdc, RGB(233, 189, 174));
                         SetRect(&textRect, 10, 210, 200, 200);
                         DrawText(hdc, TEXT("Hello"), -1, &textRect, DT_CENTER | DT_NOCLIP);
                         EndPaint(inst->hwnd, &ps);
        }

i only have 1 question: these is realyv drawed in the STATIC control or the window?
why the question? because the text is drawed out of the static position and size

That's why I said you have to change the coordinates of SetRect() so that the pixel location is within the coordinates of the static control. You might want to study this about mapping modes, unless you have already done that.

@AncientDragon, that event greek looking code is a lambda. It's just a function that will be run when an event occurs.

@OP.. WIN32/WINAPI code others are posting would be correct if they took into consideration that Labels (the control you want to paint) is a static control (no insult to them as they taught me all that I know). Well AFAIK, labels do not send WM_PAINT. Labels send the WM_CTLCOLORSTATIC message and that is why your WM_PAINT is being ignored.

case WM_PAINT:
        {
            hdc = BeginPaint(window, &PS);
            //Paint whatever else here.
            EndPaint(window, &PS);
            break;
        }

        case WM_ERASEBKGND: //Erases the window's background. Usually when a window is resized.
        {
            RECT rect = {0};
            HBRUSH Brush = CreateSolidBrush(0xECE6E1); //paint using a custom brush/colour.
            SelectObject((HDC)wParam, Brush);
            GetClientRect(window, &rect);
            Rectangle((HDC)wParam, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
            DeleteObject(Brush);
            break;
        }

        case WM_CTLCOLORSTATIC:  //For painting static OR read-only/disabled controls backgrounds.
        {
            //a label is a read-only static control. This code will change the label's text color and background colour.
            if (WelcomeLabel == (HWND)lParam)
            {
                hdc = (HDC)wParam;
                SetTextColor(hdc, RGB(0, 0, 0));
                SetBkColor(hdc, 0xECE6E1);
                return (LRESULT)GetStockObject(NULL_BRUSH);
            }
            else if (HelpBox == (HWND)lParam) //edit controls are also static and "can be" read-only.
            {
                hdc = (HDC)wParam;
                SetTextColor(hdc, RGB(0, 0, 0)); //change their text colour.
                SetBkColor(hdc, 0xECE6E1);  //change the background colour.
                return (LRESULT)GetStockObject(NULL_BRUSH);
            }
            break;
        }

There is also:

WM_CTLCOLORBTN 
WM_CTLCOLOREDIT
WM_CTLCOLORLISTBOX
WM_CTLCOLORSCROLLBAR

etc..

commented: thanks +2

triumphost: i'm trying understand your code for i change it :(

@OP, all you need to look at is the WM_CTLCOLORSTATIC case. The other cases are just there to show the different messages that need to be handled when painting. I wish I could tell you it is as easy as handling WM_PAINT but I'd be lying to you then.

WM_CTRLCOLORSTATIC is used for painting static controls (such as labels) or read-only controls (such as read-only edit/textbox controls): http://msdn.microsoft.com/en-us/library/windows/desktop/bb787524(v=vs.85).aspx

wParam will have the HDC to the control that is being painted. You can use wParam in any paint functions such as SetTextColor((HDC)wParam, ...)

lParam will have the HWND of the control to be painted and this can be used to see which control the window is drawing or moving or resizing, etc..

An very quick example I whipped up:

HWND MyLabel = NULL;
HWND MyReadOnlyEdit = NULL;

LRESULT WndProc(HWND hwnd, MSG msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CREATE:
        {
            //Create some label. Aka a static control.
            MyLabel = CreateWindow("STATIC","My Label Text", WS_VISIBLE | WS_CHILD, 10, 200, 75, 35, hWnd, (HMENU)LABEL_ID, hInstance, 0);

            //Create some read-only edit control.
            MyReadOnlyEdit = CreateWindowEx("EDIT", "My Edit Text", WS_CHILD | WS_VISIBLE | ES_READONLY, 0, 0, 100, 100, hwnd, (HMENU)EDIT_ID, hInstance, 0);
        }

        case WM_CTRLCOLORSTATIC:
        {
            HWND somecontrol = (HWND)lParam; //lParam is the control's handle.

            if (somecontrol == MyLabel) //if it is our label control..
            {
                //Paint the label.

                HDC hdc = (HDC)wParam; //wParam is the HDC to our control

                SetTextColor(hdc, RGB(255, 0, 0)); //Set our label's text colour to red.
                SetBkColor(hdc, RGB(0, 0, 0));  //Set the label's background colour to black.
                //we did not create any brushes to paint the label so we:
                return (LRESULT)GetStockObject(NULL_BRUSH); //must return the brush used. We used the default brush.
            }


            if (somecontrol == MyReadOnlyEdit) //if it is our read-only edit control
            {
                //paint just like above..
            }
        }
    }
}

it's like draw my own label inside of label control, right?
(put a border, background color, text(with TextOutA() instead SetWindowText()), images and more)

but the mouse messages aren't working... why?

now i know why the code isn't working, because i'm using a Window Procedure Super Class.
the control procedure is inside of class... how can i change the code for works with my situation?

thanks for share that code.
let me ask 1 thing: what WM_PAINT have to do with mouse messages?
(why the question? because when i used the WM_PAINT, seems the mouse message aren't working)

The WM_PAINT message is sent when the window opens and when the system wants to repaint it.

You can send it by calling the UpdateWindow or RedrawWindow function.

Example:

case WM_CREATE:
    Button1 = CreateWindow(
        _T("BUTTON");
        _T("click here");
        WS_CHILD | WS_VISIBLE | WS_TABSTOP | SS_NOTIFY | SS_LEFT,
        10,
        10,
        150,
        25,
        hwnd,
        (HMENU)1,
        hInst,
        NULL;
    );
    break;
case WM_COMMAND:
    switch(LOWORD(WPARAM)) {
        case 1:
            UpdateWindow();
            break;
    }
    break;
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.