Solved

Screen capture with Directx makes transparent Windows to disappear

Posted on 2011-03-11
24
1,500 Views
Last Modified: 2012-05-11
Hi experts,

I am facing trouble when capturing the desktop screen with both DirectX 8 and 9. Some windows dissappear at the very moment of capturing the screen, which is very annoying to users.

The hint I can give you is that those dissappearing windows are transparent. The method I am using is basically GetFrontBuffer, and I can not use GDI. I don't care if the content of the transparent window is not included in the screenshot, I just want that users don't complaint.

Thanks in advance
0
Comment
Question by:parnasso
  • 13
  • 11
24 Comments
 
LVL 12

Accepted Solution

by:
satsumo earned 500 total points
ID: 35107691
I've never seen this happen.  It may be that D3D is grabbing the data directly from the the display and holds up the system in a way that prevents the transparent window redrawing.  It could be holding up the GDI or preventing WM_PAINT messages getting to those windows.

Transparent windows get their WM_PAINT message after the windows beneath have updated.  If GetFrontBufferData() is causing the app window to update and then grabbing the data, there would be a pause before the transparent windows redraw.  Grabbing the data is slow and WM_PAINT messages are given low priority.

I have display grabbing code, except I'm using a lockable back buffer.  Grabing the display is done by locking the back buffer and copying data out of it.  This is still slow, but faster than GetFrontBufferData and won't interfere with the display.  It still works if the app window is off the edge of the screen or on a second monitor. GetFrontBufferData converts to D3DFMT_A8R8G8B8 if the display is 16 bit, that conversion slows things down.  Locking the surface does not convert, the program chooses a back buffer format.
0
 
LVL 4

Author Comment

by:parnasso
ID: 35107852
Satsumo:

When you say "Grabing the display is done by locking the back buffer and copying data out of it".
How do you do it? I ask you because every time I try something like that I get all black bytes.
I think it is because my application does not use Present neither does put something into the back buffer, Maybe I am wrong and you can guide me getting to know how to use the back buffer instead.

Thanks by the way
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35110379
You're using Direct 3D only to grab the display, not to render anything?
0
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 
LVL 4

Author Comment

by:parnasso
ID: 35126018
Yes, I'm using Direct 3D just to grab the display. I am not allowed to use GDI and it seemed the only way i have to grab.
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35128071
In that case locking the back buffer isn't going to help.  If this idea is to grab one window, I was going to suggest sending a WM_PRINTCLIENT message.  Except that requires creating a memory device context, which uses GDI.

How about simulating the PrintScreen key to copy an image of the active window onto the clipboard?  On the clipboard it's just DIB data, not a GDI device.  Maybe use SendKeys() to simulate pressing the PrintScreen key, not exactly sure what you would send it to, possibly the Desktop object.  You may get the same result from sending a WM_KEYDOWN message to the desktop window.

I looked at the possibility of using Still Image, Windows Image Aquisition and Video for Windows but they all appear to be concerned with capturing from external devices.

The not using GDI thing is a real sticker.  Using D3D is an inventive way around it, though I can't see how that's going to cause less trouble than using the GDI.  It means the program depends on Direct X being installed, and Direct X uses more system resource than GDI.
0
 
LVL 4

Author Comment

by:parnasso
ID: 35205282
satsumo:

I'm grateful for your help and for taking your time to answer the question. In spite of the problem itself has not been solved, because as you posted it can't be solved, your comments have been really great.
0
 
LVL 4

Author Closing Comment

by:parnasso
ID: 35205296
The solution isn't really a solution but rather a thorough explanation of why it is not going to work in the way I've planned.
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35205866
Thanks for awarding me the answer.  I would have preferred to solve the problem too.  Though I think the problem is part of Windows and Direct X.
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35205905
Actually, that started me wondering about the grabbing procedure.  How does it work exactly?  Does the program update the window then call GetFrontBuferData immediately after?  I'm wondering what would happen if it updated, then waited for a short time before calling GetFrontBufferData.  Maybe that would allow Windows enough time to send the WM_PAINT messages to the transparent windows.  Perhaps it dosen't need to update the display at all.
0
 
LVL 4

Author Comment

by:parnasso
ID: 35206768
Looks interesting. The transparent window is not actually my window; it is another program that happens to be running when I take the screenshot with GetFrontBufferData.

At the beginning I didn't realize that. It was a client of mine who found that his program disappears and then appears again, when the screenshot is done.

Any further ideas?

 
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35206981
How does this work?  Does the screen grabbing code update the display before doing the grab?  Is the client program updating then calling your program.  I'm wondering whether the display repaint is caused by Direct X, your code or the clients program.
0
 
