Resizing window with Win32 API - c++

i'm writing a program with the Win32 API just to get a hang of it and have come across this annoying problem. After a little while of resizing the window minimizes and after bringing it up again it's visible but non-clickable and clicking on it just activates what's on the window below it. The only solution being exiting the program.
At first i thought it was because of my custom-made function for sizing the window (i use a custom gui and don't want the default windows sizebox border) but then i reactivated the default sizebox and the problem still persisted. It's hard to tell but the problem seems to consistently occur after roughly the same amount of time/ticks being resized.
I had a similar problem before where the window would minimize and then becoming completely white when brought up again, which for some reason was caused by a for-loop in the resizing function.
I have excluded as many potential problems as possible in the code but still haven't found a solution. Below is the source file where all the code handling how the window is drawn lies (with the default sizebox).
I appreciate any help i can get.
Ps. I apologize for any bad language (non-native speaker), incorrectly used terms or bad syntax (first time venturing this far into the API).
//WinMain.cpp
#include <Windows.h>
#include "Utility.h"
#include "Mouse.h"
#include "AppInfo.h"
#include "Buttons.h"
//Function prototypes
ATOM MainRegister();
bool MainInit(HWND &hWnd, int nCmdShow);
void MatchRectToWnd(RECT &rect);
//Variables define in AppInfo.h
HRGN rgnMain, rgnCaptionbar;
bool _APPRUNNING = true;
const char _APPTITLE[] = "Dark";
//Variables
bool WIREFRAME = false;
//Pointers to buttons (singelton design)
btnCloseClass * btnCloseClass::s_Instance = 0;
btnMaximizeClass * btnMaximizeClass::s_Instance = 0;
btnMinimizeClass * btnMinimizeClass::s_Instance = 0;
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONDBLCLK: //Left mouse button double-clicked
Mouse.CheckDblClick(hWnd, wParam);
Mouse.m_Pressed = false;
break;
case WM_LBUTTONDOWN: //Left mouse button clicked
//Update the mouse position variables
GetCursorPos(&Mouse.prevPt);
GetCursorPos(&Mouse.m_LastClick);
Mouse.m_Pressed = true;
Mouse.CheckClickDown(hWnd);
break;
case WM_LBUTTONUP: //Left mouse button released
{
GetCursorPos(&Mouse.prevPt);
Mouse.CheckClickUp(hWnd);
Mouse.m_Pressed = false;
}
break;
case WM_SIZE: //Check if the window has been resized
{
//Update the buttons
btnClose->Update(hWnd);
btnMaximize->Update(hWnd);
btnMinimize->Update(hWnd);
//Update the regions
RECT rect; GetWindowRect(hWnd, &rect);
rgnMain = CreateRectRgn(0, 0, rect.right - rect.left, rect.bottom- rect.top);
rgnCaptionbar = CreateRectRgn(0, 0, rect.right - rect.left, CAPTIONBAR_HEIGHT);
}
break;
case WM_PAINT: //Draw the window
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hBrush;
hdc = BeginPaint(hWnd, &ps);
//Color the mainregion
hBrush = CreateSolidBrush(COLOR_MAIN);
FillRgn(hdc, rgnMain, hBrush);
//Color the captionbarregion
hBrush = CreateSolidBrush(COLOR_CAPTIONBAR);
FillRgn(hdc, rgnCaptionbar, hBrush);
//Color the button backgrounds
hBrush = CreateSolidBrush(COLOR_BUTTON_BACKGROUND);
FillRgn(hdc, btnClose->GetRegion(), hBrush);
FillRgn(hdc, btnMinimize->GetRegion(), hBrush);
FillRgn(hdc, btnMaximize->GetRegion(), hBrush);
//Color the button icons
hBrush = CreateSolidBrush(COLOR_BUTTON_ICON);
FillRgn(hdc, btnClose->GetIcon(), hBrush);
FillRgn(hdc, btnMinimize->GetIcon(), hBrush);
FillRgn(hdc, btnMaximize->GetIcon(), hBrush);
//Paint the wireframe
if (WIREFRAME)
{
hBrush = CreateSolidBrush(COLOR_WIREFRAME);
FrameRgn(hdc, rgnMain, hBrush, 1, 1);
FrameRgn(hdc, rgnCaptionbar, hBrush, 1, 1);
FrameRgn(hdc, btnClose->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnMaximize->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnMinimize->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnClose->GetIcon(), hBrush, 1, 1);
FrameRgn(hdc, btnMaximize->GetIcon(), hBrush, 1, 1);
FrameRgn(hdc, btnMinimize->GetIcon(), hBrush, 1, 1);
}
//Free up memomry
DeleteObject(hBrush);
EndPaint(hWnd, &ps);
}
break;
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_TAB: //If TAB is pressed
{
if (WIREFRAME) //Activate the wireframe
WIREFRAME = false;
else
WIREFRAME = true;
InvalidateRgn(hWnd, NULL, true);
}
break;
case VK_ESCAPE: //If the ESCAPE is pressed
PostMessage(hWnd, WM_DESTROY, 0, 0);
break;
}
}
break;
case WM_DESTROY: //Free up memory and exit the program
_APPRUNNING = false;
DeleteObject(rgnMain);
DeleteObject(rgnCaptionbar);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
break;
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;
_APPRUNNING = true;
//Register the main window
if (!MainRegister())
{
MessageBox(hWnd, "Error registering main window!", "Error", MB_ICONERROR);
return false;
}
//Initialize the main window
MainInit(hWnd, nCmdShow);
//App-loop
while (_APPRUNNING)
{
if ((GetKeyState(VK_LBUTTON) & 0x80) == 0) //Make sure the mouse's status gets updated
{
Mouse.m_Pressed = false;
}
Mouse.Update(hWnd);
//Message-loop
if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
bool MainInit(HWND &hWnd, int nCmdShow)
{
//Create the window
hWnd = CreateWindowEx(
WS_EX_LAYERED,
_APPTITLE,
_APPTITLE,
WS_OVERLAPPEDWINDOW,
0, 0, //Starting positons (x,y)
START_WIDTH, START_HEIGHT, //Width and height
NULL, //Parent-handle
NULL, //Menu-handle
GetModuleHandle(NULL),
NULL);
//Make sure the window was created properly
if (hWnd == NULL)
{
MessageBox(hWnd, "Error initializing main window!", "Error!", MB_ICONERROR);
return false;
}
SetLayeredWindowAttributes(hWnd, NULL, NULL, NULL);
//Get and set the window's style
DWORD wndStyle = GetWindowLong(hWnd, GWL_STYLE);
wndStyle &= ~(WS_CAPTION);
SetWindowLong(hWnd, GWL_STYLE, wndStyle);
//Create regions
rgnMain = CreateRectRgn(0, 0, START_WIDTH, START_HEIGHT);
rgnCaptionbar = CreateRectRgn(0, 0, START_WIDTH, CAPTIONBAR_HEIGHT);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return true;
}
ATOM MainRegister()
{
//Create the window's classEx (extended class)
WNDCLASSEX wc;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hInstance = GetModuleHandle(NULL);
wc.lpfnWndProc = MainWndProc;
wc.lpszClassName = _APPTITLE;
wc.lpszMenuName = NULL;
wc.style = CS_DBLCLKS;
//Register the classEx
return RegisterClassEx(&wc);
}

As #CodyGray suggested here's the working code aswell as the class and the functions dealing with freeing up memory for the region and now brushes too.
Edit: The problem was caused by a memory leak in WM_PAINT when creating, and not deleting, brushes (HBRUSH).
//WinMain.cpp
#include <Windows.h>
#include "Utility.h"
#include "Mouse.h"
#include "AppInfo.h"
#include "Buttons.h"
//Function prototypes
ATOM MainRegister();
bool MainInit(HWND &hWnd, int nCmdShow);
void MatchRectToWnd(RECT &rect);
//Variables define in AppInfo.h
HRGN rgnMain, rgnCaptionbar;
bool _APPRUNNING = true;
const char _APPTITLE[] = "Dark";
//Variables
bool WIREFRAME = false;
//Pointers to buttons (singelton design)
btnCloseClass * btnCloseClass::s_Instance = 0;
btnMaximizeClass * btnMaximizeClass::s_Instance = 0;
btnMinimizeClass * btnMinimizeClass::s_Instance = 0;
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONDBLCLK: //Left mouse button double-clicked
Mouse.CheckDblClick(hWnd, wParam);
Mouse.m_Pressed = false;
break;
case WM_LBUTTONDOWN: //Left mouse button clicked
//Update the mouse position variables
GetCursorPos(&Mouse.prevPt);
GetCursorPos(&Mouse.m_LastClick);
Mouse.m_Pressed = true;
Mouse.CheckClickDown(hWnd);
break;
case WM_LBUTTONUP: //Left mouse button released
{
GetCursorPos(&Mouse.prevPt);
Mouse.CheckClickUp(hWnd);
Mouse.m_Pressed = false;
}
break;
case WM_SIZE: //Check if the window has been resized
{
DeleteObject(rgnMain);
DeleteObject(rgnCaptionbar);
//Update the buttons
btnClose->Update(hWnd);
btnMaximize->Update(hWnd);
btnMinimize->Update(hWnd);
//Update the regions
RECT rect; GetWindowRect(hWnd, &rect);
rgnMain = CreateRectRgn(0, 0, rect.right - rect.left, rect.bottom- rect.top);
rgnCaptionbar = CreateRectRgn(0, 0, rect.right - rect.left, CAPTIONBAR_HEIGHT);
}
break;
case WM_PAINT: //Draw the window
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hBrush;
hdc = BeginPaint(hWnd, &ps);
//Color the mainregion
hBrush = CreateSolidBrush(COLOR_MAIN);
FillRgn(hdc, rgnMain, hBrush);
DeleteObject(hBrush);
//Color the captionbarregion
hBrush = CreateSolidBrush(COLOR_CAPTIONBAR);
FillRgn(hdc, rgnCaptionbar, hBrush);
DeleteObject(hBrush);
//Color the button backgrounds
FillRgn(hdc, btnClose->GetRegion(), btnClose->GetBrush());
FillRgn(hdc, btnMinimize->GetRegion(), btnMinimize->GetBrush());
FillRgn(hdc, btnMaximize->GetRegion(), btnMaximize->GetBrush());
//Color the button icons
FillRgn(hdc, btnClose->GetIcon(), btnClose->GetBrushIcon());
FillRgn(hdc, btnMinimize->GetIcon(), btnMinimize->GetBrushIcon());
FillRgn(hdc, btnMaximize->GetIcon(), btnMaximize->GetBrushIcon());
//Paint the wireframe
if (WIREFRAME)
{
hBrush = CreateSolidBrush(COLOR_WIREFRAME);
FrameRgn(hdc, rgnMain, hBrush, 1, 1);
FrameRgn(hdc, rgnCaptionbar, hBrush, 1, 1);
FrameRgn(hdc, btnClose->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnMaximize->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnMinimize->GetRegion(), hBrush, 1, 1);
FrameRgn(hdc, btnClose->GetIcon(), hBrush, 1, 1);
FrameRgn(hdc, btnMaximize->GetIcon(), hBrush, 1, 1);
FrameRgn(hdc, btnMinimize->GetIcon(), hBrush, 1, 1);
DeleteObject(hBrush);
}
//Free up memomry
DeleteObject(hBrush);
EndPaint(hWnd, &ps);
}
break;
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_TAB: //If TAB is pressed
{
if (WIREFRAME) //Activate the wireframe
WIREFRAME = false;
else
WIREFRAME = true;
InvalidateRgn(hWnd, NULL, true);
}
break;
case VK_ESCAPE: //If the ESCAPE is pressed
PostMessage(hWnd, WM_DESTROY, 0, 0);
break;
}
}
break;
case WM_DESTROY: //Free up memory and exit the program
_APPRUNNING = false;
DeleteObject(rgnMain);
DeleteObject(rgnCaptionbar);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
break;
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;
_APPRUNNING = true;
//Register the main window
if (!MainRegister())
{
MessageBox(hWnd, "Error registering main window!", "Error", MB_ICONERROR);
return false;
}
//Initialize the main window
MainInit(hWnd, nCmdShow);
//App-loop
while (_APPRUNNING)
{
if ((GetKeyState(VK_LBUTTON) & 0x80) == 0) //Make sure the mouse's status gets updated
{
Mouse.m_Pressed = false;
}
Mouse.Update(hWnd);
//Message-loop
if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
bool MainInit(HWND &hWnd, int nCmdShow)
{
//Create the window
hWnd = CreateWindowEx(
WS_EX_LAYERED,
_APPTITLE,
_APPTITLE,
WS_OVERLAPPEDWINDOW,
0, 0, //Starting positons (x,y)
START_WIDTH, START_HEIGHT, //Width and height
NULL, //Parent-handle
NULL, //Menu-handle
GetModuleHandle(NULL),
NULL);
//Make sure the window was created properly
if (hWnd == NULL)
{
MessageBox(hWnd, "Error initializing main window!", "Error!", MB_ICONERROR);
return false;
}
SetLayeredWindowAttributes(hWnd, NULL, NULL, NULL);
//Get and set the window's style
DWORD wndStyle = GetWindowLong(hWnd, GWL_STYLE);
wndStyle &= ~(WS_CAPTION | WS_SIZEBOX);
SetWindowLong(hWnd, GWL_STYLE, wndStyle);
//Create regions
rgnMain = CreateRectRgn(0, 0, START_WIDTH, START_HEIGHT);
rgnCaptionbar = CreateRectRgn(0, 0, START_WIDTH, CAPTIONBAR_HEIGHT);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return true;
}
ATOM MainRegister()
{
//Create the window's classEx (extended class)
WNDCLASSEX wc;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hInstance = GetModuleHandle(NULL);
wc.lpfnWndProc = MainWndProc;
wc.lpszClassName = _APPTITLE;
wc.lpszMenuName = NULL;
wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
//Register the classEx
return RegisterClassEx(&wc);
}
//Button.h
//Header file for the class responsible for handling the memory of the
//regions and brushes
class Button
{
protected:
//Protected default constructor
Button();
//Protected default destructor
~Button();
//Protected variables
HRGN m_Rgn;
HRGN m_Icon;
HBRUSH m_hBrush;
HBRUSH m_hBrush_Icon;
bool m_Hovered;
public:
//Public functions
virtual void CreateIcon() = 0;
virtual void Update(HWND hWnd) = 0;
bool Clicked(POINT pt);
bool CheckIfHovered(HWND hWnd);
HRGN GetRegion() { return m_Rgn; }
HRGN GetIcon() { return m_Icon; }
HBRUSH GetBrush() { return m_hBrush; }
HBRUSH GetBrushIcon() { return m_hBrush_Icon; }
};
//Button.cpp
//Default constructor
Button::Button()
{
m_hBrush = CreateSolidBrush(COLOR_BUTTON_BACKGROUND);
m_hBrush_Icon = CreateSolidBrush(COLOR_BUTTON_ICON);
m_Hovered = false;
}
//Default destructor
Button::~Button()
{
//Free up memory
DeleteObject(m_Rgn);
DeleteObject(m_Icon);
DeleteObject(m_hBrush);
DeleteObject(m_hBrush_Icon);
}
Again, thanks to #CodyGray #theB and #AdrianMcCarthy !

Related

Drawing a semi-transparent rectangle in a transparent window

I found this code in stackoverflow and it really draws a rectangle on a transparent window using a bitmap. But somehow I cannot change the transparency of the rectangle. More precisely, I can, but it gets darker. As if the bitmap itself has a black background. How do I make the rectangle transparent?
void paintRect(HDC hdc, RECT dim, COLORREF penCol, COLORREF brushCol, int opacity)
{
HDC tempHDC = CreateCompatibleDC(hdc);
BITMAPINFO bitmapInfo;
ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = dim.right - dim.left;
bitmapInfo.bmiHeader.biHeight = dim.bottom - dim.top;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = (dim.right - dim.left) * (dim.bottom - dim.top) * 4;
HBITMAP hBitmap = CreateDIBSection(tempHDC, &bitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0x0);
SelectObject(tempHDC, hBitmap);
SetDCPenColor(tempHDC, RGB(0, 0, 255));
SetDCBrushColor(tempHDC, RGB(0, 0, 255));
FillRect(tempHDC, &dim, CreateSolidBrush(RGB(0, 0, 255)));
BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
AlphaBlend(hdc, dim.left, dim.top, dim.right, dim.bottom, tempHDC, dim.left, dim.top, dim.right, dim.bottom, blend);
}
Full code
#include <Windows.h>
int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
LRESULT CALLBACK windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
WNDCLASS windowClass {};
windowClass.lpfnWndProc = windowProc;
windowClass.hInstance = hInstance;
windowClass.lpszClassName = L"Keystrokes";
windowClass.style = CS_NOCLOSE;
windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClass(&windowClass))
{
return 0;
}
HWND hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, L"Keystrokes", L"Keystrokes", WS_POPUP, 0, 0, 148, 140, 0, 0, hInstance, 0);
if (!hwnd)
{
return 0;
}
SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 0, LWA_COLORKEY);
ShowWindow(hwnd, nCmdShow);
MSG msg {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
void paintRect(HDC hdc, RECT dim, COLORREF penCol, COLORREF brushCol, int opacity)
{
HDC tempHDC = CreateCompatibleDC(hdc);
BITMAPINFO bitmapInfo;
ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = dim.right - dim.left;
bitmapInfo.bmiHeader.biHeight = dim.bottom - dim.top;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = (dim.right - dim.left) * (dim.bottom - dim.top) * 4;
HBITMAP hBitmap = CreateDIBSection(tempHDC, &bitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0x0);
SelectObject(tempHDC, hBitmap);
SetDCPenColor(tempHDC, RGB(0, 0, 255));
SetDCBrushColor(tempHDC, RGB(0, 0, 255));
FillRect(tempHDC, &dim, CreateSolidBrush(RGB(0, 0, 255)));
BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
AlphaBlend(hdc, dim.left, dim.top, dim.right, dim.bottom, tempHDC, dim.left, dim.top, dim.right, dim.bottom, blend);
}
LRESULT CALLBACK windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_LBUTTONDOWN:
{
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}
break;
case WM_MBUTTONDOWN:
{
PostQuitMessage(0);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hwnd, &ps);
paintRect(hDC, { 0, 0, 48, 48 }, RGB(255, 0, 0), RGB(255, 255, 255), 255);
EndPaint(hwnd, &ps);
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
“As if the bitmap itself has a black background.”
Because your background is set to:
windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
Of course you can set it to NULL_BRUSH to make it look transparent:
windowClass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
But when you move it, you will find that this is not to make the window transparent, but to stop drawing the background:
As #Ben answers here:
You haven't made the window transparent, you have just stopped drawing the background. What you see as the background is just whatever happened to be underneath the window when it was first drawn.
And you need to refer to Layered Windows
You can't add rectangles directly on the window, you should use a layered window, and then add what you need.
Here is a sample that you can refer to it:
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR szCmdLine, _In_ int iCmdShow)
{
static TCHAR szAppName[] = TEXT("test window");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
}
hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, szAppName,
TEXT("the hello program"),
WS_POPUP,
CW_USEDEFAULT,
CW_USEDEFAULT,
148,
148,
NULL,
NULL,
hInstance,
NULL);
SetLayeredWindowAttributes(hwnd, 0, 1, LWA_ALPHA);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return msg.wParam;
}
VOID FadeRect(RECT* prc, HDC hdc)
{
BOOL fFade = FALSE;
static HWND hwnd;
SIZE size;
POINT ptSrc = { 0, 0 };
BLENDFUNCTION blend;
SystemParametersInfo(SPI_GETSELECTIONFADE, 0, &fFade, 0);
if (!fFade)
return;
if (!hwnd) hwnd = CreateWindowEx(WS_EX_LAYERED |
WS_EX_TRANSPARENT |
WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
L"static", L"static", WS_POPUP | WS_VISIBLE, prc->left,
prc->top, prc->right, prc->bottom, NULL, (HMENU)0, NULL, NULL);
else MoveWindow(hwnd, prc->left, prc->top, prc->right, prc->bottom, TRUE);
RECT rect{ prc->left,prc->top,prc->right,prc->bottom };
size.cx = prc->right - prc->left;
size.cy = prc->bottom - prc->top;
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.AlphaFormat = 0;
blend.SourceConstantAlpha = 150;
UpdateLayeredWindow(hwnd, NULL, NULL, &size, hdc, &ptSrc, 0,
&blend, ULW_ALPHA);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
{
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
InvalidateRect(hwnd, NULL, TRUE);
}
break;
case WM_MBUTTONDOWN:
{
PostQuitMessage(0);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rect;
GetClientRect(hwnd, &rect);
MapWindowPoints(hwnd, GetParent(hwnd), (LPPOINT)&rect, 2);
HDC hDC = BeginPaint(hwnd, &ps);
RECT rc{ rect.left,rect.top,rect.left + 48,rect.top + 48 };
FadeRect(&rc, hDC);
EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

WM_POPUP on resize cutting of drawn border

I have a window that i'm trying to draw everything in my self, including title bar, borders.
My problem is that when i drag my window from the bottom right to resize it.
My right/bottom border get cut of when i'm making my window smaller, seems to work fine when dragging it bigger.
If i remove CS_HREDRAW | CS_VREDRAW it just messes up the borders and it all ends up black from where i drag. ( i seen somewhere that it is better to not use these styles to stop flicker)
I'm not sure if im using the correct styles in my window to be able to do what i want here. My end goal is to draw everything in my window including title bar, borders, buttons and all controls.
bool Window::Create(const wchar_t *title, Vector2D size)
{
HINSTANCE instanceHandle = GetModuleHandle(NULL);
if (this->RegisterWindowClass())
{
m_handle = (HWND)CreateWindowEx(0, VERSION, L"", WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, size.m_x, size.m_y, NULL, NULL, instanceHandle, this);
if (m_handle)
{
::ShowWindow(m_handle, SW_SHOW);
}
}
return m_handle != 0;
}
bool Window::RegisterWindowClass(const wchar_t *title)
{
static bool registered = false;
if (!registered)
{
HINSTANCE instanceHandle = GetModuleHandle(NULL);
WNDCLASSEX windowClass;
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = (WNDPROC)Window::WindowProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = instanceHandle;
windowClass.hIcon = NULL;
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = (HBRUSH)(CreateSolidBrush(RGB(60, 60, 60)));//set back color to window
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = title;
windowClass.hIconSm = NULL;
if (RegisterClassEx(&windowClass))
registered = true;
}
return registered;
}
void Draw_LeftRightBottom_Rectangles(HDC hdc, HBRUSH brush, RECT rect, int TaskbarHeight)
{
RECT leftrect, rightrect, bottomrect;
leftrect.left = 0;
leftrect.top = TaskbarHeight;
leftrect.right = 2;
leftrect.bottom = rect.bottom;
//fill left rect of window for border
FillRect(hdc, &leftrect, brush);
rightrect.left = rect.right - 2;
rightrect.top = TaskbarHeight;
rightrect.right = rect.right;
rightrect.bottom = rect.bottom;
//fill right rect of window
FillRect(hdc, &rightrect, brush);
bottomrect.left = 0;
bottomrect.top = rect.bottom - 2;
bottomrect.right = rect.right;
bottomrect.bottom = rect.bottom;
//fill bottom rect of window
FillRect(hdc, &bottomrect, brush);
}
LRESULT Window::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static int X, Y;
Window* pThis;
if (uMsg == WM_NCCREATE)
{
pThis = static_cast<Window*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams);
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pThis));
}
else
pThis = reinterpret_cast<Window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
if (pThis != 0)
{
switch (uMsg)
{
case WM_PAINT:
{
RECT clientArea;
GetClientRect(hwnd, &clientArea);
PAINTSTRUCT ps;
if (BeginPaint(hwnd, &ps))
{
//Creating double buffer
HDC hdcMem = CreateCompatibleDC(ps.hdc);
int ndcmem = SaveDC(hdcMem);
HBITMAP hbmMem = CreateCompatibleBitmap(ps.hdc, X, Y);
SelectObject(hdcMem, hbmMem);
//-------------------------------------------------------
// Copy background bitmap into double buffer
BitBlt(hdcMem, 0, 0, clientArea.right, clientArea.bottom, ps.hdc, 0, 0, SRCCOPY);
//---------------------------------------------------------
RECT rect;
rect.bottom = 25;
rect.right = clientArea.right;
HBRUSH brush = CreateSolidBrush(RGB(0, 0, 0));
// Draw Titlebar
FillRect(hdcMem, &rect, brush);
Draw_LeftRightBottom_Rectangles(hdcMem, brush, clientArea, 25);
DeleteObject(brush);
//-----------------------------------------------------------------------------
// Copy double buffer to screen
BitBlt(ps.hdc, 0, 0, X, Y, hdcMem, 0, 0, SRCCOPY);
//--------------------------------------------------
// Clean up
RestoreDC(hdcMem, ndcmem);
DeleteObject(hbmMem);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
//--------------------
}
return 0;;
}
case WM_SIZE:
{
X = LOWORD(lParam);
Y = HIWORD(lParam);
break;
}
case WM_NCHITTEST:
{
POINT pt;
RECT rc;
GetClientRect(hwnd, &rc);
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
ScreenToClient(hwnd, &pt);
if (pt.y > (rc.bottom - BORDERWIDTH))
{
if (pt.x>(rc.right - BORDERWIDTH))
{
return HTBOTTOMRIGHT;
}
}
if (pt.y < 25)
{
return HTCAPTION;
}
break;
}
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

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

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.