I'm trying to create a win32 semi / transparent window, on which I could draw with another program on it with GDI+ api
When i'm drawing on the main window the line is staying few second on the screen
Even if the double buffering is enabled with WS_EX_COMPOSITED in SetWindowLong
How can i disable this flickering ? I'm pretty sure the problem is from my window because i don't have this problem on other window
My WinMain
int WINAPI WinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(wcex.hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Windows Desktop Guided Tour"),
0);
return 1;
}
hInst = hInstance;
HWND hWnd = CreateWindowEx(
0,
szWindowClass,
szTitle,
WS_POPUP,
CW_USEDEFAULT, CW_USEDEFAULT,
1280, 720,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Windows Desktop Guided Tour"),
0);
return 1;
}
MSG msg;
SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_COMPOSITED);
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), (255 * 50) / 100, LWA_ALPHA); //50%
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
while(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}return(int)msg.wParam;
}
and my WndProc
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
Here my code for drawing on the main window
while(1){
DrawLine(ScreenX, ScreenY/2,ScreenX/2 , id, targethdc);
Sleep(1);
id++;
if(id >= ScreenY){
id=0;
}
}
void DrawLine(float StartX, float StartY, float EndX, float EndY, HDC hdc)
{
int a, b = 0;
HPEN hOPen;
HPEN hNPen = CreatePen(PS_SOLID, 2, RGB(255,0,0));// penstyle, width, color
hOPen = (HPEN)SelectObject(hdc, hNPen);
MoveToEx(hdc, StartX, StartY, NULL); //start
a = LineTo(hdc, EndX, EndY); //end
DeleteObject(SelectObject(hdc, hOPen));
}
Thx
Related
I have this directory structure:
---- test.cpp
---- test.exe (created after compiling test.cpp)
---- sample.bmp
I have this code, which (for the time being) reads the image sample.bmp and stores it in a HBITMAP handle:
#include <tchar.h>
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
{
HWND sampleImg = CreateWindowEx(0, "Static", "", WS_CHILD | WS_VISIBLE | SS_BITMAP, 0, 0, 0, 0, hWnd, NULL, NULL, NULL);
/* --------------HERE----------------- */
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, "D:\\Rest\\New Folder\\sample.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (hBitmap == NULL)
{
/* This block is reached, hBitmap is NULL */
MessageBox(NULL, "LoadImage failed", "Error", MB_OK);
return 0;
}
SendMessage(sampleImg, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "Test";
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
RegisterClassEx(&wcex);
HWND hWnd = CreateWindow("Test", "Test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
I tried to call GetLastError() and check the error code. The error code is 0 (ERROR_SUCCESS), implying there are no errors.
Could anyone tell me what is wrong with the code?
Directory structure of D:/Rest/New Folder:
I wanted to fetch a bitmap image, but the necessary routine returns NULL.
Is there a way to get the control handle using the coordinate position of the control? In other words, is there a way to find the control in the window area provided that we know its coordinate position?
You can use WindowFromPoint:
Here is the sample:
#include <Windows.h>
#include <iostream>
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("hello windows");
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 = CreateWindow(szAppName,
TEXT("the hello program"),
WS_OVERLAPPEDWINDOW,
100,
100,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
POINT pt;
char bf[100];
HWND h;
HDC hdc;
RECT rc;
case WM_LBUTTONDOWN:
pt.x = 10;
pt.y = 10;
hdc = GetDC(hwnd);
h = WindowFromPoint(pt);
GetClientRect(hwnd, &rc);
sprintf_s(bf, 100, "%p\n", h);
TextOut(hdc,rc.right/2,rc.bottom/2,bf,strlen(bf));
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
When I press the left button, the handle for setting the coordinates is displayed in the middle of the screen.
I'm trying to draw a custom painted non-client area, instead of default theme border (Windows 10).
I handled WM_NCCALCSIZE to resize the non-client area to 4 pixels on each side and then handled WM_NCPAINT to draw the red border.
My custom painting succeeds when application is first displayed, but fails to redraw either when application is resized, or when minimized and restored, despite the fact that both WM_NCCALCSIZE and WM_NCPAINT are called during resizing or when window is restored.
#pragma comment(lib, "UxTheme")
#include <windows.h>
#include <uxtheme.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = (HICON) LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = CreateSolidBrush(RGB(0,128,0));
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "window";
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
HWND hWnd = CreateWindowEx(
WS_EX_COMPOSITED,
"window",
NULL,
WS_OVERLAPPEDWINDOW,
100,
100,
600,
400,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_CREATE:
SetWindowTheme(hWnd, L"", L"");
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_NCCALCSIZE:
{
RECT rect;
GetWindowRect(hWnd, &rect);
LPNCCALCSIZE_PARAMS ncParams = (LPNCCALCSIZE_PARAMS) lParam;
ncParams->rgrc[0].top = rect.top + 4;
ncParams->rgrc[0].left = rect.left + 4;
ncParams->rgrc[0].bottom = rect.bottom - 4;
ncParams->rgrc[0].right = rect.right - 4;
return 0;
}
case WM_NCPAINT:
{
RECT rect;
GetWindowRect(hWnd, &rect);
HDC dc = GetDCEx(hWnd, (HRGN) wParam, DCX_WINDOW | DCX_CACHE | DCX_INTERSECTRGN | DCX_LOCKWINDOWUPDATE);
HPEN pen = CreatePen(PS_INSIDEFRAME, 4, RGB(255, 0, 0));
HGDIOBJ old = SelectObject(dc, pen);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
Rectangle(dc, 0, 0, width, height);
SelectObject(dc, old);
DeleteObject(pen);
ReleaseDC(hWnd, dc);
return 0;
}
case WM_NCACTIVATE:
RedrawWindow(hWnd, NULL, NULL, RDW_UPDATENOW);
return 0;
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
The wParam of WM_NCPAINT message sometimes returns 1 instead of a handle to a region (HRGN). In that case HRGN must be created using CreateRectRgn function.
#pragma comment(lib, "UxTheme")
#include <windows.h>
#include <uxtheme.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = (HICON) LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = CreateSolidBrush(RGB(0,128,0));
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "window";
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
HWND hWnd = CreateWindowEx(
NULL,
"window",
NULL,
WS_OVERLAPPEDWINDOW,
100,
100,
600,
400,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_CREATE:
SetWindowTheme(hWnd, L"", L"");
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_NCCALCSIZE:
{
LPNCCALCSIZE_PARAMS ncParams = (LPNCCALCSIZE_PARAMS) lParam;
ncParams->rgrc[0].top += 4;
ncParams->rgrc[0].left += 4;
ncParams->rgrc[0].bottom -= 4;
ncParams->rgrc[0].right -= 4;
return 0;
}
case WM_NCPAINT:
{
RECT rect;
GetWindowRect(hWnd, &rect);
HRGN region = NULL;
if (wParam == NULLREGION) {
region = CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
} else {
HRGN copy = CreateRectRgn(0, 0, 0, 0);
if (CombineRgn(copy, (HRGN) wParam, NULL, RGN_COPY)) {
region = copy;
} else {
DeleteObject(copy);
}
}
HDC dc = GetDCEx(hWnd, region, DCX_WINDOW | DCX_CACHE | DCX_INTERSECTRGN | DCX_LOCKWINDOWUPDATE);
if (!dc && region) {
DeleteObject(region);
}
HPEN pen = CreatePen(PS_INSIDEFRAME, 4, RGB(255, 0, 0));
HGDIOBJ old = SelectObject(dc, pen);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
Rectangle(dc, 0, 0, width, height);
SelectObject(dc, old);
ReleaseDC(hWnd, dc);
DeleteObject(pen);
return 0;
}
case WM_NCACTIVATE:
RedrawWindow(hWnd, NULL, NULL, RDW_UPDATENOW);
return 0;
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
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.
I'm trying to draw with GDIplus on an transparent window and experiencing a lot of flickering. I've read plenty of threads that suggest implementing double-buffering or rendering to offscreen surface would help, which I've done but to no avail.
Any idea what I've done wrong and how to fix it?
Thanks.
#include <Windows.h>
#include <stdio.h>
#include <time.h>
#include <GdiPlus.h>
#pragma comment(lib, "GdiPlus.lib")
HWND hWnd = NULL;
WNDCLASSEX wcex;
HDC hdc = NULL;
PAINTSTRUCT ps;
HGDIOBJ hfDefault;
MSG msg;
COLORREF transKey = RGB(37,14,103);
ULONG_PTR m_gdiplusToken;
char window_title[9] = "testings";
char window_class[9] = "testings";
int window_width = GetSystemMetrics(SM_CXSCREEN);
int window_height = GetSystemMetrics(SM_CYSCREEN);
DWORD MainThread(LPVOID lpArgs)
{
while(1)
{
RECT rc = {0,0,window_width,window_height};
InvalidateRect(hWnd, &rc, false);
UpdateWindow(hWnd);
Sleep(50);
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if(msg == WM_CREATE)
{
hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
SetLayeredWindowAttributes(hWnd, transKey, 128, LWA_COLORKEY);
}
else if(msg == WM_PAINT)
{
hdc = BeginPaint(hWnd, &ps);
Gdiplus::Graphics g(hdc);
g.Clear(Gdiplus::Color(37,14,103));
Gdiplus::Bitmap* curBitmap = new Gdiplus::Bitmap(window_width, window_height);
Gdiplus::Graphics* g1 = g.FromImage(curBitmap);
static int x=1,y=1;
// x += 3;
y += 2;
Gdiplus::Pen pen(Gdiplus::Color(255, 255, 0, 255));
g1->DrawLine(&pen, x, y, window_width/2, window_height/2);
g.DrawImage(curBitmap, 0, 0);
EndPaint(hWnd, &ps);
}
else if(msg == WM_CLOSE)
{
DestroyWindow(hWnd);
}
else if(msg == WM_DESTROY)
{
PostQuitMessage(0);
}
else
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HBRUSH hbrBackground = CreateSolidBrush(transKey);
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = hbrBackground;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = window_class;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if(!RegisterClassEx(&wcex))
return 1;
hWnd = CreateWindowEx(
WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
window_class,
window_title,
WS_POPUP,
0,
0,
window_width,
window_height,
NULL,
NULL,
hInstance,
NULL
);
if(!hWnd)
return 1;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainThread, NULL, NULL, NULL);
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Gdiplus::GdiplusShutdown(m_gdiplusToken);
return msg.wParam;
}
You have the WS_EX_TRANSPARENT attribute on your window, which causes the window underneath it to repaint every time your window is invalidated. Try removing it.
The meaning of WS_EX_TRANSPARENT is to tell Windows that you won't be drawing on the full window surface (i.e. leaving parts of it transparent), so it needs to make sure everything underneath is rendered first so it can show through.