Windows 7 - DWM composition + get part of desktop area obscured by a window

Asked By /dev/nul on 28-Jan-08 03:56 AM
Hi,

What I want is to get desktop's bitmap bits obscured by a window in DMW
composition on mode. Is this achievable from the application level?

Before Vista it was practically undoable, the only desperate attempt I
am aware of is Feng Yuan's "WM_PRINT hook"
(http://www.fengyuan.com/article/wmprint.html). But apart from other
flaws it doesn't support layered windows that do paint themselves using
UpdateLayeredWindow() rather than using Windows WM_PAINT paradigm.


Is this task in Windows Vista with DMW composition turned on any easier?
Needless to say the DMW has all the data to perform easily such
operation, but can this data be exported to the application? The point
is to create custom glass effect (on application level) and for this the
application needs to know the background it lays on.


Thanks,

--
Grzegorz Wróbel
677265676F727940346E6575726F6E732E636F6D




Ivan Brugiolo [MSFT] replied on 28-Jan-08 12:21 PM
When the desktop compositor is active, each top level window
is layered and redirected.
If you call BitBlt from the DC obtained from GetWindowDC(hWndTopLevel)
you will be getting a copy of the window bitmap-bits, regardless of
occlusion.

The redirection bitmap for a top-level window is currently implemented
as a DIBSECTION owned by the application, therefore mapped
in the address space of the application. If you can discover the
base-address of the mapping, you could, conceivably, do something
like ReadProcessMemory() to read the bitmap across processes.
However you should not relay on this implementation, because one day
the redirection bitmap could be a texture in aperture space, and, you would
not be able to read-it-back without cooperation with a lot of system
components.

--

--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of any included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
/dev/nul replied on 29-Jan-08 04:01 AM
It sounded too good to be to be true so I've check it. With DMW
composition on it will work indeed like that, but only in case of
(WS_EX_LAYERED style) window. If it is obscured by a layered window then
BitBlt from such window's DC will give unobscured client area, however
non-client area (frames and title bar precisely) will have the parts of
that layered window obscuring it.

It gets much worse in case of layered windows. If the window paints
itself using WM_PAINT then BitBlt form its DC will return what WM_PAINT
does, however additional information related to WS_EX_LAYERED style (ie
one set with SetLayeredWindowAttributes() like constant alpha) will be
lost. And in case of layered windows that paint themselves using
UpdateLayeredWindow() you'll only get a black rectangle.


If that's not enough this will not work with DirectX applications and
since DWM is DirectX application itself, many Windows Vista programs has
been rewritten in DirectX now (like Windows games such as Minesweeper).
For these applications BitBlt gives some unactual frame (unactual
bitmap) taken during application startup, instead of actual window's bits.


For what I want (get the background) it's not interesting, not only
because of the reasons you've mentioned, but also because it would mean
I will have to "manually" apply all the effects DWM does. Though for any
other application like printing, making screenshots for documentation,
etc. it would be interesting to have possibility to get 32bit
DIBSECTIONs (ie ability to decide what background we'll put that windows
on).

--
Grzegorz Wróbel
677265676F727940346E6575726F6E732E636F6D
Ivan Brugiolo [MSFT] replied on 29-Jan-08 05:37 PM
Let me take-in one piece at the time:

A `normal` windows will be forcefully layered by the system
when redirection and composition are started.
Normal window that do not elect any special non-client rendering policy
will have undefined content in their non-client area, because
that area will be drawn by DWM as part od the render-pass
to compose a frame for the desktop.

An Update-Layered-Window window is never supposed
to paint via WM_PAINT, and, the concept of a redirection
bitmap is not affected by redirection and desktop composition
being on or off. The visible-region calculation is different, but
the bits of the window content are always there.

A Set-Layered-Window-Attribute window is supposed to be painted
by the application in the regualar BeginPaint/EndPaint
(or GetDC/Paint/ReleaseDC) fashion, and, it's redirected content is always
present, regardless of redirection or composition.
The visible-region calculation is different, but
the bits of the window content are always there.

DirectX applications are a different beasts.
When desktop composition is OFF, the front-buffer
of their swapchains is shared with the primary.
When desktop composition is ON, depending on the present-semantic,
they will either blit the content of the current buffer of the swap-chain
to a DW-redirection surface managed by DWM, or, they will share
the swap-chain with DWM, and DWM will use that as a texture
in the dexture sampler during the render pass to produce a frame.

So, let me ask this:
what are you tring to accomplish ?
Replace `PrintWindow` ?
Get access to the redirection surfaces ?
Get access to the DWM swapchain ?

--

--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of any included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
/dev/nul replied on 29-Jan-08 11:30 PM
Something like this:
http://www.4neurons.com/other/lens4.png

Since I rather won't be able to obtain from the system the underlying
area of my window I could theoretically build it myself. But for this to
work I need to be able to render each visible window (that lies under my
program's window) exactly the same way DWM does.

Of course if there is a simpler way to achieve that I would appreciate it.

--
Grzegorz Wróbel
677265676F727940346E6575726F6E732E636F6D
Ivan Brugiolo [MSFT] replied on 30-Jan-08 05:02 AM
Did you try to read the content of the back-buffer of the device associated
with the screen to an Off-Screen-Render target, and, use that in the texture
sampler for your 3D model that build the lens ?


--

--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of any included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
/dev/nul replied on 30-Jan-08 05:54 AM
At this point this is just a layered window and the background image is
obtained by BitBlt-ing from the desktop's DC. The BitBlt call is made
without CAPTUREBLT flag, so it doesn't capture my window on pre-DWM
driver model. But it also doesn't catch any other layered windows, so
this solution is merely sweeping the real problem under the carpet. But
on Windows Vista with DWM composition on, even this non-perfect
workaround doesn't work.

Are you suggesting that for Vista I should try to rewrite this as an
DirectX application?


--
Grzegorz Wróbel
677265676F727940346E6575726F6E732E636F6D
Ivan Brugiolo [MSFT] replied on 30-Jan-08 07:15 AM
You could use DirectX to get a copy of the front-buffer, but,
you would still have the problem of excluding your window from the capture.
In Vista, you should be able to use Magnification.dll to get a view of the
desktop
filtered of the un-wanted windows.
In theory, with the image-filtering callback you should be able to provide
a curved/filtered image to the window.

--

--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of any included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
/dev/nul replied on 30-Jan-08 08:05 AM
All I need is this. I originally thought that built-in Vista magnifier
just copies bits from cursor area to Magnifier window (which is docked
outside the desktop), but now I see it can be moved over other windows
and it excludes itself from the view.

However I just noticed that for reasons uknown to me Vista magnifier
changes fonts on the desktop and in all applications...
Ok, I just got it. It looks like it disables cleartype rendering since
it does not look good when magnified...


I'll take a look at the Magnification API in the MSDN. Thanks for
pointing me to this.

--
Grzegorz Wróbel
677265676F727940346E6575726F6E732E636F6D