WM_POPUP on resize cutting of drawn border - c++

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

Related

c++ windows.h memory increse

hellow for some reson when i move mouse in window made in
windows.h allocated memory increse, pls help,
and also when mouse is moving screen blink
................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
code:
#include <Windows.h>
#include <windowsx.h>
#include <iostream>
#include <WinUser.h>
void DrawTirangle(HWND hwnd, POINT vertices[], int r, int g, int b) {
HDC hdc = GetDC(hwnd);
HPEN hPen = CreatePen(PS_SOLID, 2, RGB(r, g, b));
HPEN hOldPen = SelectPen(hdc, hPen);
HBRUSH hBrush = CreateSolidBrush(RGB(r, g, b));
HBRUSH hOldBrush = SelectBrush(hdc, hBrush);
POINT verticesx[] = { {vertices[0].x, vertices[0].y}, {vertices[1].x, vertices[1].y}, {vertices[2].x, vertices[2].y} };
Polygon(hdc, verticesx, sizeof(verticesx) / sizeof(verticesx[0]));
SelectBrush(hdc, hOldBrush);
DeleteObject(hBrush);
SelectPen(hdc, hOldPen);
DeleteObject(hPen);
}
#include "sys.h"
LRESULT CALLBACK ScreenProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) {
switch (uMsg)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
HDC hDC = GetDC(hWnd);
RECT rect;
GetWindowRect(hWnd, &rect);
PatBlt(hDC, 0, 0, rect.right, rect.bottom, BLACKNESS);
ReleaseDC(hWnd, hDC);
renderer(hWnd);
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
void ClearBuffer(HWND hwnd, RECT screenDef) {
HDC hdc = GetDC(hwnd);
HPEN hPen = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
HPEN hOldPen = SelectPen(hdc, hPen);
HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));
HBRUSH hOldBrush = SelectBrush(hdc, hBrush);
POINT vertices1[] = { {0, 0}, {0, screenDef.bottom}, {screenDef.right + 80, screenDef.bottom},{screenDef.right,0} };
Polygon(hdc, vertices1, sizeof(vertices1) / sizeof(vertices1[0]));
SelectBrush(hdc, hOldBrush);
DeleteObject(hBrush);
SelectPen(hdc, hOldPen);
DeleteObject(hPen);
}
class SCREEN {
public:
SCREEN()
: m_hInstance(GetModuleHandle(nullptr))
{
const wchar_t* CLASS_NAME = L"x64 PxOS";
WNDCLASS wndClass = {};
wndClass.lpszClassName = CLASS_NAME;
wndClass.hInstance = m_hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wndClass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndClass.lpfnWndProc = ScreenProc;
RegisterClass(&wndClass);
DWORD style = WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
int w = 640;
int h = 480;
RECT rect;
rect.left = 250;
rect.top = 250;
rect.right = rect.left + w;
rect.bottom = rect.top + h;
screenDef.left = rect.left;
screenDef.top = rect.top;
screenDef.right = rect.right;
screenDef.bottom = rect.bottom;
AdjustWindowRect(&rect, style, false);
mainBuffer = CreateWindowEx(
0,
CLASS_NAME,
L"x64 PxOS",
style,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
NULL,
NULL,
m_hInstance,
NULL
);
ShowWindow(mainBuffer, SW_SHOW);
OldBuffer = mainBuffer;
OldBuffer1 = mainBuffer;
ClearBufferI = mainBuffer;
ClearBuffer(ClearBufferI, screenDef);
screenDefI = screenDef;
}
SCREEN(const SCREEN&) = delete;
SCREEN& operator = (const SCREEN&) = delete;
~SCREEN() {
const wchar_t* CLASS_NAME = L"x64 PxOS";
UnregisterClass(CLASS_NAME,m_hInstance);
}
bool ProcessMessages() {
MSG msg = {};
while (PeekMessage(&msg,nullptr,0u,0u,PM_REMOVE))
{
if (msg.message == WM_QUIT) {
return false;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return true;
}
HINSTANCE m_hInstance;
void SwapBuffers() {
/*if (bs == 1) {
bs = 2;
mainBuffer = OldBuffer;
}
else if(bs == 2) {
bs = 1;
mainBuffer = OldBuffer1;
}*/
}
HWND mainBuffer;
HWND OldBuffer;
HWND OldBuffer1;
HWND ClearBufferI;
int bs = 1;
RECT screenDef;
RECT screenDefI;
};
You are missing ReleaseDC for every GetDC.
You should only paint your window in response to WM_PAINT by calling BeginPaint/EndPaint.

How to increase bitmap pixel size? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I'm struggling to find the way to increase pixel sizes in a win32 bitmap. Is there any way to do it?
I made a small win32 program below. When you run it, you should get a window with a very tiny red dot in the center. You can use up, down, left, and right arrow keys to control the dot.
/* compile: gcc test.c -o test -lgdi32 -Wl,-subsystem,windows */
// TODO fast way to update? resize pixel size? best coding practices?
#include <windows.h>
#define WND_WIDTH 500
#define WND_HEIGHT 500
#define ID_TIMER 1
void DrawBitmap(HDC hdc, RECT *rect, BITMAPINFO info, void *bmpMem)
{
int width = rect->right - rect->left;
int height = rect->bottom - rect->top;
StretchDIBits(hdc,
0,
0,
info.bmiHeader.biWidth,
info.bmiHeader.biHeight,
0,
0,
width,
height,
bmpMem,
&info,
DIB_RGB_COLORS,
SRCCOPY);
}
void UpdateBitmap(BITMAPINFO info, void *bmpMem, POINT pix)
{
int width = info.bmiHeader.biWidth;
int height = info.bmiHeader.biHeight;
BYTE *pixel = (BYTE *) bmpMem;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (x == pix.x && y == pix.y)
{
*pixel++ = 0; /* blue */
*pixel++ = 0; /* green */
*pixel++ = 255; /* red */
*pixel++ = 255; /* alpha */
}
else
{
*pixel++ = 0; /* blue */
*pixel++ = 0; /* green */
*pixel++ = 0; /* red */
*pixel++ = 255; /* alpha */
}
}
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static BITMAPINFO info;
static void *bmpMem;
static POINT pixel;
switch (msg)
{
case WM_CREATE:
{
RECT rcClient;
GetClientRect(hWnd, &rcClient);
int width = rcClient.right - rcClient.left;
int height = rcClient.bottom - rcClient.top;
info.bmiHeader.biSize = sizeof(info.bmiHeader);
info.bmiHeader.biWidth = width;
info.bmiHeader.biHeight = height;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 32;
info.bmiHeader.biCompression = BI_RGB;
info.bmiHeader.biSizeImage = 0;
info.bmiHeader.biXPelsPerMeter = 0;
info.bmiHeader.biYPelsPerMeter = 0;
info.bmiHeader.biClrUsed = 0;
info.bmiHeader.biClrImportant = 0;
bmpMem = VirtualAlloc(0, width * height * 4, MEM_COMMIT, PAGE_READWRITE);
pixel.x = width / 2;
pixel.y = height / 2;
if(!SetTimer(hWnd, ID_TIMER, 50, NULL))
{
MessageBox(hWnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);
PostQuitMessage(1);
}
break;
}/*
case WM_PAINT:
{
RECT rcClient;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rcClient);
DrawBitmap(hdc, &rcClient, info, bmpMem);
EndPaint(hWnd, &ps);
break;
}*/
case WM_TIMER:
{
RECT rcClient;
HDC hdc = GetDC(hWnd);
GetClientRect(hWnd, &rcClient);
UpdateBitmap(info, bmpMem, pixel);
DrawBitmap(hdc, &rcClient, info, bmpMem);
ReleaseDC(hWnd, hdc);
break;
}
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_LEFT: pixel.x -= 1; break;
case VK_RIGHT: pixel.x += 1; break;
case VK_UP: pixel.y += 1; break;
case VK_DOWN: pixel.y -= 1; break;
}
break;
}
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
KillTimer(hWnd, ID_TIMER);
VirtualFree(bmpMem, 0, MEM_RELEASE);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
const TCHAR szClassName[] = TEXT("MyClass");
WNDCLASS wc;
HWND hWnd;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
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 = szClassName;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClass(&wc))
{
MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
MB_ICONEXCLAMATION | MB_OK);
return 1;
}
hWnd = CreateWindow(szClassName,
TEXT("Title"),
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, /* this window style prevents window resizing */
CW_USEDEFAULT,
CW_USEDEFAULT,
WND_WIDTH,
WND_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
if (hWnd == NULL)
{
MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
MB_ICONEXCLAMATION | MB_OK);
return 1;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
I want to increase the size of the tiny red dot and all other pixels in the bitmap. I tried to decrease the width and height like this
switch (msg)
{
case WM_CREATE:
{
//RECT rcClient;
//GetClientRect(hWnd, &rcClient);
int width = 30;
int height = 30;
I expected to see a big red dot at the center but I got the white screen instead. How can I edit the code to display bigger pixels?
You are creating a single red pixel in your UpdateBitmap:
if (x == pix.x && y == pix.y)
{
*pixel++ = 0; /* blue */
*pixel++ = 0; /* green */
*pixel++ = 255; /* red */
*pixel++ = 255; /* alpha */
}
If you want a bigger "dot" - define a radius somewhere:
int r = 17;
and change your condition to
if ((x - pix.x)* (x - pix.x) + (y - pix.y)* (y - pix.y) <= r*r)
To scale the entire bitmap, modify DrawBitmap:
void DrawBitmap(HDC hdc, RECT* rect, BITMAPINFO info, void* bmpMem)
{
int width = rect->right - rect->left;
int height = rect->bottom - rect->top;
int scale = 7;
StretchDIBits(hdc,
-(info.bmiHeader.biWidth * scale - width) / 2,
-(info.bmiHeader.biHeight * scale - height) / 2,
info.bmiHeader.biWidth * scale,
info.bmiHeader.biHeight * scale,
0,
0,
width,
height,
bmpMem,
&info,
DIB_RGB_COLORS,
SRCCOPY);
}
StretchDIBits will stretch (or shrink) the area of the source (specified by 0, 0, width, height) into some are of the destination.
In this example, I magnified the size of the destination by the factor of scale - so the image will stretch. The negative offset is to "center" the image over destination; you can use 0,0 to keep the top-left anchor.

Resizing window with Win32 API

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 !

Painted image is always black

I'm trying draw an image within a popup windows. I get the bitmap infos from a stream. That part should be ok, because if I create a file and save the bitmap it looks fine.
The byte array is stored as follows:
static BYTE* _bitampContent;
Here is how I create the window:
static WCHAR name[] = L"Bitmap Display";
HINSTANCE _instance = ::GetModuleHandle(NULL);
HWND hWnd;
MSG msg;
WNDCLASS wndClass;
wndClass.style = 0;
wndClass.lpfnWndProc = class::_WindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hInstance = _instance;
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = name;
if (RegisterClass(&wndClass) == 0)
{
MessageBox(0, L"The Window is not registered", L"Message", MB_OK);
return 0;
}
RECT rc;
GetWindowRect(hwndOwner, &rc);
int xPos = (GetSystemMetrics(SM_CXSCREEN) - rc.right) / 2;
int yPos = (GetSystemMetrics(SM_CYSCREEN) - rc.bottom) / 2;
hWnd = CreateWindowEx(WS_EX_TOPMOST, name, name, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 200, 200, NULL, NULL, _instance, NULL);
if (hWnd == 0)
{
MessageBox(0, L"hWnd = 0", L"Message", MB_OK);
return 0;
}
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
msg.wParam;
And in the WndProc function a paint the bitmap.
LRESULT CALLBACK class::_WindowProc(HWND hWnd, UINT uMsgId, WPARAM wParam, LPARAM lParam)
{
HBITMAP hbitmap;
BITMAP bitmap;
HDC hdc, hmemdc;
switch (uMsgId)
{
case WM_PAINT:
BITMAPINFOHEADER bmpInfoHeader;
bmpInfoHeader = { 0 };
bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfoHeader.biBitCount = 24;
bmpInfoHeader.biClrImportant = 0;
bmpInfoHeader.biClrUsed = 0;
bmpInfoHeader.biCompression = BI_RGB;
bmpInfoHeader.biHeight = 200;
bmpInfoHeader.biWidth = 200;
bmpInfoHeader.biPlanes = 1;
unsigned long pixel_data_size;
pixel_data_size = 200 * ((200 * (24 / 8)));
bmpInfoHeader.biSizeImage = pixel_data_size;
BITMAPINFO dbmi;
ZeroMemory(&dbmi, sizeof(dbmi));
dbmi.bmiHeader = bmpInfoHeader;
dbmi.bmiColors->rgbBlue = 0;
dbmi.bmiColors->rgbGreen = 0;
dbmi.bmiColors->rgbRed = 0;
dbmi.bmiColors->rgbReserved = 0;
void* bits;
bits = NULL;
hbitmap = CreateDIBSection(NULL, &dbmi, DIB_RGB_COLORS, &bits, NULL, 0);
if (hbitmap == NULL) {
MessageBox(NULL, L"Bitmap not loaded", L"Error", MB_OK);
return 0;
}
GdiFlush();
// copy pixels into DIB.
memcpy(bits, _bitampContent, sizeof(_bitampContent));
GetObject(hbitmap, sizeof(BITMAP), &bitmap);
PAINTSTRUCT paintStruct;
hdc = BeginPaint(hWnd, &paintStruct);
hmemdc = CreateCompatibleDC(hdc);
SelectObject(hmemdc, hbitmap);
BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hmemdc, 0, 0, SRCCOPY);
DeleteObject(hbitmap);
EndPaint(hWnd, &paintStruct);
return 0;
My problem is now, that the painted image is always black. I assume that this behavior has something to do with the DC's but I don't know exactly what.
What do I need to change?

OpenGL Flashing?

I'm trying to draw some text in OpenGL while the program draw a cube or any Opengl native so, when I try to put the text on the screen it flashes very fast and I don't know why, I tried to change the Sleep value and nothing...
The code is below; here is a GIF showing the problem.
The green background is the cube, the camera is very close to the background, you can move back with the NUM_2.
#include <windows.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include "default.h"
using namespace std;
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
DWORD WINAPI WorkLoop(LPVOID PARAMS);
void keyScan (MSG msg, Camera cam);
HDC hDC;
HGLRC hRC;
HWND hwnd;
RECT WBounds;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;
MSG msg;
BOOL bQuit = FALSE;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_OWNDC;
wcex.lpfnWndProc = WindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "GLSample";
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);;
Screen ();
if (!RegisterClassEx(&wcex))
return 0;
hwnd = CreateWindowEx(0,
"GLSample",
"OpenGL Testing",
WS_OVERLAPPEDWINDOW,
Scr.sx/2-630,
Scr.sy/2-450,
1260,
900,
NULL,
NULL,
hInstance,
NULL);
GetClientRect(hwnd, &WBounds);
ShowWindow(hwnd, nCmdShow);
EnableOpenGL(hwnd, &hDC, &hRC); ///ENABLE OPENGL
Camera cam = Camera (0, 0, -1);
CreateThread(0, 0x1000, &WorkLoop, 0, 0, 0);
while (!bQuit)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT) bQuit = TRUE;
else
{
keyScan (msg, cam);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
renderSimulation (cam);
SwapBuffers (hDC);
}
Sleep(1);
}
DisableOpenGL(hwnd, hDC, hRC);
DestroyWindow(hwnd);
return msg.wParam;
}
DWORD WINAPI WorkLoop(LPVOID PARAMS)
{
while (true)
{
InvalidateRect(hwnd, &WBounds, true);
Sleep(33);
}
ExitThread(0);
}
float x = 0.0f, y = 0.0f, z = 0.0f;
float rx = 0.0f, ry = 0.0f, rz = 0.0f;
char* textas = "test";
void keyScan (MSG p, Camera cam)
{
if (p.message == WM_KEYDOWN)
{
if (p.wParam == ARROW_RIGHT) {x += 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == ARROW_LEFT) {x -= 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == ARROW_UP) {y += 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == ARROW_DOWN) {y -= 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == NUM_8) {z += 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == NUM_2) {z -= 0.1; cam.SetCameraPosition (x, y, z);}
else if (p.wParam == L) SetFullScreen (p.hwnd, hDC, hRC);
else if (p.wParam == K) textas = "cambiado";
}
}
HFONT Font = CreateFont(40, 0, 0, 0,FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY, FF_MODERN, TEXT("Arial"));
HPEN BoxPen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));
HPEN OutlinePen = CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
HPEN CHPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
HBRUSH CHBrush = CreateSolidBrush(RGB(0, 255, 0));
void drawtext(HDC hdc, int x, int y, const char * text)
{
SetBkMode (hdc, TRANSPARENT);
SetTextColor(hdc, RGB(0, 255, 0));
SetBkColor(hdc, RGB(255, 255, 255));
TextOutA(hdc, x, y, text, strlen(text));
}
/*void Draw(HDC hdc, int x, int y, float dist)
{
int width = 20000 / dist;
int height = 45000 / dist;
SelectObject(hdc, OutlinePen);
SelectObject(hdc, WHITE_BRUSH);
Rectangle(hdc, x - (width / 2), y - height, x + (width / 2), y);
SelectObject(hdc, BoxPen);
Rectangle(hdc, x - (width / 2), y - height, x + (width / 2), y);
SetTextAlign(hdc, TA_CENTER | TA_NOUPDATECP);
std::stringstream ss2;
ss2 << "Dist: " << dist << " m";
drawtext(hdc, x, y + 90, ss2.str().c_str());
}*/
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_PAINT:
{
int win_width = WBounds.right - WBounds.left;
int win_height = WBounds.bottom + WBounds.left;
PAINTSTRUCT ps;
HDC Memhdc;
HDC hdc;
HBITMAP Membitmap;
hdc = BeginPaint(hwnd, &ps);
Memhdc = CreateCompatibleDC (hdc);
Membitmap = CreateCompatibleBitmap (hdc, win_width, win_height);
SelectObject (Memhdc, Membitmap);
//FillRect (Memhdc, &WBounds, WHITE_BRUSH);
SelectObject (Memhdc, Font);
SetTextAlign (Memhdc, TA_LEFT | TA_NOUPDATECP);
drawtext(Memhdc, 100, 100, textas);
//Draw (Memhdc, 20, 50, 90.0);
/*SelectObject(Memhdc, CHPen);
SelectObject(Memhdc, CHBrush);*/
BitBlt (hdc, 0, 0, win_width, win_height, Memhdc, 0, 0, SRCCOPY);
DeleteObject(Membitmap);
DeleteDC(Memhdc);
DeleteDC(hdc);
EndPaint(hwnd, &ps);
ValidateRect(hwnd, &WBounds);
}
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_ESCAPE:
PostQuitMessage(0);
}
}
case WM_ERASEBKGND:
return 1;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
Two problems with your program:
Setting a background brush for a OpenGL window will make the OS visibly clear the window with the brush before sending WM_PAINT (upon which you overdraw with OpenGL). By using InvalidateRect you're triggering this erase-with-background before WM_PAINT
Double buffered OpenGL pixelformats and drawing with the GDI don't go well together. If you want to draw text you'll have to do it differently. For example drawing to a DIBSECTION DC and then drawing that bitmap per using a textured quad. Or using a font rasterizer that addresses OpenGL (FTGL, Glyphy or the likes).