Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

change the background color of a dialog box win32api

Tags:

c++

winapi

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?

like image 428
David Avatar asked Jan 28 '26 02:01

David


2 Answers

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);
like image 105
arx Avatar answered Jan 29 '26 14:01

arx


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.

like image 22
AlwaysLearningNewStuff Avatar answered Jan 29 '26 15:01

AlwaysLearningNewStuff