LVL 4

Author Comment

by:parnasso
ID: 35207121
The whole thing works like this:

1. My client's program X is running on the machine. It has nothing to do with my program.
2. My program Y runs and calls GetFrontBufferData
3. X's window  disappears and then appears
4. My program Y does things with the screenshot data
5. Goto 1.

I'm sorry I didn't clarify how this work before.
0
 
LVL 4

Author Comment

by:parnasso
ID: 35207152
By the way I never call UpdateData in my program
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35208350
Ok, but I guess you create a window.  What do you attach the D3D device to otherwise.  Where is the window?
0
 
LVL 4

Author Comment

by:parnasso
ID: 35209299
Well, i just put the desktop Window

GetDesktopWindow();
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35211619
What else do you do, can you go through the rest of the details of the grabbing code?
0
 
LVL 4

Author Comment

by:parnasso
ID: 35213581
Sure.

grabbing the code looks like the following example:

3 methods of capturing the screen
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35213809
Based on that I'd assume that D3D is updating the display, though I don't see what the purpose of doing that is.  Maybe the transparent windows aren't children of the desktop window so its trying to remove them from.  Do the transparent windows appear in the screen grab?

You could try creating a window that covers the desktop and grabbing from that instead.  Maximise it and  make sure its on top of the window order, set it to have no background brush, no title, no frame etc.  Attach D3D to that and see if you can grab the display.
0
 
LVL 4

Author Comment

by:parnasso
ID: 35215018
The transparent window does not appear in the grab, which I don't really care. I just want users not to be annoyed.

In the case of creating a window that covers the desktop, on top of the windows order, what would happen to auser that is writing in the word pad? the newly created window will get those keys?

Thanks
0
 
LVL 12

Expert Comment

by:satsumo
ID: 35217540
The window would only exist when taking the screenshot, you can destroy it again as soon as your done.  Besides, it dosen't have to take the keyboard focus away from another window.  It would prevent any windows beneath it from changing the display while grabbing the screen, but that happens anyway.
0
 
LVL 4

Author Comment

by:parnasso
ID: 35230463
I'm going to give it a try. Thanks a lot
0
 
LVL 4

Author Comment

by:parnasso
ID: 35339774
I've tried creating the topmost window and capture, but still no luck. This is the code i use to create the window:

WNDCLASS wc = {0};
	wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
	wc.hbrBackground = 0;
	wc.lpszClassName = MYCLASSNAME;
	wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
	wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WinProc;
	wc.lpszMenuName = NULL;

	// Register the windows class
	RegisterClass(&wc);


	// Create the actual window
	HWND hWnd = CreateWindowEx(WS_EX_LAYERED, MYCLASSNAME, NULL, WS_MAXIMIZE | WS_POPUP, 0, 0,
		GetSystemMetrics(SM_CXSCREEN),
		GetSystemMetrics(SM_CYSCREEN),
		NULL, NULL, hInstance, NULL);

	// Show the window
	SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_TOPMOST);
	ShowWindow(hWnd, nShowCmd);
	UpdateWindow(hWnd);

Open in new window


0
 
LVL 12

Expert Comment

by:satsumo
ID: 35341322
I would put WS_EX_TOPMOST in the CreateWindow function or call SetWindowPos.  Not sure why you add it in the line below CreateWindow.  That way the style dosen't get applied until you call SetWindowPos, even if you set the style bits.

I wouldn't use WS_EX_LAYERED, WS_POPUP, CS_HREDRAW or CS_VREDRAW either.

Thanks for letting me know whats happening.  Does it manage to grab something?
0
 
LVL 4

Author Comment

by:parnasso
ID: 35349105
Its does grab the screen, but the application is still disappearing and appearing again each time the grab takes place.

We can reproduce this behavior in some machines, while in others we can't, and the user does not notice anything annoying.

Thanks a lot for your interest, satsumo .
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Parsing HTML in C# 10 153
C# Login snippet/framework recommended? 4 103
bunnyEars challenge 6 139
Fibonacci challenge 11 133
What is RenderMan: RenderMan is a not any particular piece of software. RenderMan is an industry standard, defining set of rules that any rendering software should use, to be RenderMan-compliant. Pixar's RenderMan is a flagship implementation of …
Recently, in one of the tech-blogs I usually read, I saw a post about the best-selling video games through history. The first place in the list is for the classic, extremely addictive Tetris. Well, a long time ago, in a galaxy far far away, I was…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question