Search code examples
c++winapiwindowminimizeredraw

When I minimize the window and restore it again the window has a black background, I can't figure out why


I'm new in programming Windows Application, and I have simple window with some checkboxes, text and button. Everything seems to work as it should, but when I minimize the window and restore it again the window has a black background, I can't figure out why.

MY WINDOW CLASS:

#include "Window.h"
#include <stdio.h>
#include <iostream>

#define CHECK_BOX1 1
#define CHECK_BOX2 2
#define Button_Submit_Checkboxes 3

HMENU hMenu;
HWND hText;

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    BOOL checked1 = IsDlgButtonChecked(hWnd, 1);
    BOOL checked2 = IsDlgButtonChecked(hWnd, 2);
    switch (uMsg)
    {
        case WM_COMMAND:            
    switch (wParam)
        { // When clicked on Checkbox1, then check or uncheck.
            case CHECK_BOX1:
                if (checked1) 
                {
                    CheckDlgButton(hWnd, 1, BST_UNCHECKED);
                }
            else {
                    CheckDlgButton(hWnd, 1, BST_CHECKED);
                }
            break;

            case CHECK_BOX2:
            if (checked2) {
                CheckDlgButton(hWnd, 2, BST_UNCHECKED);
            }
            else {
                CheckDlgButton(hWnd, 2, BST_CHECKED);
            }
            break;

        case Button_Submit_Checkboxes: // Button_Submit_Checkboxes
            SetWindowTextW(hText, L"ssss");
            bool check[2];
            check[0] = checked1;
            check[1] = checked2;
            std::cout << "\ncheck1 : " << check[0] << "\ncheck2 : " << check[1];
            break;
    }
    break;

        case WM_CLOSE: // If window is closed
        DestroyWindow(hWnd); // destroy window.
        break;

    case WM_DESTROY: // When window is destroyed.
        PostQuitMessage(0); // Send message to Windows.
        return 0;
    }

return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

Window::Window()
    : m_hInstance(GetModuleHandle(nullptr)) 
{
    const wchar_t* CLASS_NAME = L"Siggis Window Class"; 

    WNDCLASS wndClass = {};
    wndClass.lpszClassName = CLASS_NAME;
    wndClass.hInstance = m_hInstance;
    wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO); // icon !!
    wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // cursor !!
    wndClass.lpfnWndProc = WindowProc; 

    RegisterClass(&wndClass);

    DWORD style = WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU; 

    int width = 440;
    int height = 300;

    RECT rect;
    rect.left = 250;
    rect.top = 250;
    rect.right = rect.left + width;
    rect.bottom = rect.top + height;

    AdjustWindowRect(&rect, style, false);

    m_hWnd = CreateWindowEx(
        0,
        CLASS_NAME,
    L"MFM - Ver. 1.00", // window title.
    style,
    rect.left,
    rect.top,
    rect.right - rect.left,
    rect.bottom - rect.top,
    NULL,
    NULL,// this is for menu!!
    m_hInstance,
    NULL
    );

    ShowWindow(m_hWnd, SW_SHOW); // Display window.

    AddMacMakeDisplay(m_hWnd); // show text and Edit window
}

Window::~Window()
{
    const wchar_t* CLASS_NAME = L"Siggis Window Class";

    UnregisterClass(CLASS_NAME, m_hInstance);
}

bool Window::ProcessMessages()
{
    MSG msg = {};

    while (PeekMessage(&msg, nullptr, 0u, 0u, PM_REMOVE))
    {
        if (msg.message == WM_QUIT)
    {
        return false;
    }

    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }

    return true;
}


void Window::AddMacMakeDisplay(HWND hWnd)
{
    const int text_chkbox_left = 100;
    const int text_chkbox_top = 50;
    const int text_chkbox_width = 230;
    const int text_chkbox_height = 20;
    hText = CreateWindowExW(NULL, 
    L"static", 
    L"Choose : ", 
    WS_VISIBLE | WS_CHILD | SS_CENTER, 
    text_chkbox_left,
    text_chkbox_top,
    text_chkbox_width,
    text_chkbox_height,
    hWnd, 
    NULL, 
    NULL, 
    NULL);


// Checkbox Group Postion and Size
    const int chkbox_left = text_chkbox_left;
    const int chkbox_top = text_chkbox_top + text_chkbox_height+2;
    const int chkbox_width = text_chkbox_width;
    const int chkbox_height = 30;
// Create Checkbox1
    CreateWindowExW(NULL, 
        TEXT("button"), 
        TEXT("check1"),
        WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
    chkbox_left, 
    chkbox_top, 
    chkbox_width, 
    chkbox_height,
    hWnd, 
    (HMENU)CHECK_BOX1, 
    NULL, 
    NULL);
    CheckDlgButton(hWnd, 1, BST_CHECKED); // Checkbox1 statues (checked or unchecked)       
// Create Checkbox2
    CreateWindowExW(NULL,
        TEXT("button"), 
    TEXT("Check2"), 
    WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
    chkbox_left, 
    chkbox_top+chkbox_height, 
    chkbox_width, 
    chkbox_height,
    hWnd, 
        (HMENU)CHECK_BOX2, 
    NULL, 
    NULL);
    CheckDlgButton(hWnd, 2, BST_CHECKED); // Checkbox2 statues (checked or unchecked)


// Button_Submit_Checkboxes Position and Size
    const int button_left = text_chkbox_left;
    const int button_top = chkbox_top + (2* chkbox_height) + 30;
    const int button_width = text_chkbox_width;
    const int button_height = 50;
// Create Button_Submit_Checkboxes
    CreateWindowExW(NULL,
        L"Button",
        L"Change Title",
        WS_VISIBLE | WS_CHILD,
        button_left,
        button_top,
        button_width,
        button_height,
        hWnd,
    (HMENU)Button_Submit_Checkboxes,
    NULL,
    NULL);
}

This is my Main

#include <iostream>
#include "Window.h"

int main()
{
    std::cout << "Creating Windows\n";

    Window* pWindow = new Window();

    bool running = true;
    while (running)
    {
        if (!pWindow->ProcessMessages())
        {
            std::cout << "Closing Window\n";
            running = false;
        }
        // render
    
        Sleep(10);
    }

    delete pWindow;

    return 0;
}

I've tried to google the problem but without any luck. So I hope you can help me.


Solution

  • You're not filling in wndClass.hbrBackground. According to the documentation:

    When this member is NULL, an application must paint its own background whenever it is requested to paint in its client area. To determine whether the background must be painted, an application can either process the WM_ERASEBKGND message or test the fErase member of the PAINTSTRUCT structure filled by the BeginPaint function.

    If you want Windows to handle this for you, pass a valid handle or a colour-plus-one:

    wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);