WinAPI - C++ - How to completeley wipe/clear everything in window? - c++

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;
}

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);

Related

Radio button text doesn't get displayed properly when setting it's font to an italic font

When setting the font of a radio button to an italic font, the radio button text doesn't get displayed all the way. It gets clipped on the right side. It only happens when visual styles are on. I am testing this on Windows XP. How do you fix this?
#include <Windows.h>
#include <Commctrl.h>
#pragma comment(linker, \
"\"/manifestdependency:type='Win32' "\
"name='Microsoft.Windows.Common-Controls' "\
"version='6.0.0.0' "\
"processorArchitecture='*' "\
"publicKeyToken='6595b64144ccf1df' "\
"language='*'\"")
#pragma comment(lib, "Comctl32.lib")
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HFONT hFont = 0;
static HWND hBtn = 0;
switch(msg)
{
case WM_CREATE:
{
HDC hdc = GetDC(hwnd);
int nHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72);
hFont = CreateFont(nHeight, 0, 0, 0, FW_NORMAL, TRUE, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, L"Microsoft Sans Serif");
ReleaseDC(hwnd, hdc);
hBtn = CreateWindowEx(0, L"Button", L"Hello", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,
20, 20, 220, 20, hwnd, 0, GetModuleHandle(0), 0);
SendMessage(hBtn, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(FALSE, 0));
}
break;
case WM_PAINT: //"Hello" gets displayed properly with WM_PAINT but not in radio button
{
HDC hdc;
PAINTSTRUCT ps;
HFONT hOldFont;
hdc = BeginPaint(hwnd, &ps);
hOldFont = (HFONT)SelectObject(hdc, hFont);
TextOut(hdc, 20, 80, L"Hello", 5);
SelectObject(hdc, hOldFont);
EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
DeleteObject(hFont);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc = {0};
HWND hwnd;
MSG msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = L"MainClass";
RegisterClassEx(&wc);
InitCommonControls();
hwnd = CreateWindowEx(0, L"MainClass", L"Hello", WS_OVERLAPPEDWINDOW, 140, 140, 400, 200, 0, 0, hInstance, 0);
ShowWindow(hwnd, nCmdShow);
while(GetMessage(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}

Resize window to fit content after WM_PAINT

is there a way to resize after all WM_PAINT calls are done? so that i can automatically resize my window to fit whatever i have painted, since initially my window size is defined at a certain size, there may be leftover spaces that are not painted, how can i remove these leftover spaces?
As you can see from the screenshot below the white spaces are the leftover spaces.
#include <windows.h>
#include "resource.h"
#include "loadFromTextFile.h"
const char g_szClassName[] = "myWindowClass";
const int recLength = 3;
const int wndHeight = 700;
const int wndWidth = 700;
PAINTSTRUCT ps;
HDC hdc;
HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0));
HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0));
HPEN myPen = CreatePen(PS_NULL, 1, RGB(0, 0, 0));
//load from text
string FILE_PATH = ("10x10.txt");
loadFromTextFile loaded = loadFromTextFile(FILE_PATH);
int mazeWidth = loaded.getColumns() * recLength;
int mazeHeight = loaded.getRows() * recLength;
void paintMaze(HWND hwnd, vector<vector<string> > grid){
hdc = ::BeginPaint(hwnd, &ps);
SelectObject(hdc, myPen);
for (int r = 0; r < loaded.getRows(); r++){
for (int c = 0; c < loaded.getColumns(); c++){
RECT rect;
rect.left = c*recLength;//x upper left
rect.top = r*recLength;//y upper left
rect.right = (c + 1)*recLength;//x lower right corner
rect.bottom = (r + 1)*recLength;//y lower right corner
if (grid[r][c] == "1"){//1 path
FillRect(hdc, &rect, blackBrush);
}
else if (grid[r][c] == "0"){//wall
FillRect(hdc, &rect, whiteBrush);
}
if (r == 50 && c == 50){
FillRect(hdc, &rect, redBrush);
}
}
}
DeleteObject(blackBrush);
DeleteObject(whiteBrush);
DeleteObject(redBrush);
DeleteObject(myPen);
EndPaint(hwnd, &ps);
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_FILE_EXIT:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
case ID_ABOUT:
SetWindowPos(hwnd, 0, 0, 0, mazeWidth, mazeHeight, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
break;
}
break;
case WM_PAINT:
{
paintMaze(hwnd, loaded.getNodeGrid());
}
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(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);;
wc.lpszClassName = g_szClassName;
wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
wc.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 32, 32, 0);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
" Maze",
WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU,//prevent resize
CW_USEDEFAULT, CW_USEDEFAULT, wndWidth, wndHeight,
NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
Paint in an offscreen buffer.
This allows you to resize the window.
Paint the window by copying the buffer.

