WM_MOVING, LPARAM Gives Wrong values on aero snap - c++

I Was working on a win32 project which uses the WM_MOVING message from WndProc to detect the new position where window is moved. but when i try to snap the window to left side the LPARAM gives wrong values for just a millisecond and gives the real value after that.
Please have a look into the output:
Left: 0, Right:683
Left: -205, Right:295
Left: 0, Right:683
Left: -205, Right:295
Left: 0, Right:683
Left: -205, Right:295
The real output is -205 but in between I get zero which cause the content of my window to flicker. In my case the position of the content is depend on the window position, so it causes flicker if I receive a wrong value.
Here is what i am trying to achieve : Manually creating acrylic effect
When ever I move the window in this mode (just before the aero snap mode) the value will get changed to zero.
This is only affecting The Top and Left coordinates of the window and also flickers when aero snapping to any sides.
Here is a simple reproduceable example:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
RECT* hostRect;
char buffer[200];
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0,CLASS_NAME,L"Learn to Program Windows",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_MOVING:
{
hostRect = reinterpret_cast<RECT*>(lParam);
sprintf_s(buffer, "Left: %d, Top:%d, Right:%d, Bottom:%d\n", hostRect->left, hostRect->top, hostRect->right, hostRect->bottom);
OutputDebugStringA(buffer);
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Run this program and check the value in output while you move the window to any side for aero snap.
Note: In my case i will not be able to use GetWindowRect() in WM_MOVING, because calling GetWindowRect() slow down the render() function (just a directx painting) in my window.

You can try to make temporary changes to the style of the window.
Here is an example:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <stdio.h>
#define WM_RESTOREORIGINALSTYLE WM_USER + 1
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
RECT* hostRect;
char buffer[200];
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"Learn to Program Windows", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_MOVING:
{
hostRect = reinterpret_cast<RECT*>(lParam);
sprintf_s(buffer, "Left: %d, Top:%d, Right:%d, Bottom:%d\n", hostRect->left, hostRect->top, hostRect->right, hostRect->bottom);
OutputDebugStringA(buffer);
break;
}
case WM_SYSCOMMAND:
{
if (wParam == (SC_MOVE | 2)) wParam = SC_SIZE | 9;
if ((wParam & 0xFFE0) == SC_SIZE && (wParam & 0x000F)) // handles MOVE and SIZE in one "if"
{
long int oldStyle = GetWindowLongW(hwnd, GWL_STYLE);
PostMessageW(hwnd, WM_RESTOREORIGINALSTYLE, GWL_STYLE, oldStyle);
SetWindowLongW(hwnd, GWL_STYLE, oldStyle & 0xFEFEFFFF); // disable WS_MAXIMIZE and WS_MAXIMIZEBOX
DefWindowProcW(hwnd, WM_SYSCOMMAND, wParam, lParam);
return 0;
}
return DefWindowProcW(hwnd, WM_SYSCOMMAND, wParam, lParam);
}
case WM_RESTOREORIGINALSTYLE:
{
if ((long int)wParam == GWL_STYLE)
SetWindowLongW(hwnd, GWL_STYLE, lParam);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
More reference : Win32 prevent window “snap”

Related

window fails to initiate when specifying a custom class name registered with RegisterClass to CreateWindowEx but only the second time I do it

I'm creating a window that's supposed to contain buttons.
When I create the first window (the container) I use a WNDCLASS to specify a WindowProc callback function to lpfnWndProc and it works as intended. When I do it the second time with a window, specifying a callback used to detect when the button is clicked, it doesn't work; the CreateWindowEx call there returns NULL (comment below shows where).
When I don't create WNDCLAS wB below and specify some other valid lpClassName to CreateWindowEx instead, such as Button it works fine.
code used
#pragma comment(linker, "/entry:wWinMainCRTStartup")
#include <windows.h>
#include <iostream>
HWND button;
LRESULT CALLBACK ButtonWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine,
int nCmdShow) {
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"textedit";
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0, wc.lpszClassName, L"textedit", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 340, 240, NULL, NULL, hInstance, NULL);
if (hwnd == NULL) {
return 0;
}
HWND hWndEdit = CreateWindowEx(WS_EX_CONTROLPARENT, L"Edit", L"id here",
WS_BORDER | WS_CHILD | WS_VISIBLE, 94, 20, 140,
40, hwnd, NULL, NULL, NULL);
// if I leave wcB unused/remove it and
// specify L"Button" as the lpClassName to CreateWindowEx below, the button displays
WNDCLASS wcB = {};
wcB.lpfnWndProc = ButtonWindowProc;
wcB.hInstance = hInstance;
wcB.lpszClassName = L"modify";
RegisterClass(&wcB);
ShowWindow(hwnd, nCmdShow);
// doing the exact same thing I did when creating the first window
// but it fails to create the window
HWND hButton =
CreateWindowEx(0L, L"modify", L"modify", BS_FLAT | WS_VISIBLE | WS_CHILD,
94, 70, 140, 50, hwnd, NULL, hInstance, NULL);
ShowWindow(hButton, nCmdShow);
// here hButton is NULL <----------------------
if (hButton == NULL) {
return 0;
}
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK ButtonWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case BN_CLICKED:
std::cout << "clicked";
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
return 0;
}
return 0;
return DefWindowProc(hwnd, uMsg, wParam, lParam);
};
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
GetLastError() returns 1400, but I don't understand how the handle hwnd could possible be invalid because as I mentioned before, when I just change the lpClassName I pass to CreateWindowEx, it works without errors.
I would appreciate any help in finding out why the window (the HWND of which is hButton) does not initiate, and possible workarounds.
The solution to the problem in the title was solved by the comment by Igor Tandetnik:
ButtonWindowProc returns 0 for all messages it doesn't handle, and doesn't pass them to DefWindowProc. In particular, it returns 0 in response to WM_NCCREATE, which is a signal that the window creation has failed. You probably didn't mean to put return 0; right before return DefWindowProc(...);
After fixing that, the window was created but was invisible.
To fix that I used FillRect with a valid brush handle
SetDCBrushColor(hdc, bkcolor);
SetBkColor(hdc, RGB(187, 189, 189));
FillRect(hdc, &ps.rcPaint, (HBRUSH)GetStockObject(DC_BRUSH));
To detect left mouse button clicks you need to check for the WM_LBUTTONDOWN message.

