PDA

View Full Version : Read content of a rendering context created by a "third" application



Dancer3
02-09-2015, 02:26 AM
Hello,

I want to read the content (image) of a rendering context that was created by a "third" application and copy it to a DC in my application.
I can not influence the "third" - the only information I have is the window handle (and therefore a DC of that window).

If I create a rendering context based on this DC, I get a rendering context - but depending on who draws last either my drawing or the drawing of the "third" application is visible ==> I get a "different" rendering context.

Is it possible to get the original rendering context of the "third" application?
And if "yes": How?

Thanks in advance :)

Shinta
02-10-2015, 05:21 AM
Basically: No

The only 3 functions in WGL that return a rendering context are:
HGLRC wglCreateContext(HDC hdc);
HGLRC wglCreateLayerContext(HDC hdc, int iLayerPlane);
HGLRC wglGetCurrentContext();

The first two will create a new rendering context, so you'll never get a used one out of them. The third function returns the currently 'current' context of the calling thread. So, unless you find a way the invoke this function (at the right moment) in the right thread of your "third" application, AND return the result to your application, this function isn't much use either.

I don't know, if there is a WGL extension that returns one rendering context specific to a window and thread, or all the rendering contexts used in the whole system, but I've my doubts.

On the other hand: Why try this with OpenGL? Can't you just read/copy the resulting content (image) of the device context via 'BitBlt' (GDI function)?

Dancer3
02-10-2015, 06:39 AM
Thanks for your response and summary.

Regarding the available API I agree with you, but - on the other hand:
For windows (OS) it is possible to read the dynamic content of the window (even if it is not in foreground) and displays it as the "applications thumbnail" that is displayed when I move my mouse over the icons in the task bar.

'BitBlt' does not work, as the area I am interested in is handled by OpenGL (I've tested this already and did not get the image of the third application form). A "cross check" with a GDI drawn application (the "windows calculator" in my test case) instead worked fine. An other aspect against BitBlt is the "pixel" ownership". I can not be sure, that the "third" application is always in the foreground - and the result "BitBlt" returns would then only be the area of the form, but not necessary the content of it.

Alfonse Reinheart
02-10-2015, 09:00 AM
For windows (OS) it is possible to read the dynamic content of the window (even if it is not in foreground) and displays it as the "applications thumbnail" that is displayed when I move my mouse over the icons in the task bar.

Right. It's possible for Windows to do that because, you know, it's the OS.

For the rest of us, not so much.

Or at least, not without cheating. There are applications that can somehow read data from D3D and OpenGL applications. I have no idea how these guys do it, but they're not using normal APIs. Certainly nothing that's a part of either D3D or OpenGL.

Shinta
02-10-2015, 10:53 AM
Also, there is no garantee that a window is repainted while minimized or occluded by other windows. It depents on the application if it refreshes it's window content by a timer or just on WM_PAINT events, and than only the regions it wants refresh. The task bar forces the application to refresh when the icon/thumbnail is needed. (On the other hand you could do that too, by sending WM_PAINT messages to that window.)

On the 'BitBlt' issue: What Windows and graphic adapter/driver do you use? Haven't encountered this since Win2k but some OpenGL implementations used overlay techniques, where windows only recieved a windows with a 'magic' color instead of the rendering result. Also, there are other ways to do the 'screenshot', I have not read up on them, but I think you'll find other ways in DirectX and GDIPlus. Maybe they work better.

On the problem: You could trick the application with an intermediate-dll that wraps all the stuff in opengl32.dll. Than you can act on (wgl)SwapBuffers-calls, read the framebuffer with glRead and send the result somehow to your app.
Or even worse: You could try to inject the necessary code into the running 'third' application. Hock the (wgl)SwapBuffers-calls ... (evil)