2
votes

I am using WinAPI in C++ for my application. I have painted some text and drawn a bitmap in the window by handling the WM_PAINT message. I have also put some button controls in the window via the CreateWindow function by handling the WM_CREATE message. I have spent hours researching this but i've had no luck - How can I completely clear the window and all of it's content (what i've put in it), so i'm left with an empty window with the same background title, etc, so I can put more buttons and stuff on it.

Here's My Code

#include <windows.h>
#include <string>
#include "mainheader.h"

const char g_szClassName[] = "myWindowClass";
HBITMAP bitmap;

//Window Procedure #Brain of the Window
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
    switch(msg){
        case WM_CREATE:{
            CreateWindow(TEXT("button"), TEXT("Play"),
                         WS_VISIBLE | WS_CHILD,
                         100, 227, 80, 25,
                             hwnd, (HMENU) 1, NULL, NULL);

            CreateWindow(TEXT("button"), TEXT("Stats"),
                         WS_VISIBLE | WS_CHILD,
                         200, 227, 80, 25,
                         hwnd, (HMENU) 2, NULL, NULL);

            CreateWindow(TEXT("button"), TEXT("Quit"),
                         WS_VISIBLE | WS_CHILD,
                         300, 227, 80, 25,
                         hwnd, (HMENU) 3, NULL, NULL);

            bitmap = (HBITMAP) LoadImage(NULL, TEXT("menuIcon.bmp"), IMAGE_BITMAP, 130, 130, LR_LOADFROMFILE);
            break;
        }

        case WM_COMMAND:{
            switch(LOWORD(wParam)){
                case 1:{
                    break;
                }

                case 2:{
                    break;
                }

                case 3:{
                    PostQuitMessage(0);
                }
            }

            break;
        }

        case WM_PAINT:{
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            HDC hMemDC = CreateCompatibleDC(hdc);

            ::SelectObject(hMemDC, bitmap);
            BitBlt(hdc, 170, 65, 200, 400, hMemDC, 0, 0, SRCCOPY);
            ::DeleteDC(hMemDC);

            SetBkColor(hdc, RGB(0, 0, 0));
            SetTextColor(hdc, RGB(0, 255, 0));

            std::string text = "Welcome to Tic Tac Toe v2.0!";
            std::string text2 = "Made By: Jaden Peterson (2015)";
            std::string text3 = "Please choose an option below:";

            TextOut(hdc, 150, 20, text.c_str(), text.length());
            TextOut(hdc, 141, 45, text2.c_str(), text2.length());
            TextOut(hdc, 145, 200, text3.c_str(), text3.length());
            EndPaint(hwnd, &ps);
            break;
        }

        case WM_CLOSE:{
            DestroyWindow(hwnd);
            break;
        }

        case WM_DESTROY:{
            PostQuitMessage(0);
            break;
        }

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

    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));

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

    //Creating the Window
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        "Tic Tac Toe v2.0",
        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
        CW_USEDEFAULT, CW_USEDEFAULT, 500, 300,
        NULL, NULL, hInstance, NULL);

    if(hwnd == NULL){
        MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

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

    //Message Loop #Heart of the Window
    while(GetMessage(&Msg, NULL, 0, 0) > 0){
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    return Msg.wParam;
}
1
If you don't want the bitmap to appear, stop painting it. - David Heffernan
I'm hoping there's one way to clear the entire window, so I don't have to manually delete every control/element in it. - jadenPete
It's clear that you don't understand how painting works in windows. There's no persistent state. There's nothing to clear. Invalidate the window rect and when the paint cycle comes, paint nothing. If you showed some code we could probably give you some more specific advice. - David Heffernan
The answer is to write the code to remove all of the child windows you created. How you keep track of the buttons and other windows you created should have been part of your initial design. - PaulMcKenzie
To elaborate what David Heffernan meant by 'Invalidate the window rect and when the paint cycle comes, paint nothing', read about Messages and Event Handling. Invalidation of a window is an Event, for which there exists a corresponding message handler. The message handler is simply a function, and in this case, its job is to paint the window starting from a fresh canvas. Obviously, if you do nothing in the handler, the blank canvas will remain blank. To change the view, you just draw the window again, this happens very fast and so you dont notice the window was completely redrawn - The Vivandiere

1 Answers

4
votes

Deleting all child windows is simple. Do a loop and enum all the child windows using EnumChildWindows . For each returned handle, call DestroyWindow.

First declare the callback function:

BOOL CALLBACK DestoryChildCallback(
  HWND   hwnd,
  LPARAM lParam
)
{
  if (hwnd != NULL) {
    DestroyWindow(hwnd)
  }

  return TRUE;
}

From your code:

EnumChildWindows(hwnd /* parent hwnd*/, DestoryChildCallback, NULL);