c++ windows.h memory increse - c++

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.

Related

Can't draw on custom window frame with DWM

I have created a custom window frame using DWM. The frame extends successfully but whenever I try to draw onto the frame, the extended frame coveres whatever I am trying to draw. I have seen other people try to input a top left within negative bounds, but even when I try to do that, the title bar still overlaps the main window's painting. Here is my code (note: i don't have any code for hit testing):
#include <Windows.h>
#include <numeric>
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
const auto s_brush = CreateSolidBrush(RGB(0, 0, 255));
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
LRESULT res;
if (DwmDefWindowProc(hwnd, msg, wparam, lparam, &res))
return res;
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
{
RECT r;
GetWindowRect(hwnd, &r);
SetWindowPos(hwnd, 0, 0, 0, r.right - r.left, r.bottom - r.top, SWP_FRAMECHANGED);
}
break;
case WM_ACTIVATE:
{
int metrics[4];
const auto window_dpi_ = GetDpiForWindow(hwnd);
metrics[0] = GetSystemMetricsForDpi(SM_CYCAPTION, window_dpi_);
metrics[1] = GetSystemMetricsForDpi(SM_CXFIXEDFRAME, window_dpi_);
metrics[2] = GetSystemMetricsForDpi(SM_CYSIZEFRAME, window_dpi_);
metrics[3] = GetSystemMetricsForDpi(SM_CYBORDER, window_dpi_);
const auto cy_titlebar_ = std::accumulate(metrics, metrics + sizeof metrics / sizeof(int), 0);
MARGINS margins{ 0, 0, cy_titlebar_, 0 };
DwmExtendFrameIntoClientArea(hwnd, &margins);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
const auto hdc = BeginPaint(hwnd, &ps);
const auto old = SelectObject(hdc, s_brush);
Rectangle(hdc, 0, 0, 50, 75);
SelectObject(hdc, old);
EndPaint(hwnd, &ps);
}
break;
case WM_NCCALCSIZE:
if (wparam == TRUE)
{
RECT& client_rect = reinterpret_cast<LPNCCALCSIZE_PARAMS>(lparam)->rgrc[0];
const auto window_dpi_ = GetDpiForWindow(hwnd);
const auto frame_width{ GetSystemMetricsForDpi(SM_CXFRAME, window_dpi_) };
const auto border_width{ GetSystemMetricsForDpi(SM_CXPADDEDBORDER, window_dpi_) };
const auto frame_height{ GetSystemMetricsForDpi(SM_CYFRAME, window_dpi_) };
client_rect.bottom -= frame_height + border_width;
client_rect.left += frame_width + border_width;
client_rect.right -= frame_width + border_width;
break;
}
default:
return DefWindowProcW(hwnd, msg, wparam, lparam);
}
return 0;
}
int WINAPI wWinMain(HINSTANCE hinstance, HINSTANCE, LPWSTR lpcmdline, int cmd_show)
{
WNDCLASS wc{ CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hinstance,
0,0, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)), 0, L"CustWnd" };
const auto hwnd = CreateWindow(MAKEINTATOM(RegisterClass(&wc)), L"Custom Window Frame", WS_OVERLAPPEDWINDOW,
0, 0, 500, 700, 0, 0, hinstance, 0);
ShowWindow(hwnd, cmd_show);
UpdateWindow(hwnd);
MSG msg;
while (GetMessageW(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}
The window class doesn't have a default cursor, it's going to show the wrong cursors as you move the mouse. Change wc to
WNDCLASS wc{ CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hinstance, 0,
LoadCursor(NULL, IDC_ARROW),
reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)), 0, L"CustWnd" };
WM_NCHITTEST should also be handled, otherwise title-bar will not grip. It is better to calculate the border thickness based on Windows style, or keep it as static value because it will be needed throughout the procedure, as well as title bar height.
Note that this code will look very different in Windows 10 versus Window 7 which has the weird transparent title-bar, you'll need 32-bit bitmap with alpha channel to draw on title-bar. Or use buffered paint with BufferedPaintSetAlpha as shown below
#include <Windows.h>
#include <Windowsx.h> //for `GET_X_LPARAM` etc.
...
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static int cy_titlebar_ = 100;
static RECT border_thickness;
LRESULT result;
if(DwmDefWindowProc(hWnd, msg, wParam, lParam, &result))
return result;
switch(msg)
{
case WM_CREATE:
{
//find border thickness
border_thickness = { 0 };
if(GetWindowLongPtr(hWnd, GWL_STYLE) & WS_THICKFRAME)
{
AdjustWindowRectEx(&border_thickness,
GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION, FALSE, NULL);
border_thickness.left *= -1;
border_thickness.top *= -1;
}
else if(GetWindowLongPtr(hWnd, GWL_STYLE) & WS_BORDER)
{
border_thickness = { 1,1,1,1 };
}
MARGINS margins = { 0, 0, cy_titlebar_, 0 };
DwmExtendFrameIntoClientArea(hWnd, &margins);
SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
return 0;
}
case WM_NCCALCSIZE:
{
if(wParam)
{
RECT& r = reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam)->rgrc[0];
r.left += border_thickness.left;
r.right -= border_thickness.right;
r.bottom -= border_thickness.bottom;
return 0;
}
break;
}
case WM_NCHITTEST:
{
result = DefWindowProc(hWnd, msg, wParam, lParam);
if(result == HTCLIENT)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
ScreenToClient(hWnd, &pt);
if(pt.y < border_thickness.top) return HTTOP;
if(pt.y < cy_titlebar_) return HTCAPTION;
}
return result;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
auto hdc = BeginPaint(hWnd, &ps);
//paint opaque:
RECT rc{ 0, 0, 100, cy_titlebar_ };
BP_PAINTPARAMS params = { sizeof(params), BPPF_NOCLIP | BPPF_ERASE };
HDC memdc;
HPAINTBUFFER hbuffer = BeginBufferedPaint(
hdc, &rc, BPBF_TOPDOWNDIB, &params, &memdc);
auto brush = CreateSolidBrush(RGB(255, 0, 0));
FillRect(memdc, &rc, brush);
DeleteObject(brush);
SetBkMode(memdc, TRANSPARENT);
DrawText(memdc, L"Opaque", -1, &rc, 0);
BufferedPaintSetAlpha(hbuffer, &rc, 255);
EndBufferedPaint(hbuffer, TRUE);
EndPaint(hWnd, &ps);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}