Transparency in GDI DCs

I have the "simple" goal of drawing a bitmap with some transparency around it on the screen. That bit wasn't so hard:
#include <windows.h>
#include "BBKG.h"
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static int wH = 156;
static int wW = 166;
HBITMAP CreateBitmapMask(HBITMAP hbmColour, COLORREF crTransparent)
{
HDC mem0, mem1;
HBITMAP hbmMask;
BITMAP bm;
GetObject(hbmColour, sizeof(BITMAP), &bm);
hbmMask = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);
mem0 = CreateCompatibleDC(0);
mem1 = CreateCompatibleDC(0);
SelectObject(mem0, hbmColour);
SelectObject(mem1, hbmMask);
SetBkColor(mem0, crTransparent);
BitBlt(mem1, 0, 0, bm.bmWidth, bm.bmHeight, mem0, 0, 0, SRCCOPY);
BitBlt(mem0, 0, 0, bm.bmWidth, bm.bmHeight, mem1, 0, 0, SRCINVERT);
DeleteDC(mem0);
DeleteDC(mem1);
return hbmMask;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
hInst = hInstance;
MSG msg;
HWND hwnd;
WNDCLASSW wc;
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.lpszClassName = L"nope";
wc.hInstance = hInst;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassW(&wc);
hwnd = CreateWindowW(wc.lpszClassName, L"",
WS_VISIBLE | WS_POPUP| WS_EX_TRANSPARENT,
100, 100, wW, wH, NULL, NULL, hInst, NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0)) {
//Workaround for focusables stealing my Esc key
if (msg.message == WM_KEYDOWN){
if (msg.wParam == VK_ESCAPE) {
SendMessage(hwnd, WM_CLOSE, 0, 0);
}
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
static int px;
static int py;
static HBITMAP bhbm;
static RECT nRect = { 0, 0, wW, wH };
switch (msg)
{
case WM_CREATE:
{
HWND bb = CreateWindowW(L"STATIC", L"",
WS_VISIBLE | WS_CHILD ,
0, 0, wW, wH,
hwnd, (HMENU)11, hInst, NULL);
//SetTimer(hwnd, 1, 80, NULL);
return 0;
}
case WM_PAINT: {
//Vars
RECT wRect;
if (GetUpdateRect(hwnd, &wRect, FALSE) == 0) {
return 0; //Nothing to paint
}
PAINTSTRUCT gps;
PAINTSTRUCT ps;
BeginPaint(hwnd, &gps);
HWND bb = GetDlgItem(hwnd, 11);
HDC bbhdc = BeginPaint(bb, &ps);
HDC mdc = CreateCompatibleDC(bbhdc);
//Load Image
BITMAP pBM;
HBITMAP pHBM = (HBITMAP)LoadImage(NULL, L"twi00.bmp", 0, 0, 0, LR_LOADFROMFILE);
HBITMAP pMBM = CreateBitmapMask((HBITMAP)pHBM, 0x00000000);
GetObject(pHBM, sizeof(pBM), &pBM);
//Paint
HBITMAP oldBM = (HBITMAP)SelectObject(mdc, pMBM);
BitBlt(bbhdc, 0, 0, pBM.bmWidth, pBM.bmHeight, mdc, 0, 0, SRCAND);
SelectObject(mdc, pHBM);
BitBlt(bbhdc, 0, 0, pBM.bmWidth, pBM.bmHeight, mdc, 0, 0, SRCPAINT);
//Cleanup
SelectObject(mdc, oldBM);
DeleteObject(pHBM);
DeleteObject(pMBM);
DeleteDC(mdc);
EndPaint(bb, &ps);
EndPaint(hwnd, &gps);
return 1;
}
case WM_ERASEBKGND: {
return 0;
}
case WM_DESTROY:
{
DeleteObject(bhbm);
PostQuitMessage(0);
return 0;
}
case WM_LBUTTONDOWN:
SetCapture(hwnd);
px = LOWORD(lParam);
py = HIWORD(lParam);
return 1;
case WM_LBUTTONUP:
{
ReleaseCapture();
return 1;
}
case WM_MOUSEMOVE:
{
if (GetCapture() == hwnd)
{
RECT rcWindow;
GetWindowRect(hwnd, &rcWindow);
SetWindowPos(hwnd, NULL, rcWindow.left + LOWORD(lParam) - px, rcWindow.top + HIWORD(lParam) - py, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
break;
}
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
Use any generic bmp with a black border will do, I used this:
Now the question is, how can I make it so that when I move the window (click/drag) the background updates? I was hoping for something like putting the bitmap into a transparent window so that it's overlayed on top of things but it seems to just grab the pixels of what ever is behind it.
I'm attempting to do this without GDI+ or other libraries, if possible.
CreateWindow() does not accept extended window styles, such as WS_EX_TRANSPARENT (which is why it has EX in its name). You have to use CreateWindowEx() instead:
hwnd = CreateWindowExW(WS_EX_TRANSPARENT,
wc.lpszClassName, L"",
WS_VISIBLE | WS_POPUP,
100, 100, wW, wH, NULL, NULL, hInst, NULL);
A better option is to create a layered window (see also this) by using the WS_EX_LAYERED extended style). Then you can use the UpdateLayeredWindow() function to provide the window with the bitmap and the transparent color (you can also specify alpha as well). Let the window manage all of the hard work of drawing the bitmap transparently for you.
Your WndProc() can also respond to the WM_NCHITTEST message to tell the OS that all clicks on the window should be treated as if the user were clicking on the window's titlebar. Let the window handle the mouse tracking and auto-positioning for you.
Try something more like this:
#include <windows.h>
HINSTANCE hInst;
static int wH = 156;
static int wW = 166;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
hInst = hInstance;
WNDCLASSW wc = {0};
wc.lpszClassName = L"nope";
wc.hInstance = hInst;
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassW(&wc);
HWND hwnd = CreateWindowEx(WS_EX_LAYERED,
wc.lpszClassName, L"",
WS_POPUP, 100, 100, wW, wH, NULL, NULL,
hInst, NULL);
HBITMAP hBmp = (HBITMAP) LoadImage(NULL, L"twi00.bmp", 0, 0, 0, LR_LOADFROMFILE);
HDC hdcScreen = GetDC(0);
HDC hdcBmp = CreateCompatibleDC(hdcScreen);
HBITMAP oldBM = (HBITMAP) SelectObject(hdcBmp, hBmp);
POINT pt = {0};
UpdateLayeredWindow(hwnd,
hdcScreen,
NULL, NULL,
hdcBmp, &pt,
RGB(0, 0, 0), // black
NULL, ULW_COLORKEY
);
SelectObject(hdcBmp, oldBM);
DeleteDC(hdcBmp);
ReleaseDC(0, hdcScreen);
DeleteObject(hBmp);
ShowWindow(hwnd, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0) {
//Workaround for focusables stealing my Esc key
if ((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE) {
SendMessage(hwnd, WM_CLOSE, 0, 0);
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
case WM_NCHITTEST:
{
return HTCAPTION;
}
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}

GDI sprite shown some time and disappear

I'm studying sprite drawing with GDI in Visual Studio 2013 with C++.
I can draw sprite using two bmp files, image with black background, and black mask. But after program start, sprite shown some time (about 15 second) and disappear. I can't find the reason.
Here is my code.
#include <Windows.h>
#include "resource.h"
using namespace std;
LRESULT WINAPI WinProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
HWND hWnd = 0;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
ZeroMemory(&msg, sizeof(msg));
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wc.hCursor = LoadCursor(hInst, MAKEINTRESOURCE(IDC_HAND));
wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ASTERISK));
wc.hInstance = hInst;
wc.lpfnWndProc = WinProc;
wc.lpszClassName = "ClassName";
wc.lpszMenuName = 0;
wc.style = CS_VREDRAW | CS_HREDRAW;
if (!RegisterClass(&wc))
MessageBox(0, "Class was not registered!", "Error", 0);
hWnd=CreateWindow("ClassName", "WindowName", WS_OVERLAPPEDWINDOW, 100, 100, 640, 480, 0, 0, hInst, 0);
if (hWnd==0)
MessageBox(0, "Window was not created!", "Error", 0);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (msg.message!=WM_QUIT)
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
HDC hdc = GetDC(hWnd);
HDC hBuffDC = CreateCompatibleDC(hdc);
HDC hMemDC = CreateCompatibleDC(hdc);
HBITMAP hBuffBitmap = CreateCompatibleBitmap(hdc, 640, 480);
HBITMAP hSpriteBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_MASK));
SelectObject(hBuffDC, hBuffBitmap);
SelectObject(hBuffDC, (HBRUSH)GetStockObject(GRAY_BRUSH));
Rectangle(hBuffDC, 0, 0, 640, 480);
SelectObject(hMemDC, hSpriteBitmap);
BitBlt(hBuffDC, 0, 0, 640, 480, hMemDC, 0, 0, SRCAND);
hSpriteBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SPRITE));
SelectObject(hMemDC, hSpriteBitmap);
BitBlt(hBuffDC, 0, 0, 640, 480, hMemDC, 0, 0, SRCPAINT);
BitBlt(hdc, 0, 0, 640, 480, hBuffDC, 0, 0, SRCCOPY);
DeleteObject(hBuffBitmap);
DeleteObject(hSpriteBitmap);
DeleteDC(hMemDC);
DeleteDC(hBuffDC);
ReleaseDC(hWnd, hdc);
}
return 0;
}
LRESULT WINAPI WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_KEYDOWN:
switch (wParam)
{
case VK_ESCAPE:
DestroyWindow(hWnd);
break;
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
images are just a black circle with white background (mask), and green circle with black background.
//Here is corrected code without memory leak and ReleaseDc return 1
#include <Windows.h>
#include "resource.h"
using namespace std;
LRESULT WINAPI WinProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
HWND hWnd = 0;
HDC hdc = 0;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
ZeroMemory(&msg, sizeof(msg));
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wc.hCursor = LoadCursor(hInst, MAKEINTRESOURCE(IDC_HAND));
wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ASTERISK));
wc.hInstance = hInst;
wc.lpfnWndProc = WinProc;
wc.lpszClassName = "ClassName";
wc.lpszMenuName = 0;
wc.style = CS_VREDRAW | CS_HREDRAW;
if (!RegisterClass(&wc))
MessageBox(0, "Class was not registered!", "Error", 0);
hWnd=CreateWindow("ClassName", "WindowName", WS_OVERLAPPEDWINDOW, 100, 100, 640, 480, 0, 0, hInst, 0);
if (hWnd==0)
MessageBox(0, "Window was not created!", "Error", 0);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
hdc = GetDC(hWnd);
while (msg.message!=WM_QUIT)
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
HDC hBuffDC = CreateCompatibleDC(hdc);
HDC hMemDC = CreateCompatibleDC(hdc);
HBITMAP hBuffBitmap = CreateCompatibleBitmap(hdc, 640, 480);
HBITMAP hSpriteBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SPRITE));
HBITMAP hMaskBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_MASK));
HBITMAP hOldBuffBitmap= (HBITMAP)SelectObject(hBuffDC, hBuffBitmap);
HBRUSH hOldBrush= (HBRUSH)SelectObject(hBuffDC, (HBRUSH)GetStockObject(GRAY_BRUSH));
Rectangle(hBuffDC, 0, 0, 640, 480);
HBITMAP hOldSpriteBitmap= (HBITMAP)SelectObject(hMemDC, hMaskBitmap);
BitBlt(hBuffDC, 0, 0, 640, 480, hMemDC, 0, 0, SRCAND);
SelectObject(hMemDC, hSpriteBitmap);
BitBlt(hBuffDC, 0, 0, 640, 480, hMemDC, 0, 0, SRCPAINT);
BitBlt(hdc, 0, 0, 640, 480, hBuffDC, 0, 0, SRCCOPY);
SelectObject(hBuffDC, hOldBuffBitmap);
SelectObject(hMemDC, hOldSpriteBitmap);
SelectObject(hBuffDC, hOldBrush);
DeleteObject(hBuffBitmap);
DeleteObject(hSpriteBitmap);
DeleteObject(hMaskBitmap);
DeleteDC(hMemDC);
DeleteDC(hBuffDC);
}
return 0;
}
LRESULT WINAPI WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_KEYDOWN:
switch (wParam)
{
case VK_ESCAPE:
DestroyWindow(hWnd);
break;
}
return 0;
case WM_CLOSE:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
int Res = ReleaseDC(hWnd, hdc); //Release main window device context before destroying window
DWORD err = GetLastError();
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

