How can I capture a transparent or translucent window in win32 - c++

I want to have a transparent window which has only borders and than capture it (and see all the windows behind it - since its transparent) to bitmap.
I managed to create the transparent window but when I try to capture it than it ceases to be transparent and I get it original background.
This is what I have so far,
creating the window:
//registering the window class with white backgournd
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = ScreenCaptureROIWinProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = _WPModule.GetHInstance();
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = CreateSolidBrush(0x00FFFFFF);//white brush;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = g_lpszClassName;
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
//creating a layered window
m_hWnd = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_LAYERED,g_lpszClassName, NULL,
WS_THICKFRAME, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL,
NULL, hInstance(), NULL);
// Set white brushed sections of the window to be transparent
SetLayeredWindowAttributes(m_hWnd, 0x00FFFFFF, 0, LWA_COLORKEY);
capturing the window:
RECT ROIRect;
GetWindowRect(m_hWnd,ROIRect);
HDC hdcScreen = GetDC(m_hWnd);
HDC hdcMem = CreateCompatibleDC(hdcScreen);
BitBlt(
hdcMem,
0,
0,
ROIRect.right - ROIRect.left, //width of window
ROIRect.bottom - ROIRect.top, //height of window
hdcScreen,
0,
0,
SRCCOPY);

Related

How to activate a win32 menu bar when using glut for OpenGL?

I bind the glut window with the win32 window as its subwindow. But then I want to use the win32 menu bar instead of the menu bar provided by glut. However, if I use glutMainLoop(), dispatchMessage() can't get invoked. And if I write codes as win32: while(GetMessage(&nMsg, NULL, 0, 0)){}, everythin in glut can't be implemented.
static TCHAR szAppName[] = TEXT("HelloWin");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = 0;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindowW(szAppName, // window class name
TEXT("The Hello Program"), // window caption
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
CW_USEDEFAULT,// initial x position
CW_USEDEFAULT,// initial y position
CW_USEDEFAULT,// initial x size
CW_USEDEFAULT,// initial y size
NULL, // parent window handle
NULL, // window menu handle
0, // program instance handle
NULL); // creation parameters
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(50, 50);
glutInitWindowSize(800, 600);
glutCreateWindow("easy geometry tool with typed input");
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
RegisterClass(&wc);
HWND hWnd = GetActiveWindow();
HWND hwndGLFW = GetActiveWindow();
SetWindowLong(hwndGLFW, GWL_STYLE, WS_VISIBLE);
MoveWindow(hwndGLFW, 0, 0, 1150, 800, TRUE);
SetParent(hwndGLFW, hwnd);
HINSTANCE hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE);
HMENU hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1));
SetMenu(hWnd, hMenu);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
Init();
glutDisplayFunc(myDisplay);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutSpecialFunc(keyboardSpecial);
createGlutMenu();
MSG nMsg = { 0 };
while (GetMessage(&nMsg, NULL, 0, 0)) {
glutMainLoop();
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
};
If anyone who can tell me the solution to my problem, thanks a lot!!!!!!

Transparent bitmap 32bit as window background

How can I set a graphic in bmp 32bit format as window background with TRANSPARENCY? when i use bmp 28bit everything works but then there is no transparency. When i use 32bit bitmap with alpha the background is not rendered.
Application is in c ++ winapi.
bool ApplicationInit(HINSTANCE hinstance)
{
//HBITMAP hbmp = LoadBitmap(hinstance, MAKEINTRESOURCE(IDB_LAUNCHER_BG));
HBITMAP hbmp = (HBITMAP)LoadImage(hinstance, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
HBRUSH hbr = CreatePatternBrush(hbmp);
WNDCLASSEX wcx;
wcx.cbSize = sizeof(wcx);
wcx.style = CS_HREDRAW | CS_VREDRAW;
wcx.lpfnWndProc = LauncherWndProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hinstance;
wcx.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ICON));
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = hbr;
wcx.lpszMenuName = NULL;
wcx.lpszClassName = szWindowClass;
return RegisterClassEx(&wcx);
}
please help :)

Drawing child window on main window during WM_PAINT

