Thread: Changing bkgrnd color of Child windows

  1. #1
    Registered User cMADsc's Avatar
    Join Date
    Jun 2002
    Posts
    18

    Unhappy Changing bkgrnd color of Child windows

    I have made a little connect 4 game. the board is 7 x 6 which i just used 42childwindows in a single array. the problem is that i cannot seem to set the initial color of the child windows to yellow. When a spot is click i have no problem redrawing the child window with the background yellow and the coin colored red or yellow. Any suggestion is appreciated. Thanks in advance.

    Things i have tried:
    (inside child window procedure)

    WM_CREATE:
    SetClassLong(hwndChild, GCL_HBRBACKGROUND, (LONG) CreateSolidBrush(RGB(255,255,0));
    return 0;


    also i tried creating a yellow brush and setting the child's window class background to the yellow brush;


    WNDCLASS wc;
    .
    .
    .
    wc.hbrgrnd = (HBRUSH) yellow_brush;
    There are those who say they can, and there are those who acutally do.

    ...you can not learn programming in a class, you have to learn it on your own

  2. #2
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    perhaps you need to invalidate the window's rect? Just a thought. Otherwise I think I need to see some code
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  3. #3
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    There are a bunch of messages for colouring controls WM_CTL* eg WM_CTLCOLOREDIT (edits), WM_CTLCOLORSTATIC (statics and read-only edits).

    return a brush handle from these functions and windows will use it to colour the background of the control (except buttons). Remember to DeletObject on the brush handle when you are done with it.

    The question has come up a number of times before so a quick search on this board (windows) for eg. WM_CTLCOLORSTATIC will give you more information.

    Hope that helps.

  4. #4
    Registered User cMADsc's Avatar
    Join Date
    Jun 2002
    Posts
    18
    #define PLAYER 1
    #define COM 2
    #define VACANT 3
    //the board is 7 x 6, 42 total spots

    //a structure is used to keep count which positions on the
    //board are marked
    struct tagboard
    {
    int pieces;
    int type;
    } board[42];



    //draws red coin
    void PlayerMove(HWND hwnd,HDC hdc)
    {

    RECT rect;

    GetClientRect(hwnd, &rect);
    FillRect(hdc, &rect,CreateSolidBrush(RGB(255,255,0)));
    SelectObject(hdc, CreateSolidBrush(RGB(255,0,0)));
    Ellipse(hdc,3, 9, 51, 55);
    DeleteObject((hdc, GetStockObject(WHITE_BRUSH)));
    }
    //draws black coin
    void ComputerMove(HWND hwnd,HDC hdc)
    {

    RECT rect;

    GetClientRect(hwnd, &rect);
    FillRect(hdc, &rect,CreateSolidBrush(RGB(255,255,0)));
    SelectObject(hdc, CreateSolidBrush(RGB(0,0,0)));
    Ellipse(hdc,3, 9, 51, 55);
    DeleteObject((hdc, GetStockObject(WHITE_BRUSH)));
    }

    //empty spot draws a white coin
    void VacantMove(HWND hwnd,HDC hdc)
    {

    RECT rect;

    GetClientRect(hwnd, &rect);
    FillRect(hdc, &rect,CreateSolidBrush(RGB(255,255,0)));
    SelectObject(hdc, CreateSolidBrush(RGB(255,255,255)));
    Ellipse(hdc,3, 9, 51, 55);
    DeleteObject((hdc, GetStockObject(WHITE_BRUSH)));

    }

    void SetMove(HWND hwnd, int index)
    {

    HWND hwndParent, hwndChild;

    hwndParent = GetParent(hwnd);
    board[index].type = PLAYER;
    hwndChild = GetDlgItem(hwndParent, index);
    SetWindowLong(hwndChild, 0, 1);
    InvalidateRect(hwndChild, NULL, TRUE);

    }

    LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    static HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;
    int childID;


    switch(message)
    {
    case WM_CREATE:
    SetWindowLong(hwnd, 0, 0);
    // VacantMove(hwnd, hdc);
    // InvalidateRect(hwnd, NULL, TRUE);
    // childID = GetDlgCtrlID(hwnd);
    return 0;

    case WM_LBUTTONDOWN:
    SetPlayerMove(hwnd);
    InvalidateRect(hwnd, NULL, TRUE);
    return 0;

    case WM_PAINT:
    hdc = BeginPaint(hwnd,&ps);
    GetClientRect(hwnd, &rect);
    Rectangle(hdc,0, 0, rect.right, rect.bottom);

    if(GetWindowLong(hwnd,0))
    {
    childID = GetDlgCtrlID(hwnd);

    if(board[childID].type == VACANT)
    VacantMove(hwnd,hdc);
    else
    if(board[childID].type == PLAYER)
    PlayerMove(hwnd, hdc);
    else
    ComputerMove(hwnd, hdc);

    }//end of IF

    EndPaint(hwnd, &ps);
    return 0;

    }
    return DefWindowProc(hwnd, message, wParam, lParam);
    }
    There are those who say they can, and there are those who acutally do.

    ...you can not learn programming in a class, you have to learn it on your own

  5. #5
    Registered User cMADsc's Avatar
    Join Date
    Jun 2002
    Posts
    18
    i am pretty familar with WM_CTLCOLORSTATIC, thanks to my trusted copy of Petzolds book. Although, I have not created any static windows. I will search though.
    There are those who say they can, and there are those who acutally do.

    ...you can not learn programming in a class, you have to learn it on your own

  6. #6
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    >>i am pretty familar with WM_CTLCOLORSTATIC<<

    I provided that as an example, but since you are familiar with it and have Petzolds then you should have no problem whatsoever colouring your controls.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  7. #7
    Registered User cMADsc's Avatar
    Join Date
    Jun 2002
    Posts
    18
    /**********************************************
    the header FILE 1/2
    *********************************************/

    #include<windows.h>


    #define ROW 7
    #define COLUMNS 6
    #define PLAYER 1
    #define COM 2
    #define VACANT 3



    TCHAR szChildClass[] = TEXT("Child_Conn4");
    TCHAR szAppName[] = TEXT("Conn4");



    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM);



    void PlayerMove(HWND hwnd, HDC hdc);
    void SetPlayerMove(HWND hwnd);
    void ComputerMove(HWND hwnd,HDC hdc);
    void VacantMove(HWND hwnd,HDC hdc);
    //enum status {PLAYER=1, COM=2, VACANT=3};
    void SetMove(HWND hwnd, int );

    struct tagboard
    {
    int pieces;
    int type;
    } board[42];

    /**********************************************
    A NEW FILE 2/2
    *********************************************/
    #include<windows.h>
    #include "Conn4.h"

    int cxScreen = GetSystemMetrics(SM_CXFULLSCREEN);
    int cyScreen = GetSystemMetrics(SM_CYFULLSCREEN);



    void PlayerMove(HWND hwnd,HDC hdc)
    {

    RECT rect;

    GetClientRect(hwnd, &rect);
    FillRect(hdc, &rect,CreateSolidBrush(RGB(255,255,0)));
    SelectObject(hdc, CreateSolidBrush(RGB(255,0,0)));
    Ellipse(hdc,3, 9, 51, 55);
    DeleteObject((hdc, GetStockObject(WHITE_BRUSH)));
    }

    void ComputerMove(HWND hwnd,HDC hdc)
    {

    RECT rect;

    GetClientRect(hwnd, &rect);
    FillRect(hdc, &rect,CreateSolidBrush(RGB(255,255,0)));
    SelectObject(hdc, CreateSolidBrush(RGB(0,0,0)));
    Ellipse(hdc,3, 9, 51, 55);
    DeleteObject((hdc, GetStockObject(WHITE_BRUSH)));
    }


    void VacantMove(HWND hwnd,HDC hdc)
    {

    RECT rect;

    GetClientRect(hwnd, &rect);
    FillRect(hdc, &rect,CreateSolidBrush(RGB(255,255,0)));
    SelectObject(hdc, CreateSolidBrush(RGB(255,255,255)));
    Ellipse(hdc,3, 9, 51, 55);
    DeleteObject((hdc, GetStockObject(WHITE_BRUSH)));

    }

    void SetMove(HWND hwnd, int index)
    {

    HWND hwndParent, hwndChild;

    hwndParent = GetParent(hwnd);//get handle to the parent
    board[index].type = PLAYER;//index equals the childID to set
    hwndChild = GetDlgItem(hwndParent, index);//get handle to the child
    SetWindowLong(hwndChild, 0, 1);//set the extra space set in the window
    InvalidateRect(hwndChild, NULL, TRUE);//redraw the child window

    }
    void SetPlayerMove(HWND hwnd)
    {
    int childID;

    static int col0=5, col1=11,col2=17,col3=23,col4=29,col5=35,col6=41;
    //col0-col6 are indexes for each column used to help determine were the
    //next piece will be placed

    childID = GetDlgCtrlID(hwnd);
    //the childID will be used to decide which column is next to fill

    switch(childID)
    {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    {
    SetMove(hwnd,col0);
    col0 = (col0 >0)? col0-1 : 0;
    break;
    }
    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
    case 11:
    {
    SetMove(hwnd,col1);
    col1 = (col1 >6)? col1-1 : 6;

    break;
    }

    case 12:
    case 13:
    case 14:
    case 15:
    case 16:
    case 17:
    {
    SetMove(hwnd,col2);
    col2 = (col2 >12)? col2-1 : 12;
    break;

    }
    case 18:
    case 19:
    case 20:
    case 21:
    case 22:
    case 23:
    {
    SetMove(hwnd,col3);
    col3 = (col3 >18)? col3-1 : 18;
    break;
    }

    case 24:
    case 25:
    case 26:
    case 27:
    case 28:
    case 29:
    {
    SetMove(hwnd,col4);
    col4 = (col4 >24)? col4-1 : 24;
    break;
    }

    case 30:
    case 31:
    case 32:
    case 33:
    case 34:
    case 35:
    {
    SetMove(hwnd,col5);
    col5 = (col5 >30)? col5-1 : 30;
    break;
    }

    case 36:
    case 37:
    case 38:
    case 39:
    case 40:
    case 41:
    {
    SetMove(hwnd,col6);
    col6 = (col6 >36)? col6-1 : 36;
    break;
    }
    }//end of SWITCH*/

    }
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {

    // static TCHAR szAppName[] = TEXT("Conn4");
    HWND hwnd;
    MSG msg;
    WNDCLASS wc;

    wc.style = CS_HREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = szAppName;


    if(!RegisterClass(&wc))
    {
    MessageBox(NULL, TEXT("Register Class Error!"), szAppName, MB_ICONERROR);
    return 0;
    }

    wc.lpfnWndProc = ChildWndProc;
    wc.cbWndExtra = sizeof(long);
    wc.hIcon = NULL;

    wc.lpszClassName = szChildClass;

    if(!RegisterClass(&wc))
    {
    MessageBox(NULL, TEXT("Register Child Class Error!"), szAppName, MB_ICONERROR);
    return 0;
    }


    hwnd = CreateWindow(szAppName,TEXT("Connect Four"), WS_OVERLAPPED | WS_SYSMENU
    | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
    cxScreen/3, cyScreen/3, 380, 400, NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    while(GetMessage(&msg, NULL, 0, 0))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    return msg.wParam;
    }


    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    static HWND hwndChild[42];
    int cxBlock, cyBlock,x,y,z=0;


    switch(message)
    {
    case WM_CREATE:
    for(x=0; x<42; x++)
    hwndChild[x] =CreateWindow(szChildClass,NULL, WS_CHILDWINDOW | WS_VISIBLE,
    0,0,0,0,hwnd,(HMENU) x,(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),NULL);


    return 0;

    case WM_SIZE:
    cxBlock = LOWORD(lParam) / ROW;
    cyBlock = HIWORD(lParam) / COLUMNS;

    for(x=0; x< ROW; x++)
    for(y=0; y<COLUMNS; y++)
    { MoveWindow(hwndChild[z],x * cxBlock, y*cyBlock, cxBlock, cyBlock,TRUE);
    z++;
    }
    return 0;

    case WM_DESTROY:
    PostQuitMessage(0);
    return 0;
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
    }

    LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    static HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;
    int childID;


    switch(message)
    {
    case WM_CREATE:
    SetWindowLong(hwnd, 0, 0);
    // VacantMove(hwnd, hdc);
    // InvalidateRect(hwnd, NULL, TRUE);
    // childID = GetDlgCtrlID(hwnd);
    return 0;

    case WM_LBUTTONDOWN:
    SetPlayerMove(hwnd);
    InvalidateRect(hwnd, NULL, TRUE);
    return 0;

    case WM_PAINT:
    hdc = BeginPaint(hwnd,&ps);
    GetClientRect(hwnd, &rect);
    Rectangle(hdc,0, 0, rect.right, rect.bottom);

    if(GetWindowLong(hwnd,0))
    {
    childID = GetDlgCtrlID(hwnd);

    if(board[childID].type == VACANT)
    VacantMove(hwnd,hdc);
    else
    if(board[childID].type == PLAYER)
    PlayerMove(hwnd, hdc);
    else
    ComputerMove(hwnd, hdc);




    }//end of IF

    EndPaint(hwnd, &ps);
    return 0;

    }
    return DefWindowProc(hwnd, message, wParam, lParam);
    }
    Last edited by cMADsc; 09-09-2002 at 12:16 PM.
    There are those who say they can, and there are those who acutally do.

    ...you can not learn programming in a class, you have to learn it on your own

  8. #8
    Registered User cMADsc's Avatar
    Join Date
    Jun 2002
    Posts
    18

    Wink

    ok that is the whole code, just copy and paste and u can see my premature game at work.
    There are those who say they can, and there are those who acutally do.

    ...you can not learn programming in a class, you have to learn it on your own

  9. #9
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    Perhaps you would be better just zipping up your files and attaching them - but i'll give it a go anyway.

    edit: It looks fine.
    Last edited by Ken Fitlike; 09-09-2002 at 12:21 PM.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  10. #10
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    >>FillRect(hdc, &rect, CreateSolidBrush( RGB(255,255,0)));

    this is a memory leak as the brush is created (resources allocated just as if you have alloc'ed ect) but can not be deleted. Ypur PC has much less GDI memory than RAM or virtual memory.

    >>SelectObject(hdc, CreateSolidBrush(RGB(0,0,0)));
    Here is another as you can not put the original brush (returned from SelectObject() ) back and so return the HDC to the way you Create'd or Get'ed it.


    >>DeleteObject((hdc, GetStockObject(WHITE_BRUSH)));

    And this does nothing. Stock objects do not need to be deleted, why create (alloc) some memory just to free it in the same line?

    As to you problem. A framebuffer system would have been easier (two HDC's, one is displayed (screen DC) while the other (bufferDC) is assembled. After the frameDC is draw it is copied (inc resized) to the screenDC and a WM_PAINT called for.

    Then a smaller function, that is given the little rect to change (where the player has moved) and the colour could be used to update each cell.

    then use mouse msg's to get the point clicked and PtInRect() to find the cell.

    Also an array of the form

    DataArray[NUM_COLS][NUM_ROWS] (rows down , cols across)
    would be better than the multiple switches you have.
    So you can
    Code:
    iCtrlID=GetDlgCtrlID(hwnd);
    iNumCtrl=iCtrlID-FIRST_CTRL_ID;//in your code FIRST_CTRL_ID == 0 it is the int ID of the first child
    iRow=iNumCtrl/NUM_COLS;
    iCol=iNumCtrl%NUM_COLS;
    iState=DataArray[iCol][iRow].iType;

    But other wise

    >>childID = GetDlgCtrlID(hwnd);

    Is this working? Are you getting the right rect in the drawing functions?

    Remember the WM_PAINT hdc is the invalid area on screen and may not be all of ONE square (so the drawing functions rect may be empty.

    use before BeginPaint()
    case WM_PAINT:
    GetUpdateRect(hWnd,&Rect)
    if(IsRectEmpty(&Rect))
    GetClientRect(hWnd,&Rect);
    BeginPaint(.......

    When you create the child windows, there is no Wndclass and the ID# used may conflict with others in the resource.h (should use 30,000+ to ensure no conflicts)
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  11. #11
    Registered User cMADsc's Avatar
    Join Date
    Jun 2002
    Posts
    18

    Thumbs up

    Hey Novacain, that was some good advice. I guess I got careless,
    ieeleteObject((hdc, GetStockObject(WHITE_BRUSH)));

    Although, i am not to familiar with double buffering in win32, just in opengl though. a little more explanation would help Thanks anyways!
    There are those who say they can, and there are those who acutally do.

    ...you can not learn programming in a class, you have to learn it on your own

  12. #12
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    GetStockObject() may not 'create' an instance of the GDI resource (so may not leak) but what ever was in the HDC is lost and is a leak.

    MS uses Select all over and it is poor coding style (IMO).

    Double buffering is easy, once you have done it.

    On Init
    you create two drawing 'areas' with CreateCompatibleDC(), CreateCompatibleBMP() (Select in the BMP's saving the returns from SelectObject() )

    On Input
    When the app decides (thru user input ect) that it must change what is on the screen. You draw to one of the DC's (the BUFFER).
    After all the drawing is finished you BitBlt() to the other, the FRAME( or StretchBlt() if the area has changed size)
    Do not use StretchBlt() unless you MUST, do not use it in the WM_PAINT. As it is slow and the results are terrible unless the areas have an int ratio.
    Ensure the DC's GDI objects are the same in the DC's when it leaves the drawing as when the DC entered the drawing functions.

    On Paint
    Find the update region and BitBlt() the FRAME to the paint DC.

    On Close
    Return the system BMP's to the DC's and free up resources by DeleteObject() the HDC's and the BMP's.

    I use an array of global structs to keep my window resources (HWND, HDC, BMP, original BMP ect) and free with a loop at the end. (as I code in WIN32 C no ++)
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Script errors - bool unrecognized and struct issues
    By ulillillia in forum Windows Programming
    Replies: 10
    Last Post: 12-18-2006, 04:44 AM
  2. list all child windows
    By Andrus in forum Windows Programming
    Replies: 1
    Last Post: 01-20-2006, 01:50 AM
  3. Virtual keys
    By Arkanos in forum Windows Programming
    Replies: 4
    Last Post: 12-12-2005, 10:00 AM
  4. two child windows, help!!!
    By terracota in forum Windows Programming
    Replies: 9
    Last Post: 12-08-2004, 06:30 PM
  5. Tab Controls - API
    By -KEN- in forum Windows Programming
    Replies: 7
    Last Post: 06-02-2002, 09:44 AM