How to change an image in a window MFC application

Let me start off by saying that I am very new to MFC applications, so please bear with me...
I would like to create a window with an image (lets say a green light). When necessary, I want the application to change the image (to a yellow or red light). I have code that will create the window and display the image (green light), but it will not update the image (when i == 15 or i == 50)
#include "resource.h"
using namespace std;
const char g_szClassName[] = "myWindowClass";
HBITMAP Light = NULL;
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_PAINT:
{
BITMAP bm;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, Light);
GetObject(Light, sizeof(bm), &bm);
BitBlt(hdc, 20, 180, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
}
case WM_CREATE:
{
Light = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP1));
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
{
DeleteObject(Light);
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;
int eventCode;
int i = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = (LPCSTR)g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, (LPCSTR)"Window Registration Failed!", (LPCSTR)"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
(LPCSTR)g_szClassName,
(LPCSTR)"Test Picture",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 420, 280,
NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
MessageBox(NULL, (LPCSTR)"Window Creation Failed!", (LPCSTR)"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
if (i == 15)
{
Light = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP3));
UpdateWindow(hwnd);
}
else if (i == 50)
{
Light = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP2));
UpdateWindow(hwnd);
}
i++;
}
return Msg.wParam;
}
I thought that I could do
Light = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP3));
UpdateWindow(hwnd);
to update the window picture, but I was wrong :( ...what could I use to change the image?
You need to call InvalidateRect to cause a repaint. UpdateWindow doesn't do anything if the window's invalid region is empty.