SetBkMode() appears not to be working


  • Hi All,
    I am developing in Native C++ using Visual Stodio in a Win32 API Environment. I have a strange problen in that SetBkMode() appears not to be setting the background to OPAQUE. In WM_PAINT, just before EndPaint(), the following code is inserted and run in debug:

    iTemp = GetBkMode(hdc); // after F10, iTemp = 2
    iTemp = SetBkMode(hdc, OPAQUE); // after F10, iTemp = 2

    Surely iTemp should be 1?

    This results in the background being TRANSPARENT, and I can't get it to paint the default background colour as set in the window class, viz. hbrBackground = (HBRUSH)(COLOR_WINDOW + 1), ie. white.

    Any ideas as to how to fix would be appreciated.

    Friday, February 12, 2010 10:16 AM


All replies

  • GetBkMode returns current background mix mode, SetBkMode will return the same previous mode.
    OPAQUE param allows to draw text with background that is filled with current DC brush.
    Friday, February 12, 2010 10:37 AM
  • MSDN says:

    The background mode defines whether the system removes existing background colors on the drawing surface before drawing text , hatched brushes, or any pen style that is not a solid line.


    How is this related to background color of a window?

    Microsoft MVP - Visual C++
    Posts are provided as is without warranties or guaranties.
    Friday, February 12, 2010 10:41 AM
  • Hi Nikita,
    Thanks for reply, although this much I do know. To explain further, when the screen is first painted, all is correct. When I press Alt+Tab to go to debug, and then Alt+Tab to return to program, the background is transparent and all my WM_PAINT and edit boxes are displayed over the debug screen.

    How do I then solve my problem?
    Friday, February 12, 2010 10:43 AM
  • Post your WM_PAINT and, if exists, WM_ERASEBKGND code blocks.
    • Marked as answer by Richard.G Friday, February 12, 2010 11:48 AM
    Friday, February 12, 2010 11:25 AM
  • Hi Nikita,
    Thanks. I will try this, but I need to research WM_ERASEBKGND first. Never encountered it yet. Will come back to you if I have further problems/questions.

    Friday, February 12, 2010 11:48 AM
  • I meant post your code blocks here if they exist in your code.
    Friday, February 12, 2010 12:00 PM
  • Hi Nikita,
    I have inserted code as follows:

    return 0;

    But this makes no difference. When I return to the program from debug the background is still transparent. The way I understand it, in more simple terms, WM_PAINT paints the foreground and WM_ERASEBKGND paints (clears or erases) the background.

    I need to do the opposite of WM_ERASEBKGND, ie. paint the background with a white brush before painting the foreground. Maybe I need to insert some code into the above case statement for it to paint the background white?

    Any further suggestions?
    Friday, February 12, 2010 1:13 PM
  • Remove WM_ERASEBKGND handler from the code.
    Set hbrBackground member of WNDCLASS struct to (HBRUSH)GetStockObject(WHITE_BRUSH).
    And draw what you want in WM_PAINT.
    On each paint cycle background will be white.
    Friday, February 12, 2010 1:27 PM
  • Hi Nikita,
    Code as follows. The code is actually too long to post, so I have left out parts dealing with TEXTOUT. Hope you can make something of it.

    case WM_PAINT:

    hdc = BeginPaint(hWnd, &ps);


    hFont = fnCreateFont(hdc, TEXT("Arial"), 90, -6, 0, TRUE);

    SelectObject(hdc, hFont);


    fnPlace_of_Residence_Paint(hWnd, hdc, hFont);


    EndPaint(hWnd, &ps);




    BOOL fnPlace_of_Residence_Paint(HWND hWnd, HDC hdc, HFONT hFont)



                 HBRUSH          hBrush;

                 RECT               aRect;

                 POINT              pt;



                char szBuffer[150] = {0};

                char *pText      = "";

                char *pID                      = "";


                sd_yRow          = 10;

                iRow                             = sd_yRow;

                pt.x                                          = 0;

                pt.y                                          = iRow;


                ClientToScreen(hWnd, &pt);

                aRect.left                                  = 6;

                                        = 0;

                aRect.right                   = dl_xCenter;

                aRect.bottom    = pt.y;


                hBrush = (HBRUSH) GetStockObject(LTGRAY_BRUSH);

                FillRect(hdc, &aRect, hBrush);


                MoveToEx(hdc, dl_xCenter, 0, 0);

                LineTo(hdc, dl_xCenter, pt.y);

                LineTo(hdc, 6, pt.y);


                sd_yRow          = 20;

                iRow                             = sd_yRow);

                pt.y                                          = iRow;

                MoveToEx(hdc, dl_xCenter, iRow, &pt);

                pt.y                                          = iRow;

                LineTo(hdc, 6, pt.y);


                SetBkMode(hdc, TRANSPARENT);


                sd_yRow          = 6;

                iCol                                          = sd_xCol;

                iRow                             = sd_yRow;

                pText                           = "Place(s) of Residence";

                wsprintfA(szBuffer, "%s", pText);

                iTextLen = strlen(szBuffer);

                TextOutA(hdc, iCol, iRow, szBuffer, iTextLen);



                sd_xCol                        = 8;

                sd_yRow          = 65;


                iCol                                          = sd_xCol;

                iRow                             = sd_yRow;

                pText                           = "Address 1";

                iTextLen           = strlen(pText);

                TextOutA(hdc, iCol, iRow, pText, iTextLen);


                SetBkMode(hdc, OPAQUE);

                return TRUE;



    Friday, February 12, 2010 1:52 PM
  • WM_PAINT should ends with return 0, if application process message.
    Friday, February 12, 2010 1:59 PM
  • Hi Nikita,
    Done the changes. When WM_PAINT breaks after EndPaint(), it goes to the end of the proc and there it returns 0;

    Unfortunately it still paints in transparent mode. I have three programs, lets say prg A, prg B and prg C. prg A resides in normal memory, whilst prg B & prg C reside in a DLL. Prg A subclasses prg B which in turn subclasses prg C directly, in some way like a dialog box. Prg C then paints a rect in grey with edit boxes in the top left hand corner.

    My theory is that I think when subclassing prg C directly from prg B, it looses the value of hbrBackground. Is this a possibility, as prg B works correctly.

    Friday, February 12, 2010 2:24 PM
  • Window proc should ends with: return DefWindowProc(hWnd, nMsg, wParam, lParam);
    • Marked as answer by Richard.G Friday, February 12, 2010 2:48 PM
    Friday, February 12, 2010 2:41 PM
  • Hi Nikita,
    You are Brilliant. I have no idea why I REMMED out this line from the subproc. Removed the REM and it now behaves correctly.
    Thanks for your patience with me in this matter.

    Friday, February 12, 2010 2:47 PM