How do I render a win32 window to an opengl texture? - c++

I want to be able to render a win32 control inside an OpenGL texture. In order to be able to 3d transform it. Specifically I want to embed Internet explorer to show webpages and video inside a 3D transformed window.
How do I render a win32 window to a texture in a fast enough way (I need to keep 60 fps)?

There are a few ways you can go about it. In all cases, you will need to fetch a device context (DC) from the target window (GetDC, GetDCEx).
Then, you can either read the pixels directly (GetPixel); or blit the contents into your own DC (BitBlt) and then access that (e.g. GetDIBits).
Since you want to "embed" Internet Explorer, and by that you probably mean keeping its window hidden; you will want to consider how to make the above work on windows that are not visible, partially visible, etc. Consider as well your Windows version and/or whether the DWM might be disabled (and therefore the content of a window may not be available). Take a look at PrintWindow to force a WM_PAINT/WM_PRINT.
One small MSDN guide that can introduce you to all this and has a full example is: Capturing an Image.
In any case, you can always go for an alternative solution by embedding some other browser/engine as a library (e.g. Chromium Embedded Framework (CEF), Qt's WebEngine, Electron...).

Related

DirectComposition render to texture?

I would like to have directcomposition render to a texture. Is this possible?
The reason for this is that I would like to be able to render a gpu accelerated windowless transparent flash player activex control to a texture. Something that is usually not possible, but which I hope to achieve with DirectComposition.
It's unlikely that this is possible, to quote MSDN (emphasis mine)
DirectComposition does not offer any rasterization services. An application must use some other software-based or hardware-accelerated rasterization library such as Direct2D or Direct3D to populate the bitmaps that are to be composed. After composing, DirectComposition passes composed bitmap content to Desktop Window Manager (DWM) for rendering to the screen.
As far as I know there are only official APIs to share your offscreen surfaces with DWM, but no API allowing you to get read-access to a DWM surface.
What DWM does allow you is redirecting HWND surfaces, so you can display the surfaces of other HWNDs on your window. This can be done either through DirectComposition (via CreateSurfaceFromHwnd) or the DWM API (via DwmRegisterThumbnail). For an example of the latter look here.
If you want to go the "hacking route" as indicated in your comment, there are undocumented APIs which look like they can give you access to the DWM surfaces, in particular DwmpDxGetWindowSharedSurface sounds promising. Someone else already did some reverse engineering and figured out the signature, but couldn't get it to work (texture works but renders black). This guy seems to have had more luck and was able to render window textures in 3d. I don't understand his language but you seem to have to use DwmpDxUpdateWindowSharedSurface (also undocumented).
You should be aware however that using undocumented functions is not a good idea, Microsoft can change them anytime (even in service pack releases) or remove them completely, since they are only used by Microsoft themselves they have no reason to maintain compatibility. Also there is a good chance that you are going to use them wrong (e.g. you might be missing necessary synchronization and cause random crashes, or worse).
However since the functionality is actually available there is hope that Microsoft may actually open it for puplic use in some future version of Windows.

Creating a program that creates a full screen overlay

I want to write a program that would create a transparent overlay filling the entire screen in Windows 7, preferably with C++ and OpenGL. Though, if there is an API written in another language that makes this super easy, I would be more than willing to use that too. In general, I assume I would have to be able to read the pixels that are already on the screen somehow.
Using the same method screen capture software uses to get the pixels from the screen and then redrawing them would work initially, but the problem would then be if the screen updates. My program would then have to minimize/close and reappear in order for me to be able to read the underlying pixels.
Windows Vista introduced a new flag into the PIXELFORMATDESCRIPTOR: PFD_SUPPORT_COMPOSITION. If the OpenGL context is created with an alpha channel, i.e. AlphaBits of the PFD is nonzero, the alpha channel of the OpenGL framebuffer is respected by the Windows compositor.
Then by creating a full screen, borderless, undecorated window you get this exakt kind of overlay you desire. However this window will still receive all input events, so you'll have to do some grunt work and pass on all input events to the underlying windows manually.

Draw OpenGL on the windows desktop without a window

I've seen things like this and I was wondering if this was possible, say I run my application
and it will show the render on whatever is below it.
So basically, rendering on the screen without a window.
Possible or a lie?
Note: Want to do this on windows and in c++.
It is possible to use your application to draw on other application's windows. Once you have found the window you want, you have it's HWND, you can then use it just like it was your own window for the purposes of drawing. But since that window doesn't know you have done this, it will probably mess up whatever you have drawn on it when it tries to redraw itself.
There are some very complicated ways of getting around this, some of them involve using windows "hooks" to intercept drawing messages to that window so you know when it has redrawn so that you can do your redrawing as well.
Another option is to use clipping regions on a window. This can allow you to give your window an unusual shape, and have everything behind it still look correct.
There are also ways to take over drawing of the desktop background window, and you can actually run an application that draws animations and stuff on the desktop background (while the desktop is still usable). At least, this was possible up through XP, not sure if it has changed in Vista/Win7.
Unfortunately, all of these options are too very complex to go in depth without more information on what you are trying to do.
You can use GetDesktopWindow(), to get the HWND of the desktop. But as a previous answer says (SoapBox), be careful, you may mess up the desktop because the OS expects that it owns it.
I wrote an open source project a few years ago to achieve this on the desktop background. It's called Uberdash. If you follow the window hierarchy, the desktop is just a window in a sort of "background" container. Then there is a main container and a front container. The front container is how windows become full screen or "always on top." You may be able to use Aero composition to render a window with alpha in the front container, but you will need to pass events on to the lower windows. It won't be pretty.
Also, there's a technology in some video cards called overlays/underlays. You used to be able to render directly to an overlay. Your GPU would apply it directly, with no interference to main memory. So even if you took a screen capture, your overlay/underlay would not show up in the screen cap. Unfortunately MS banned that technology in Vista...

Is is possible to make a shaped, alpha-blended dialog?

I'm making a non-rectangular dialog, modelled over an image from Photoshop (the image is the background of the dialog, and the user will see trough the transparent part of the image). I'ts like a dashboard-style window for a media-app with a few custom-drawn controls. Most of the background-image is either opaque or 100% transparent - but in between there is a thin area of partially transparent pixels, ment to blend the image smootly into the background. This works great for web-graphics, but I have not found a way to make this work for Windows windows. I'm using the Windows Template Library (WTL), msvc 2008 - and the app must run on Windows XP as well as Vista and Windows 7.
Currently, I'm simply using the opaque part of the background-image to create a GDI clipping-region, but this gives pretty rough edges.
Does anyone know about any API functions to accomplish this (part of WTL, or reachable from WTL)?
Perhaps you could use layered windows? I haven't tested these with WTL but you should be able to get the effect you want. To the best of my knowledge I don't think you can add controls to a layered window so you'll need to attach it to another (non-layered) window to use controls.
Not sure how this interoperates with WTL, but have a look at the AlphaBlend function. You'll need to select your partially transparent bitmap into a DC and copy that to your dialog's DC in your paint function.
This article shows how to use layered windows with WTL and the Gdi+ API which is available on all your target platforms.

Shatter Glass desktop Win32 effect for windows?

I would like a win32 program that takes the desktop and acts like it is shattering glass and in the end would put the pieces back together is there way reference on Doing this kind of effect with C++?
I wrote a program (unfortunately now lost) to do something like this a few years ago.
The desktop image can be retrieved by creating a DC for the screen, creating a compatible bitmap, then using BitBlt to copy the screen contents into the bitmap. Then use GetDIBits to get the pixels from this bitmap in a known format.
This link doesn't do exactly that, but it demonstrates the principle, albeit using MFC. I couldn't find a Win32-specific example:
http://www.flounder.com/screencapture.htm
For the shattering effect, best to use Direct3D or OpenGL. (Further details are up to you.) Create a texture using the bitmap data saved earlier.
By way of window for associating with OpenGL or D3D, create a borderless window that fills the entire screen and doesn't do painting or background erasing. This will prevent any flicker when switching from the desktop image to the copy of the desktop image being used to draw.
(If using D3D, you'll also find GetMonitorInfo useful in conjunction with IDirect3D9::GetAdapterMonitor and friends, as you'll need to create a separate device for each monitor and you'll therefore need to know which portion of the desktop corresponds to that device.)