The Bottom Border of a simple Windows Application keeps disappearing and reaapearing when resizing the window

Here's a simple Win32 Application that I copied from the official MSDN docs (link):
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_DESKTOP+1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
The only difference is I used COLOR_DESKTOP instead of COLOR_WINDOW in FillRect() (this problem occurs in both the cases).
Whenever I resize the window, the bottom border keeps disappearing and then reappearing as I resize it further. Can anyone tell what's happening?
Here's GIF to show the bottom border disappearing when resizing:
I suggest you could try to enable DPI awareness: Property -> Manifest Tool ->Input and Output -> DPI Awareness.

open window program in visual c++

I just started to learn windows app development in c++ and I found some program code on Microsoft docs that all it should do is open simple window. I tried to build it on visual studio and it was built but it didn't run. And when I tried to compile and run it with the local debugger I got some error that I have no idea what is it about. I'd like to get some help with it.
Here is the code and the error message.
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

Making Transparent Label c++ WINAPI

Having a window with gif and some elements c++ winapi(Non-MFC) using gdi+. SO I want to make transparent elements(Edit,Static,Button). I want to make transparent gray background of elements.
I have tried to handle WM_CTLCOLORSTATIC and adding style WS_EX_TRANSPARENT and m. but it didn't give correct result. But when I handle WM_CTLCOLORSTATIC with code:
hdcStatic = (HDC) wParam;
SetTextColor(hdcStatic, RGB(0,0,0));
SetBkMode (hdcStatic, TRANSPARENT);
return (LRESULT)GetStockObject(NULL_BRUSH);
And it showed STATIC styles transparent, but I could see background of Windows 10.
Minimum code is:
#include <memory>
#include "Resource.h"
#include <vector>
#include "TESTING.h"
#include "framework.h"
#include <algorithm>
#include <windows.h>
#include <objidl.h>
#include <GdiPlus.h>
#include <gdiplusimaging.h>
#include <shlwapi.h>
#include<CommCtrl.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
#pragma comment (lib,"shlwapi.lib")
#pragma comment (lib,"Comctl32.lib")
#define TIMER_ID 101
static HFONT s_hFont = NULL;
static HWND hWnd;
static HWND hwndText;
static HWND hwndButton;
static HWND hwndLabel;
static HWND hwndCode;
static HWND hwndCode2;
static HWND hwndTime;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK SubWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR, DWORD_PTR);
int WINAPI _WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
ULONG_PTR m_gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
HMODULE hMod = GetModuleHandle(NULL);
HRSRC hRes = FindResource(hMod, MAKEINTRESOURCEW(MY_GIF_ID), RT_RCDATA);
if (!hRes) MessageBox(NULL, L"hRes!!", L"ERROR", 0);
HGLOBAL hGlobal = LoadResource(hMod, hRes);
if (!hGlobal)MessageBox(NULL, L"hGlobal!!", L"ERROR", 0);
void* pResData = LockResource(hGlobal);
if (!pResData) MessageBox(NULL, L"pResData!!", L"ERROR", 0);
DWORD dwResData = SizeofResource(hMod, hRes);
IStream* pStream = SHCreateMemStream((BYTE*)pResData, dwResData);
if (!pStream) MessageBox(NULL, L"pStream!!", L"ERROR", 0);
Image gif(pStream);
pStream->Release();
MSG msg = { 0 };
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = NULL; // <= Do not provide a background brush.
wc.lpszClassName = L"anim_gif_player";
if (!RegisterClass(&wc))
return -1;
hWnd = CreateWindow(wc.lpszClassName,
L"",
WS_EX_TOPMOST | WS_CLIPCHILDREN & ~WS_CAPTION & ~WS_SYSMENU,
0, 0, 640, 480, 0, 0, hInstance, &gif);
if (!hWnd) {
MessageBox(0, L"SSSSSSSSSSSSSSSSSSS", L"kkkkkkkkkkkkkkkkkkkkkk", 0);
return -2;
}
hwndLabel = CreateWindowEx(WS_EX_TRANSPARENT,L"STATIC",
NULL,
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS,
325, 90, 440, 45,
hWnd,
NULL,
NULL,
NULL);
SetWindowSubclass(hwndLabel, SubWndProc, 0, 0);
const TCHAR* fontName = TEXT("Croobie");
const long nFontSize = 24;
HDC hdc = GetDC(hwndLabel);
LOGFONT logFont = { 0 };
logFont.lfHeight = -MulDiv(nFontSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
logFont.lfWeight = FW_BOLD;
wcscpy_s(logFont.lfFaceName, fontName);
s_hFont = CreateFontIndirect(&logFont);
SendMessage(hwndLabel, WM_SETFONT, (WPARAM)s_hFont, (LPARAM)MAKELONG(TRUE, 0));
ShowWindow(hWnd, SW_SHOWMAXIMIZED);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//DeleteObject(wc.hbrBackground);
return msg.wParam;
}
std::vector<unsigned int> LoadGifFrameInfo(Image* image)
{
// I think animated gifs will always only have 1 frame dimension...
// the "dimension" being the frame count, but I could be wrong about this
int count = image->GetFrameDimensionsCount();
if (count != 1)
return std::vector<unsigned int>();
GUID guid;
if (image->GetFrameDimensionsList(&guid, 1) != 0)
return std::vector<unsigned int>();
int frame_count = image->GetFrameCount(&guid);
auto sz = image->GetPropertyItemSize(PropertyTagFrameDelay);
if (sz == 0)
return std::vector<unsigned int>();
// copy the frame delay property into the buffer backing an std::vector
// of bytes and then get a pointer to its value, which will be an array of
// unsigned ints
std::vector<unsigned char> buffer(sz);
PropertyItem* property_item = reinterpret_cast<PropertyItem*>(&buffer[0]);
image->GetPropertyItem(PropertyTagFrameDelay, sz, property_item);
unsigned int* frame_delay_array = (unsigned int*)property_item[0].value;
// copy the delay values into an std::vector while converting to milliseconds.
std::vector<unsigned int> frame_delays(frame_count);
std::transform(frame_delay_array, frame_delay_array + frame_count, frame_delays.begin(),
[](unsigned int n) {return n * 10; }
);
return frame_delays;
}
void GenerateFrame(Bitmap* bmp, Image* gif)
{
Graphics dest(bmp);
SolidBrush white(Color::White);
dest.FillRectangle(&white, 0, 0, bmp->GetWidth(), bmp->GetHeight());
if (gif)
dest.DrawImage(gif, 0, 0);
}
std::unique_ptr<Bitmap> CreateBackBuffer(HWND hWnd)
{
RECT r;
GetClientRect(hWnd, &r);
return std::make_unique<Bitmap>(r.right - r.left, r.bottom - r.top);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static Image* animated_gif;
static std::unique_ptr<Bitmap> back_buffer;
static std::vector<unsigned int> frame_delays;
static int current_frame;
switch (message) {
case WM_CREATE: {
animated_gif = reinterpret_cast<Image*>(
reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams
);
if (!animated_gif || animated_gif->GetLastStatus() != 0) {
MessageBox(hWnd, L"Unable to load animated gif", L"error", MB_ICONERROR);
return 0;
}
// Create a bitmap the size of the window's clent area
back_buffer = CreateBackBuffer(hWnd);
// get the frame delays and thereby test that this is really an animated gif
frame_delays = LoadGifFrameInfo(animated_gif);
if (frame_delays.empty()) {
MessageBox(hWnd, L"Invalid gif or not an animated gif", L"error", MB_ICONERROR);
return 0;
}
current_frame = 0;
animated_gif->SelectActiveFrame(&FrameDimensionTime, current_frame);
GenerateFrame(back_buffer.get(), animated_gif);
SetTimer(hWnd, TIMER_ID, frame_delays[0], nullptr);
InvalidateRect(hWnd, nullptr, FALSE);
}
break;
case WM_TIMER: {
KillTimer(hWnd, TIMER_ID);
current_frame = (current_frame + 1) % frame_delays.size();
animated_gif->SelectActiveFrame(&FrameDimensionTime, current_frame);
GenerateFrame(back_buffer.get(), animated_gif);
SetTimer(hWnd, TIMER_ID, frame_delays[current_frame], nullptr);
InvalidateRect(hWnd, nullptr, FALSE);
} break;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
Graphics g(hdc);
g.DrawImage(back_buffer.get(), 0, 0);
EndPaint(hWnd, &ps);
} break;
case WM_SIZE: {
back_buffer = CreateBackBuffer(hWnd);
GenerateFrame(back_buffer.get(), animated_gif);
} break;
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK SubWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR, DWORD_PTR) {
switch (msg) {
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rc; GetClientRect(hwnd, &rc);
SetTextColor(hdc, Color::Yellow);
SetBkMode(hdc, TRANSPARENT);
wchar_t buf[256] = { 0 };
GetWindowTextW(hwnd, buf, sizeof(buf) / sizeof(*buf));
DrawTextW(hdc, buf, wcslen(buf), &rc, DT_LEFT | DT_TOP);
EndPaint(hwnd, &ps);
return 0;
}
case WM_NCDESTROY://safely remove subclass
RemoveWindowSubclass(hwnd, SubWndProc, 0);
return DefSubclassProc(hwnd, msg, wParam, lParam);
}
return DefSubclassProc(hwnd, msg, wParam, lParam);
}
The WS_EX_TRANSPARENT style doesn’t mean “transparent”; it means
“paint over siblings.”
The style is called “transparent” not because it makes the window
transparent but because it makes transparency possible.
Please refer: Why isn't my transparent static control transparent?
The only way I've found to do this reliably is to sub-class the static control and paint the background manually.
You can catch the WM_ERASEBKGND message and paint the appropriate portion of the underlying bitmap.
Please refer:
Is it possible to make a Static control transparent?
C++ Win32 Static Control Transparent Background
Also, if you want remove grey background, you can change static control background and make it transparent.
Demon of custom static control:
#include "stdafx.h"
#include "Test_WM_CTLCOLORSTATIC.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
HWND hWndStatic;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WndProcPanel(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_TESTWMCTLCOLORSTATIC, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTWMCTLCOLORSTATIC));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW 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, MAKEINTRESOURCE(IDI_TESTWMCTLCOLORSTATIC));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_TESTWMCTLCOLORSTATIC);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
WNDPROC StaticWndProc = NULL;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{ LRESULT lRes = DefWindowProc(hWnd, message, wParam, lParam);
hWndStatic = CreateWindowEx(0, L"Static", NULL, WS_CHILD | WS_VISIBLE | SS_LEFT, 10, 130, 200, 40, hWnd, NULL, hInst, NULL); //v2 deleted HWND
StaticWndProc = (WNDPROC)SetWindowLong(hWndStatic, GWL_WNDPROC, (LPARAM)WndProcPanel);
return lRes;
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_ERASEBKGND:
{
HBRUSH brush;
RECT rect;
brush = CreateSolidBrush(RGB(0, 255, 0));
SelectObject((HDC)wParam, brush);
GetClientRect(hWnd, &rect);
Rectangle((HDC)wParam, rect.left, rect.top, rect.right, rect.bottom);
}
break;
case WM_DESTROY:
SetWindowLong(hWndStatic, GWL_WNDPROC, (LPARAM)StaticWndProc);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
TCHAR szText[] = _T("TestString");;
LRESULT CALLBACK WndProcPanel(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_PAINT)
{
RECT rc;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rc);
SetBkMode(hdc, TRANSPARENT);
DrawText(hdc, szText, _tcslen(szText), &rc, DT_CENTER | DT_VCENTER);
EndPaint(hWnd, &ps);
return 0;
}
return CallWindowProc(StaticWndProc, hWnd, message, wParam, lParam);
}
thx #IInspectable's remind, the best way to subclass controls is to use SetWindowsSubclass, see Subclassing Controls
I'll update the new code later, and I'm sorry for my shallow knowledge.
Updated:
case WM_TIMER: {
KillTimer(hWnd, TIMER_ID);
current_frame = (current_frame + 1) % frame_delays.size();
animated_gif->SelectActiveFrame(&FrameDimensionTime, current_frame);
GenerateFrame(back_buffer.get(), animated_gif);
SetTimer(hWnd, TIMER_ID, frame_delays[current_frame], nullptr);
InvalidateRect(hWnd, nullptr, FALSE);
InvalidateRect(hwndLabel, nullptr, FALSE); //Here add new code
}
Debug Result:

Error creating a window in windows "undefined reference to 'WinMain#16'"

#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0,
CLASS_NAME,
L"Learn to Program Windows",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
This is the code, which is also the standard example you can find in the microsoft website that teach people how to program windows.
http://msdn.microsoft.com/en-us/library/windows/desktop/ff381409(v=vs.85).aspx
The problem I receive is the following whenever I try to compile this code in codeblocks.
undefined reference to 'WinMain#16'
What is that and what can I do to compile and run this piece of code?
It seems strange to me that WinMain is called wWinMain: evidently you need a function called WinMain.
Oh, wait, you are using codeblocks? Probably wWinMain is specific of visual studio. Codeblocks wants the standard WinMain.