I have a problem,
When I move my child window over the main window it is being drawed on it during WM_PAINT and it looks like this:
(it disappears quickly).
How can I fix this? Here is my code, WM_PAINT:
case WM_PAINT:
{
PAINTSTRUCT ps = { 0 };
HDC hdc = BeginPaint(hwnd, &ps);
RECT rc;
GetClientRect(hwnd, &rc);
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
HGDIOBJ oldbmp = SelectObject(memdc, hbitmap);
FillRect(memdc, &rc, WHITE_BRUSH);
Gdiplus::Graphics gr(memdc);
gr.DrawImage(firstImage, 0, 150, 810, 400);
gr.DrawImage(secondImage, 0, 0, 800, 580);
BitBlt(hdc, 0, 0, rc.right, rc.bottom, memdc, 0, 0, SRCCOPY);
SelectObject(memdc, oldbmp);
DeleteObject(hbitmap);
DeleteDC(memdc);
EndPaint(hwnd, &ps);
return 0;
}
And how I create my windows:
memset(&wc, 0, sizeof(wc));
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszClassName = "WindowClass";
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hIcon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( 1284 ) );
wc.hIconSm = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( 2503 ) );
INITCOMMONCONTROLSEX iccex;
iccex.dwICC = ICC_WIN95_CLASSES;
iccex.dwSize = sizeof( INITCOMMONCONTROLSEX );
InitCommonControlsEx( & iccex );
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Launcher",WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX | WS_CLIPCHILDREN,
CW_USEDEFAULT, /* x */
CW_USEDEFAULT, /* y */
500, /* width */
120, /* height */
NULL,NULL,hInstance,NULL);
memset(&wc,0,sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc2;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszClassName = "WindowClass2";
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hIcon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( 1284 ) );
wc.hIconSm = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( 2503 ) );
hwndLog = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass2", "Log in",WS_DLGFRAME|WS_EX_TOOLWINDOW|WS_EX_TOPMOST|WS_SYSMENU|WS_CAPTION,
CW_USEDEFAULT, /* x */
CW_USEDEFAULT, /* y */
600, /* width */
200, /* height */
hwnd,NULL,hInstance,NULL);
It's funny, because when I move other window over my main window (eg. Google Chrome), everything is OK.

C++, GDI+, Load Bitmap and use UpdateLayeredWindow to show Bitmap

