Reputation: 127
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.
Upvotes: 0
Views: 174