Solved

Screen capture with Directx makes transparent Windows to disappear

Posted on 2011-03-11
24
1,472 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
 
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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

The following diagram presents a diamond class hierarchy: As depicted, diamond inheritance denotes when two classes (e.g., CDerived1 and CDerived2), separately extending a common base class (e.g., CBase), are sub classed simultaneously by a fourt…
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 …
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

757 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now