Community, I have a small problem and I need help.
I want to load a bitmap and want to show this with UpdatelayerdWindow. I have written the following source code. But nothing appears.
When I use the BitBlt function, the picture appears.
Where do I have here the error in my source code?
ATOM SplashRegisterClass(HINSTANCE hInstance) {
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 = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
void ShowBitMap(HWND hwnd, HINSTANCE hInstance) {
int nuXPos = 0;
int nuYPos = 0;
int width = 0;
int height = 0;
BITMAP bm;
hbmpSplash = (HBITMAP)::LoadImage(hInstance, L"software.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (hbmpSplash == NULL)
{
::MessageBox(NULL, __T("Image not Found"), __T("Error"), MB_OK);
}
GetObject(hbmpSplash, sizeof(bm), &bm);
SIZE size = { bm.bmHeight, bm.bmWidth };
width = bm.bmWidth;
height = bm.bmHeight;
POINT ptZero = { 0 };
HMONITOR hmonPrimary = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
MONITORINFO monitorinfo = { 0 };
monitorinfo.cbSize = sizeof(monitorinfo);
GetMonitorInfo(hmonPrimary, &monitorinfo);
const RECT & rcWork = monitorinfo.rcWork;
nuXPos = rcWork.left + (rcWork.right - rcWork.left) / 2;
nuYPos = rcWork.top + (rcWork.bottom - rcWork.top) / 2;
nuXPos = nuXPos - (175 / 2);
nuYPos = nuYPos - (170 / 2);
HDC hdcScreen = GetDC(NULL);
HDC hdcneu = CreateCompatibleDC(hdcScreen);
HDC hdcMem = CreateCompatibleDC(hdcScreen);
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, hbmpSplash);
POINT position = { nuXPos, nuYPos };
BLENDFUNCTION blend = { 0 };
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
//Next line only for test!
//::BitBlt(hdcScreen, nuXPos, nuYPos, width, height, hdcMem, 0, 0, SRCCOPY);
//Show the Bitmap
if (!UpdateLayeredWindow(splashOwner, hdcScreen, &position, &size, hdcMem, NULL, RGB(0, 0, 0), &blend, ULW_ALPHA))
{
//int LastError = GetLastError();
}
SelectObject(hdcMem, hbmpOld);
DeleteDC(hdcMem);
ReleaseDC(NULL, hdcScreen);
}
HWND CreateSplashWindow(HINSTANCE hInstance, int nCmdShow) {
SplashRegisterClass(hInstance);
splashOwner = CreateWindow(szWindowClass, NULL, WS_POPUP, 0, 0, 100, 100, NULL, NULL, hInstance, NULL);
if (!splashOwner)
{
::MessageBox(NULL, __T("Error"), __T("Error"), MB_OK);
}
ShowBitMap(splashOwner, hInstance);
return CreateWindowEx(WS_EX_LAYERED, szWindowClass, 0, WS_POPUP, 0, 0, 100, 100, splashOwner, NULL, hInstance, NULL);
}
I want delete everything when the main programme is running. Can I make with this function?
void DeleteSplashWindow(){
ReleaseDC(splashOwner, 0);
}
Thanks for help!
hbmpSplash = (HBITMAP)::LoadImage(hInstance, L"software.bmp",
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
This function fails, it should give an error. Change it to
hbmpSplash = (HBITMAP)::LoadImage(0, L"software.bmp",
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
When creating layered window you must call SetLayeredWindowAttributes. Example
HWND CreateSplashWindow(HINSTANCE hInstance, int nCmdShow) {
...
HWND hwnd = CreateWindowEx(WS_EX_LAYERED, szWindowClass,
0, WS_POPUP, 0, 0, 100, 100,
splashOwner, NULL, hInstance, NULL);
SetLayeredWindowAttributes(hwnd, transparentColor, alpha, LWA_COLORKEY | LWA_ALPHA);
return hwnd;
}
Thanks for the help, I arrive myself to the solution. 1. I forgot ShowWindow(hwnd,SW_SHOW); and
2.void DeleteSplashWindow(){
ReleaseDC(splashOwner, NULL);
ShowWindow(splashOwner, NULL);
}

C++ WINAPI setting window background image doesn't work

I hate that I have done it before, I feel like I am missing something and I don't know what it is. So, I am trying to set the background image of a windows in C++ WinAPI.
My Resources.rc
#include "Resources.h"
BACKGROUND BITMAP "background.bmp"
My Resources.h
#define BACKGROUND 200
My Main.cpp
....
WNDCLASSEX wcls;
wcls.cbSize = sizeof(WNDCLASSEX);
wcls.style = CS_PARENTDC|CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
wcls.lpfnWndProc = WndProc;
wcls.cbClsExtra = 0;
wcls.cbWndExtra = 0;
wcls.hInstance = hInstance;
wcls.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(HICON));
wcls.hCursor = LoadCursor(NULL, IDC_ARROW);
wcls.hbrBackground = HBRUSH(COLOR_WINDOW + 1);
wcls.lpszClassName = L"WndClass";
wcls.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(HICON));
HWND Window = CreateWindowEx (
WS_EX_LAYERED|WS_EX_TOOLWINDOW,
wcls.lpszClassName,
L"Window Title",
WS_VISIBLE|WS_POPUP|WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
384,
128,
NULL,
NULL,
hInstance,
NULL
);
if (!Window ) return 0;
SetLayeredWindowAttributes(
Window,
RGB(35, 35, 35),
85,
LWA_ALPHA|LWA_COLORKEY
);
SetWindowPos(
Window,
HWND_TOPMOST,
0,
0,
0,
0,
SWP_NOMOVE|SWP_NOREDRAW|SWP_NOSIZE
);
ShowWindow(Window, SW_SHOWNORMAL);
UpdateWindow(Window);
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM Wpar, LPARAM Lpar) {
HBITMAP Background = NULL;
BITMAP BgImg;
HDC DeviceContext, BgContext;
PAINTSTRUCT PaintStruct;
switch (Msg) {
case WM_PAINT:
ContextLansator = BeginPaint(hWnd, &PaintStruct);
Fundal = LoadBitmap(hInstance, MAKEINTRESOURCE(BACKGROUND));
FundalLansator = CreateCompatibleDC(DeviceContext);
SelectObject(DeviceContext, Background);
GetObject(Background, sizeof(BgImg), &BgImg);
BitBlt(DeviceContext, 0, 0, 384, 128, BgContext, 0, 0, SRCAND);
DeleteObject(Background);
DeleteDC(BgContext);
EndPaint(hWnd, &PaintStruct);
break;
.....
I am using Code::Blocks. The resource is embedded correctly, the window starts but just a white background, the image is not painted. The WM_PAINT message is called once, at the beginning. I fill like something is wrong with BgImg but I don't know what. Some help needed! Thanks!
Create a PatternBrush and set it to the background before registering class. For example:
ATOM MyRegisterClass(HINSTANCE hInstance)
{
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, MAKEINTRESOURCE(IDI_WINAPIBACKGROUND));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = CreatePatternBrush(LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP1 ) ) );
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WINAPIBACKGROUND);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
It looks like this:
Bitmap depth shouldn't matter. But take a look at the styles in your implementation.
i use this code and it work fine for me.
i use code block 4.7 too.
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
BITMAP bitmap;
HDC hdcMem;
HGDIOBJ oldBitmap;
hBitmap01 = (HBITMAP)LoadImage(NULL, "c:\\energy.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
hdc = BeginPaint(wnd01, &ps);
hdcMem = CreateCompatibleDC(hdc);
oldBitmap = SelectObject(hdcMem, hBitmap01);
GetObject(hBitmap01, sizeof(bitmap), &bitmap);
BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, oldBitmap);
DeleteDC(hdcMem);
EndPaint(wnd01, &ps);
}
After 20 hours working on what I think is a similar symptom, I found a solution.
My problem was bitmap not loading. I verified the file was truly bitmap and code correct. I corrected and recompiled but Code::Blocks would not load it (return = 0). Try deleting, the two folders BIN and OBJ and the two files xxx.depend and xxx.layout. Then recompile and run.