I want to create a layered window, the size of which is bigger than the size of its contents (hdcSrc). So that the window is for example 900x900, and we can place a 300x300 image inside of it anywhere we want, while the rest of the window is transparent.
Here is my code so far:
#include <Windows.h>
#include <string>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment( lib, "Gdiplus.lib" )
HWND hwnd;
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
void updateTestWindow();
LRESULT CALLBACK windowProcedure(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow)
{
MSG msg;
// GDI+ elements
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
// Initialize GDI+.
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
// Register Window Class
WNDCLASS testWindowClass;
testWindowClass.lpszClassName = TEXT("TestWindow");
testWindowClass.hInstance = hInstance;
testWindowClass.style = CS_HREDRAW | CS_VREDRAW;
testWindowClass.lpfnWndProc = windowProcedure;
testWindowClass.hIcon = 0;
testWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
testWindowClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
testWindowClass.cbClsExtra = 0;
testWindowClass.cbWndExtra = 0;
testWindowClass.lpszMenuName = NULL;
RegisterClass(&testWindowClass);
// Create a layered window
hwnd = CreateWindowEx(
WS_EX_LAYERED,
TEXT("TestWindow"), // window class name
TEXT("TestWindow"), // window caption
WS_POPUP, // window style
0, // initial x position
0, // initial y position
screenWidth, // initial x size
screenHeight, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow(hwnd, iCmdShow);
// Update the layered window using a custom function
updateTestWindow();
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
void updateTestWindow()
{
// Let's imagine that in reality we are drawing an image, but to test it, just draw a rectangle
int imageWidth = 300;
int imageHeight = 300;
HDC screenDC = GetDC(NULL);
// Create a DC for drawing
HDC drawingDC = CreateCompatibleDC(screenDC);
// Create a new bitmap for drawing on it
HBITMAP newBitmap = CreateCompatibleBitmap(screenDC, imageWidth, imageHeight);
// Select the new bitmap to draw on it and save the old one
HBITMAP oldBitmap = (HBITMAP)SelectObject(drawingDC, newBitmap);
// Create graphics object
Graphics graphics(drawingDC);
// Draw a rectangle
Pen redPen(Color(255, 255, 0, 0), 15);
Rect windowRect(0, 0, imageWidth, imageWidth);
graphics.DrawRectangle(&redPen, windowRect);
// The position of the layered window
POINT windowPosition = { 0, 0 };
// The size of the layered window
SIZE windowSize = { imageWidth, imageHeight }; // <----------------------------------!!!!
POINT drawingDCPosition = { 0,0 };
// Create a blend function
BLENDFUNCTION blend = { 0 };
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
// Call UpdateLayeredWindow
UpdateLayeredWindow(hwnd, screenDC, &windowPosition, &windowSize,
drawingDC, &drawingDCPosition, 0, &blend, ULW_ALPHA);
// Clean up
SelectObject(drawingDC, oldBitmap);
DeleteObject(newBitmap);
DeleteDC(drawingDC);
ReleaseDC(NULL, screenDC);
}
This creates a window that is exactly the size of the image that's drawn on it.
We can reduce the window size: SIZE windowSize = { imageWidth-100, imageHeight-100 };
and the window will be drawn as expected - smaller size, while the image is the same size but now it's clipped (in this case, the rectangle is clipped).
However, if we want to achieve what I described in the beginning, SIZE windowSize = { imageWidth+100, imageHeight+100 };
doesn't work. The window is just not rendered at all, yet it opens (window taskbar icon is visible).
I probably just can't understand how a layered window works completely yet, which is why I can't understand why in this example it's not being rendered.
Is it possible to create such a layered window at all? And if yes, then how?
Or maybe this is not something I should be doing at all?
Just as a note: The reason I want to do this, is to use the layered window as a sort of an overlay, that would constantly be the size of the screen but the images, figures and text would be drawn on to it, updated, moved and so on.