1

I'm trying to change the background color of a dialog box (win 7, vs2010,c++).

I tried to catch WM_CTLCOLOR, WM_ERASEBKGND and change the color. I managed to catch only the WM_ERASEBKGND message but in this way I manage in debug mode to see that I changed the background color of the window, but when the dialogBox is finish to upload itself, the color is overrun by the defualt grey color of the DialogBox.

I'm creating the DialogBox using the CreateDialogParam func.

case WM_ERASEBKGND:
{
   HBRUSH brush;
   RECT rect;
   brush = CreateSolidBrush(RGB(255,0,0));
   SelectObject((HDC)wParam,brush);
   GetClientRect(m_hDlg,&rect)//m_hDlg is HWND type
   Rectangle((HDC)wParam,rect.left,rect.top,rect.right,rect.bottom);
   break;
}

I tried to use the function:

SetBkMode((HDC)wParam,TRANSPARENTE);

but it didn't help.

What should I do?

newfurniturey
  • 37,556
  • 9
  • 94
  • 102
David
  • 287
  • 2
  • 3
  • 13
  • Please show a complete program – David Heffernan Dec 11 '13 at 12:48
  • its too big to add, i added only the relevant part. – David Dec 11 '13 at 12:49
  • How do you know you added the relevant part? Please show a complete program. Cut it down to size. It should be possible to do it in around 50 lines of code. – David Heffernan Dec 11 '13 at 12:51
  • It's to difficult for me to minimize the code because I use a framework that wraps all the dlg functions and it's to much of code to post – David Dec 11 '13 at 13:03
  • Try harder. We need an SSCCE. From the close vote text: *Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See http://SSCCE.org for guidance.* Because you won't do this, I vote to close. And I downvote. – David Heffernan Dec 11 '13 at 13:04
  • @user2171244 you could post a simple c++ Win32 program which would display a message every time user clicks left mouse button and your attempt to change the background colour in that situation. :-) Good luck :-) – XAMlMAX Dec 11 '13 at 13:44
  • I tried to catch up the wm_lbuttondblclk in the dlgProc but I couldn't catch it. I'm only able to catch this msg in the wndProc. But when I try to change the background color from there nothing happened – David Dec 11 '13 at 14:10

2 Answers2

9

You need to handle WM_CTLCOLORDLG. You should return a brush handle. For example, to make the background white:

case WM_CTLCOLORDLG:
    return (INT_PTR)GetStockObject(WHITE_BRUSH);
arx
  • 16,686
  • 2
  • 44
  • 61
  • As I mentioned in the question I couldn't catch this msg in the dlgProc – David Dec 11 '13 at 14:12
  • This is why we need an SSCCE. Stop being lazy and make one. You'd have had an answer by now if you'd done so. – David Heffernan Dec 11 '13 at 14:16
  • I can't do so because as I mentioned before I'm have the code on my work computer and I can't connect him to the net. So if I want do make the sscce I need to manually write my program and rewrite it in here. And as I said before it's too big to be copied. – David Dec 11 '13 at 14:20
  • 2
    @user2171244 In the question you said WM_CTLCOLOR, not WM_CTLCOLORDLG. Create a new win32 app in Visual Studio. Paste the code above into the "About" function (the message handler for the about box). The about box will now have a white background. Your problem is either finger trouble or an issue in your unidentified framework. Absent the code, I can't help with either. – arx Dec 11 '13 at 14:59
4

When you respond to WM_ERASEBKGND you must return TRUE, otherwise your default dialog procedure will set the color of the dialog to the default system color.

Also, your second parameter in your call to SelectObject is wrong, it should be TRANSPARENT, not TRANSPARENTE.

As member arx said, you need to handle WM_CTLCOLORDLG message to achieve what you want.

Here is a small demo app that you can copy and paste into your Visual Studio:

In your resource.h paste this:

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Dlg bkgnd.rc
//
#define IDD_DIALOG1                     101
#define IDC_BUTTON1                     1001

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1002
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif 

Do not forget the empty line above!

In your resource file ( .rc extension ) paste this:

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_DIALOG1 DIALOGEX 0, 0, 200, 124
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,52,71,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,111,71,50,14
    PUSHBUTTON      "",IDC_BUTTON1,47,23,73,16
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO 
BEGIN
    IDD_DIALOG1, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 189
        TOPMARGIN, 7
        BOTTOMMARGIN, 117
    END
END
#endif    // APSTUDIO_INVOKED

#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

And finaly, the main.cpp:

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

// variable for storing the instance

static HINSTANCE hInst; 