Draw border on top of another application window

I'm need to draw border on top another application's window (the main purpose is to highlight window user chooses from running applications list). I'm trying to draw border on top of native window border, but the border isn't drawn. Here is the code:
HPEN framePen = ::CreatePen(PS_SOLID, 5, RGB(255, 0, 0));
HWND handle = FindWindow(L"ConsoleWindowClass", L"C:\\WINDOWS\\system32\\cmd.exe");
WINDOWPLACEMENT winPlacement;
GetWindowPlacement(handle, &winPlacement);
if (winPlacement.showCmd == SW_SHOWMINIMIZED)
{
ShowWindow(handle, SW_RESTORE);
}
SetWindowPos(handle, HWND_TOP, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
SetForegroundWindow(handle);
PAINTSTRUCT ps;
RECT rect = {};
::GetClientRect(handle, &rect);
HDC hdc = ::BeginPaint(handle, &ps);
::SelectObject(hdc, framePen);
::Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
::EndPaint(handle, &ps);
In this example used handle of cmd window, but in fact it doesn't matter.
Could you please tell why border isn't drawn and how to draw it?
Thanks.
You can't draw directly on another window, because the system may refresh the window at any time, overwriting your drawing.
To make your drawing persistent, create a layered window, positioned on top of the other window.
Create the window with WS_EX_LAYERED flag.
Pass a color key to SetLayeredWindowAttributes().
In your WM_PAINT handler, draw the inside of the rectangle with the color key (by using it for the brush). Everything you draw with the color key will become transparent. Draw the border of the rectangle with the desired color (by using it for the pen).
Here is a minimal example to get you started. The frame can be moved around by drag-n-drop.
Note there is no error handling to keep the sample code concise. You should check the return value of each Windows API call.
#include <windows.h>
const COLORREF MY_COLOR_KEY = RGB( 255, 0, 255 );
int APIENTRY wWinMain(
HINSTANCE hInstance, HINSTANCE /*hPrevInst*/, LPWSTR /*lpCmdLine*/, int nCmdShow )
{
WNDCLASSW wc{ sizeof( wc ) };
wc.hInstance = hInstance;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hCursor = LoadCursor( nullptr, IDC_ARROW );
wc.hbrBackground = reinterpret_cast<HBRUSH>( COLOR_BTNFACE + 1 );
wc.lpszClassName = L"MyTransparentFrame";
wc.lpfnWndProc = []( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) -> LRESULT
{
switch( msg )
{
case WM_PAINT:
{
PAINTSTRUCT ps{};
HDC hdc = BeginPaint( hwnd, &ps );
RECT rc{}; GetClientRect( hwnd, &rc );
HPEN hPen = CreatePen( PS_SOLID, 20, GetSysColor( COLOR_HIGHLIGHT ) );
HBRUSH hBrush = CreateSolidBrush( MY_COLOR_KEY );
HGDIOBJ hOldPen = SelectObject( hdc, hPen );
HGDIOBJ hOldBrush = SelectObject( hdc, hBrush );
Rectangle( hdc, rc.left, rc.top, rc.right, rc.bottom );
if( hOldPen )
SelectObject( hdc, hOldPen );
if( hOldBrush )
SelectObject( hdc, hOldBrush );
if( hPen )
DeleteObject( hPen );
if( hBrush )
DeleteObject( hBrush );
EndPaint( hwnd, &ps );
}
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
case WM_NCHITTEST:
return HTCAPTION; // to be able to drag the window around
break;
default:
return DefWindowProcW( hwnd, msg, wp, lp );
}
return 0;
};
RegisterClassW( &wc );
HWND hwnd = CreateWindowExW( WS_EX_LAYERED, wc.lpszClassName, L"", WS_POPUP,
200, 200, 800, 600, nullptr, nullptr, hInstance, nullptr );
SetLayeredWindowAttributes( hwnd, MY_COLOR_KEY, 255, LWA_COLORKEY );
ShowWindow( hwnd, nCmdShow );
MSG msg;
while( GetMessage( &msg, nullptr, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return (int) msg.wParam;
}
Finally I managed to solve the problem with the following code:
const COLORREF MY_COLOR_KEY = RGB(255, 128, 0);
HWND cmdHanlde = NULL;
constexpr unsigned int timerIdWindowUpdate = 1;
constexpr unsigned int timerIdFrameColor = 2;
bool tick = false;
bool minimized = false;
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpszClassName = L"MyTransparentFrame";
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpfnWndProc = [](HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) -> LRESULT
{
switch (msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps{};
HDC hdc = BeginPaint(hwnd, &ps);
RECT rc{}; GetClientRect(hwnd, &rc);
HPEN hPen = CreatePen(PS_SOLID, 5, tick ? RGB(255, 128, 1) : RGB(255, 201, 14));
HBRUSH hBrush = CreateSolidBrush(MY_COLOR_KEY);
HGDIOBJ hOldPen = SelectObject(hdc, hPen);
HGDIOBJ hOldBrush = SelectObject(hdc, hBrush);
Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
if (hOldPen)
SelectObject(hdc, hOldPen);
if (hOldBrush)
SelectObject(hdc, hOldBrush);
if (hPen)
DeleteObject(hPen);
if (hBrush)
DeleteObject(hBrush);
EndPaint(hwnd, &ps);
}
break;
case WM_TIMER:
{
if (wp == timerIdWindowUpdate)
{
WINDOWPLACEMENT windowPlacement = { sizeof(WINDOWPLACEMENT), };
if (::GetWindowPlacement(cmdHanlde, &windowPlacement))
{
if (windowPlacement.showCmd == SW_SHOWMINIMIZED
|| !IsWindowVisible(cmdHanlde))
{
ShowWindow(hwnd, SW_HIDE);
minimized = true;
}
else
{
RECT rect = {};
DwmGetWindowAttribute(cmdHanlde, DWMWA_EXTENDED_FRAME_BOUNDS, &rect, sizeof(rect));
MONITORINFO monInfo;
monInfo.cbSize = sizeof(MONITORINFO);
GetMonitorInfoW(MonitorFromWindow(cmdHanlde, MONITOR_DEFAULTTONEAREST), &monInfo);
if (cmdHanlde != NULL && ::IsZoomed(cmdHanlde))
{
rect.left = monInfo.rcWork.left;
rect.top = monInfo.rcWork.top;
rect.bottom = monInfo.rcWork.bottom > rect.bottom ? rect.bottom : monInfo.rcWork.bottom;
rect.right = monInfo.rcWork.right > rect.right ? rect.right : monInfo.rcWork.right;
}
if (minimized)
{
::SetWindowPos(hwnd, cmdHanlde, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
minimized = false;
}
else
{
::SetWindowPos(cmdHanlde, hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
::SetWindowPos(hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_SHOWWINDOW);
}
}
}
}
else if (wp == timerIdFrameColor)
{
tick = !tick;
::RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hwnd, msg, wp, lp);
}
return 0;
};
RegisterClassEx(&wc);
HWND hwnd = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE | WS_EX_LAYERED | WS_EX_TRANSPARENT, wc.lpszClassName, L"", WS_POPUP | WS_VISIBLE | WS_DISABLED,
0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
::SetTimer(hwnd, timerIdWindowUpdate, 50, NULL);
::SetTimer(hwnd, timerIdFrameColor, 500, NULL);
SetLayeredWindowAttributes(hwnd, MY_COLOR_KEY, 255, LWA_COLORKEY);
ShowWindow(hwnd, SW_SHOW);
cmdHanlde = FindWindow(L"ConsoleWindowClass", L"C:\\WINDOWS\\system32\\cmd.exe");
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
May be it is not the best solution, but it works for me. Could you please take a look on it and tell if there something to improve?

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

draw on transparent window using pen

I want to draw on a transparent window using a pen.
When drawing a line black area surround the line.
This image shows the problem:
How to solve this problem?
LRESULT __stdcall WindowProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc, backDC;
PAINTSTRUCT ps;
static Point prevPt;
// Draw or Erase
static bool isDraw = false;
static bool isErase = false;
// Select Pen Color
static int selectColor = 1;
// Color Pen(R, G, B) and Current Pen
static HPEN redPen;
static HPEN greenPen;
static HPEN bluePen;
static HPEN* currentPen = &redPen;
switch (iMessage)
{
case WM_CREATE:
{
redPen = CreatePen(PS_SOLID, 4, RGB(255, 0, 0));
greenPen = CreatePen(PS_SOLID, 4, RGB(0, 255, 0));
bluePen = CreatePen(PS_SOLID, 4, RGB(0, 0, 255));
return 0L;
}
case WM_DESTROY:
cout << "\n" << "destroying window" << endl;
PostQuitMessage(0);
return 0L;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
return 0L;
case WM_LBUTTONDOWN:
prevPt.x = LOWORD(lParam);
prevPt.y = HIWORD(lParam);
isDraw = true;
return 0L;
case WM_LBUTTONUP:
isDraw = false;
return 0L;
case WM_MOUSEMOVE:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
if (isDraw)
{
hdc = GetDC(g_hWnd);
HPEN OldPen = (HPEN)SelectObject(hdc, *currentPen);
MoveToEx(hdc, prevPt.x, prevPt.y, NULL);
LineTo(hdc, x, y);
prevPt.x = x;
prevPt.y = y;
DeleteObject(OldPen);
ReleaseDC(g_hWnd, hdc);
}
}
return 0L;
case WM_RBUTTONDOWN:
isErase = true;
return 0L;
case WM_RBUTTONUP:
isErase = false;
return 0L;
case WM_MOUSEWHEEL:
if (selectColor > 3)
selectColor = 1;
if (selectColor == 1) // Red
currentPen = &redPen;
else if (selectColor == 2)
currentPen = &greenPen;
else if (selectColor == 3)
currentPen = &bluePen;
selectColor++;
return 0L;
}
return DefWindowProc(hWnd, iMessage, wParam, lParam);
}
void main()
{
HWND window;
LPCWSTR myclass = L"DrawTest";
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW, WindowProc,
0, 0, NULL, LoadIcon(0,IDI_APPLICATION), LoadCursor(0,IDC_ARROW), (HBRUSH)WHITE_BRUSH, 0, myclass, LoadIcon(0,IDI_APPLICATION) };
if (RegisterClassEx(&wndclass))
{
window = CreateWindowEx(WS_EX_TRANSPARENT, myclass, L"title", WS_POPUP, 0, 0, GetSystemMetrics(SM_CXFULLSCREEN), GetSystemMetrics(SM_CYFULLSCREEN), 0, 0, NULL, 0);
}
VideoCapture* pCapture = nullptr;
pCapture = new VideoCapture(0);
if (pCapture)
{
if (!pCapture->isOpened())
{
cout << "Can not open video file." << endl;
return;
}
int fps = (int)(pCapture->get(CAP_PROP_FPS));
int delay = 0;
if (fps == 0)
fps = 24;
delay = 1000 / fps;
Mat colorMat;
while (1)
{
*pCapture >> colorMat;
if (colorMat.empty())
break;
Mat copyColor;
colorMat.copyTo(copyColor);
imshow("colorMat", copyColor);
int ckey = waitKey(delay);
if (ckey == 27)
break;
if (window)
{
ShowWindow(window, SW_SHOW);
MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
GetMessage(&msg, 0, 0, 0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
cv::destroyAllWindows();
}
}
As I said in my comment, create a layered window:
window = CreateWindowEx(WS_EX_LAYERED, myclass, L"title", WS_POPUP, 0, 0,
GetSystemMetrics(SM_CXFULLSCREEN), GetSystemMetrics(SM_CYFULLSCREEN),
HWND_DESKTOP, NULL, NULL, NULL);
set color transparency the same as your background brush:
SetLayeredWindowAttributes(window, RGB(255, 255, 255), 0, LWA_COLORKEY);
In WM_PAINT
hdc = BeginPaint(hwnd, &ps);
HPEN OldPen = (HPEN)SelectObject(hdc, *currentPen);
//set random values
MoveToEx(hdc, 50, 50, NULL);
LineTo(hdc, 450, 450);
SelectObject(hdc, OldPen);
EndPaint(hwnd, &ps);
return 0;
This code works, BUT you cant get mouse messages cause the window is transparent. That is the main issue, not the drawing.
EDIT
The problem is how to get mouse messages. The solution is to create a second window on top of your main window with opacity nearly zero so it is not visible but get the mouse messages!
window = CreateWindowEx(WS_EX_LAYERED, myclass, L"title", WS_POPUP, 0, 0,
GetSystemMetrics(SM_CXFULLSCREEN), GetSystemMetrics(SM_CYFULLSCREEN),
HWND_DESKTOP, NULL, NULL, NULL);
windowClone = CreateWindowEx(WS_EX_LAYERED, myclass, L"title", WS_POPUP, 0, 0,
GetSystemMetrics(SM_CXFULLSCREEN), GetSystemMetrics(SM_CYFULLSCREEN),
window, NULL, NULL, NULL);
Make your main window complete transparent:
//background color MUST be the same with color Key!
SetLayeredWindowAttributes(window, RGB(255, 255, 255), 0, LWA_COLORKEY);
Make nearly transparent your clone window
//The transparency is set to 1
SetLayeredWindowAttributes(windowClone, 0, 1, LWA_ALPHA);
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
PAINTSTRUCT ps;
HDC hdc;
static int draw = FALSE, startX, startY, endX, endY, posX, posY;
switch(message){ //handle the messages
case WM_PAINT:
printf("WM_PAINT \n");
if( hwnd == window && draw == TRUE ){
HPEN OldPen, redPen;
redPen = CreatePen(PS_SOLID, 4, RGB(255, 0, 0));
hdc = BeginPaint(hwnd, &ps);
OldPen = (HPEN)SelectObject(hdc, redPen);
MoveToEx(hdc, startX, startY, NULL);
LineTo(hdc, endX, endY);
SelectObject(hdc, OldPen);
EndPaint(hwnd, &ps);
DeleteObject(redPen);
return 0;
}
break;
case WM_MOUSEMOVE:
//printf("WM_MOUSEMOVE \n");
if( hwnd == windowClone && draw == TRUE ){
startX = posX;
startY = posY;
endX = GET_X_LPARAM(lParam);
endY = GET_Y_LPARAM(lParam);
posX = endX;
posY = endY;
InvalidateRect(window, NULL, FALSE);
}
break;
case WM_LBUTTONDOWN:
printf("WM_LBUTTONDOWN \n");
if( hwnd == windowClone ){
posX = GET_X_LPARAM(lParam);
posY = GET_Y_LPARAM(lParam);
draw = TRUE;
}
break;
case WM_LBUTTONUP:
printf("WM_LBUTTONUP \n");
if( hwnd == windowClone && draw == TRUE ){
draw = FALSE;
}
break;
case WM_CAPTURECHANGED:
printf("WM_CAPTURECHANGED \n");
if( hwnd == windowClone && draw == TRUE ){
draw = FALSE;
}
break;
default: //for messages that we don't deal with
return DefWindowProc(hwnd, message, wParam, lParam);
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

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