// handle for dialog box

static HWND Dlg;

// dialog procedure

INT_PTR CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    static HBRUSH testBrush;

    switch(Message)
    {
    case WM_INITDIALOG:

          //set text of our static control with the data sent to dialog
          SetWindowText( GetDlgItem( hwnd, IDC_BUTTON1 ), (LPCWSTR)lParam );

          //initialize the brush
          testBrush = CreateSolidBrush( RGB( 255, 0, 0 ) );

          return TRUE;

    case WM_CTLCOLORDLG:
          return (INT_PTR)( testBrush );

    case WM_CLOSE: 
          // if we do not use stock brush we must destroy it
          DeleteObject( testBrush );
          DestroyWindow( hwnd );
          Dlg = NULL;
          return TRUE;
    case WM_COMMAND:
          switch(LOWORD(wParam))
          {
               case IDOK:
               case IDCANCEL:

                    // if we do not use stock brush we must destroy it
                    DeleteObject( testBrush );
                    DestroyWindow( hwnd );
                    Dlg = NULL;
                    break;
          }
          break;
    default:
          return FALSE;
    }
    return TRUE;
}

// WinMain's procedure

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_CREATE:
          {
               Dlg = NULL;

               // create button we can click on 
               HWND btn = CreateWindowEx( 0, L"Button", L"Click me!", 
                                          WS_VISIBLE | WS_CHILD | SS_NOTIFY, 
                                          65, 10, 70, 50, hwnd, 
                                          (HMENU)4000, hInst, 0);
          }
          return (LRESULT)0;

    case WM_COMMAND:

          switch( LOWORD(wParam) )
          {
               case 4000: // activate dialog box
                   {
                        // we will send anything as the parameter to the dialog
                        // this is just an example
                        Dlg = CreateDialogParam( hInst, MAKEINTRESOURCE(IDD_DIALOG1),
                                                 hwnd, DlgProc, (LPARAM)L"Test text" );
                        //show it
                        ShowWindow( Dlg, SW_SHOW );
                   }
                   break;

               default: // pass it to the default window procedure
                   return DefWindowProc(hwnd, msg, wParam, lParam);
          }
          break;

    case WM_PAINT:
         {
               // we do not paint anything
               PAINTSTRUCT ps;
               BeginPaint( hwnd, &ps);
               EndPaint( hwnd, &ps);
         }
         return (LRESULT)0;

    case WM_CLOSE:

         DestroyWindow(hwnd);

         return (LRESULT)0;

    case WM_DESTROY:

         PostQuitMessage(0);

         return (LRESULT)0;

    default:
         return DefWindowProc(hwnd, msg, wParam, lParam);
   }
   return 0;
}

// WinMain

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, 
               int nCmdShow)
{
   // store hInstance in global variable for later use

   hInst = hInstance;

   WNDCLASSEX wc;
   HWND hwnd;
   MSG Msg;

   // register main window class

   wc.cbSize = sizeof(WNDCLASSEX);
   wc.style = 0;
   wc.lpfnWndProc = WndProc;
   wc.cbClsExtra = 0;
   wc.cbWndExtra = 0;
   wc.hInstance = hInst;
   wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
   wc.hCursor = LoadCursor( NULL, IDC_ARROW );
   wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
   wc.lpszMenuName = NULL;
   wc.lpszClassName = L"Main_Window";
   wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc))
    {
       MessageBox(NULL, L"Window Registration Failed!", L"Error!",
                  MB_ICONEXCLAMATION | MB_OK);

       return 0;
    }

    // create main window

    hwnd = CreateWindowEx( 0,
                           L"Main_Window", 
                           L"test app", 
                           WS_OVERLAPPEDWINDOW,
                           CW_USEDEFAULT, 
                           CW_USEDEFAULT, 
                           200, 100, NULL, NULL, hInstance, 0 );

    if(hwnd == NULL)
    {
       MessageBox(NULL, L"Window creation failed!", L"Error!", 
                  MB_ICONEXCLAMATION | MB_OK);

       return 0; 
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        // check if message is for dialog or main window
        if(!IsDialogMessage( Dlg, &Msg ) )
        {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
    }

    return Msg.wParam;
}

Especially pay attention to the message loop, and the way I have stored the HWND of the dialog.

Also note that the brush you create is the brush you must destroy when you no longer need ( usually in response to WM_CLOSE ).

If there is anything else I can do to help, ask me and I will try to help you.

Best regards.

AlwaysLearningNewStuff
  • 2,939
  • 3
  • 31
  • 84