Overlay window drawing which appears in screen captures of other applications - windows

We need to overlay a target window with a custom shape and tracks the position of the target window such that the overlay drawing always appears above it. Also, the overlay drawing should appear in screenshots taken using BitBlt or PrintClient by screen-capturing tools like Camtasia, Debut, etc. Also, moving the target window around should not leave traces of the drawing at earlier location. The target window is not made using our code.
So far we've tried several ways but each method has its problems:
1) Layered Window:
Using a layered window as the child/owned window of the target window is the easiest thing and it works. But the problem is on Windows 7 and XP, layered windows do not appear in a BitBlt done without the CAPTUREBLT flag and the screen-capturing tools may call BitBlt without the flag, thereby skipping our window from the capture.
2) Region Window:
The crude approach to support all Windows versions then is to use a region window using SetWindowRgn and make the target window its owner. However, region windows are generally very slow in rendering complex shapes and also impact the performance of other windows, sometimes to the point of freezing the application. Region window also leaves traces on dragging the application window.
3) Subclassing and Drawing on HDC:
Another approach is to sub-class the target window and draw the shape on its HDC on the OnPaint() event inside the window procedure hook. The shape can be drawn on the desktop window instead too. The problem is that applications may draw without a paint event, like when some text is selected using the cursor, and such drawing may erase a part of the custom drawing. Tracking all possible paint events is not a good way to do this.
4) Drawing continuously in a timer:
The last resort is to draw the custom shape on the target window in a timer continuously so the drawing is always above the target, even on text selection. But this may show a bit of flicker when the text is selected. Not to mention, it is very performance heavy to draw constantly.
Question
What is the best way to achieve an overlay drawing which works on all Windows versions (since XP) at the same time appearing in screen-captures. We've exhausted all approaches. Is there some method I'm missing? Can the above mentioned ways be used with some improvement? Is DirectX an option? I'm looking for methods with fast rendering capacity to achieve this. Appreciate any help!

I think the best solution to draw an overlay window, is to use a double-buffered technique GDI, just like in this example:
Overlay Drawing in CScrollView
I have myself the same task, and the only solution was that one. Hope it help you.

Related

Can we avoid WM_PAINT when using ScrollWindow in win32?

I am new to win32 programming and have a very naive question.
Say there is my application window of size 1920x1280 and I create a child window over it of size 1920x2560 (double of vertical screen size). Now I load an image onto this child window which has the same size as that of child window i.e 1920x2560.
Now my question is If I use ScrollWindow for vertical scroll, will I necessarily need to repaint the dirty rect (the bottom part), since the image would be already loaded? Is it not possible to avoid that and just move the screen buffers ? Or is there any other way possible to avoid redrawing, may be using bitmaps or something?
An application draws in a window when scrolling, changing, or
selecting a portion of the displayed
data
but you could only draw the differences in the Update Region.
It's also noted that disabling the default handling for the WM_ERASEBKGND message makes smooth.
The disadvantage of your idea is always drawing outside of client area and how to just move the screen buffers to avoid redrawing?

How to draw a custom shaped window using Qt and apply current Windows theme colors/effects to it?

Is it possible to draw a custom shaped window in Qt which inherits color and transparency (glass) effects from current system theme. Ultimately I need it to look & feel just like user's taskbar adjusting to his theme. Like in this concept. I realize that it might not be possible to achieve such perfect integration, but at least make a custom shaped background which look the same as the taskbar (glass look&feel) I believe is achievable.
Partially it is answered in similar questoin - Displaying translucent / irregular-shaped windows with Qt. But still not sure how to read system theme information and apply it to QPainter.
The tricky part is that slope on the left. I'd wager you could get a title bar on a window to be taller and have the rest of the window be 0 height so the window was entirely a title bar but that slope would require rendering functions that just won't exist on Windows.
Also, you're wanting your window hide the taskbar's bevel under where your window appears. That will probably not be possible either as your window will be semi-transparent so it won't be able to block the rendered bevel of the normal taskbar.
Sorry. Might have to go back to the drawing board on your design.

Direct2D: leave a region of a window render target untouched

I am drawing to a regular HwndRengerTarget but other windows, which have nothing to do with Direct2D, overlap it.
The problem is that these windows get painted over when I draw to the HwndRengerTarget.
I would like to tell Direct2D not to touch a specific region of the HwndRengerTarget (i.e. don't touch the pixels that are already on the screen), so that these windows remain correctly visible.
Is that possible?
If I draw normally then call RedrawWindow on the windows, it flickers a lot.
Thanks.
If you want to manually restrict your rendering to a certain region you can use layers (ID2D1Layer objects).
More info here Layers Overview
If the visible region is rectangular it may be simpler to use axis aligned clips via methods PushAxisAlignedClip and PopAxisAlignedClip.
ID2D1RenderTarget::PushAxisAlignedClip
Another method of restricting drawing to a certain shape is to render it to a bitmap and then use this bitmap via a bitmap brush in the FillGeomtry method.
ID2D1RenderTarget::FillGeometry
Why not arrange the windows (HWNDs) so that the Direct2D one is at the bottom of the z-index? It should be the first child of its parent. Then clipping will be automatic. You may need the WS_CLIPSIBLINGS window style.
I had the same problem.
Fixed by calling CreateWindowEx LAST for the D2D child HWND.
So AFTER all the other child windows are created.

Skinned Window: Win32 API and DirectX

I'm trying to create a borderless window using a WS_EX_LAYERED style window. The objective is to render graphics using DirectX directly to the desktop, using alpha to blend onto the current desktop windows.
Now on my system this technique seems to work perfectly. I can set various alpha levels and achieve different levels of transparency. Unfortunately several users have reported severe performance problems and low frame rate, making this technique unusable.
The code setup is as follows:
Create a layered (WS_EX_LAYERED extended-style) window.
Initialize DirectX using the window HWND.
Create a render target using the CreateRenderTarget DirectX method.
Then during the render loop:
Render graphics to the render target using DirectX calls.
Get the HDC handle to the DirectX render target surface using GetDC method.
Update the window contents using the UpdateLayeredWindow function, specifying the DirectX surface HDC.
My question is: Am I doing something wrong? Is there a way to improve the performance of the window update. I have tried various things, like locking the render target and manually copying the bits to a DIB section to display in the window area, without success.
How big is your window? Note MSDN's documentation at http://msdn.microsoft.com/en-us/library/windows/desktop/ms633556%28v=vs.85%29.aspx says "For best drawing performance by the layered window and any underlying windows, the layered window should be as small as possible."
You may be getting a performance boost if compositing (Aero) is enabled. If Windows is already compositing, it won't have to do as much extra work to draw layered windows.
If you're not seeing any difference in performance depending on compositing, then I am probably completely off base here.

How do I perform my own redraw in the Paint event of a VB6 PictureBox?

A coworker is encountering an error when he tries to run a VB6 app we're working on. The error is, "480: Can't create AutoRedraw image". Microsoft's documentation says this is because "There isn't enough available memory for the AutoRedraw property to be set to True. Set the AutoRedraw property to False and perform your own redraw in the Paint event procedure or make the PictureBox control or Form object smaller..."
Making the PictureBox smaller isn't an option. I'd be glad to "...perform my own redraw in the Paint event procedure...", but I'm not sure how to go about it. Can someone show me the way?
Without details this will be a simplistic answer. In general most beginning VB6 programmers use AutoRedraw=True draw in responds to some input. Fill out some data, click draw, and it appears in the picture box.
The click event in the Draw Button is linked do your drawing code. The first step is move the call to the drawing code to the paint event of the picture. The second step is to replace all calls to the drawing code with MyPictureBox.Refresh. Refresh forces the paint event of that picture box to fire.
The main problem you will have to be concerned with is that the paint event is going to be fired everytime the form needs refreshed. Like if a window covering it is moved. This means that any speed issue in your drawing code will be exposed. AutoRedraw=True takes what you drew and puts in a hidden bitmap that the PictureBox uses to display what you drew.
The Paint event will execute each step of your drawing process so you have to make sure you are as fast as possible. Depending on how dynamic your application is the worse slowdown issues will become. If you are displaying a static image then the problem isn't as bad.
Making the PictureBox smaller isn't an option. I'd be glad to "...perform my own redraw in the Paint event procedure...", but I'm not sure how to go about it. Can someone show me the way?
That is easy. You just implement the _Paint()-Event of your Form or PictureBox and draw.
Because you are asking, i think i should clarify what the AutoRedraw-Propeprty does. If it is set to true, you can "just draw your image" any way you want. In multiple steps. Whatever. If it needs to be redrawn, for example, because another windows was on top it, it will be magically done. The down site is, that is slow, for the drawing part.
If AutoRedraw is false, no magic will happen. The Paint()-Event will be fired and you are responsible to draw your image again. This will be much faster, if your window is not "invalidated" (e.g. "covered") often. Or you are doing a lot of drawing.
Or you are running out of memory for the "magic space" ;-)
If you don't mind rewriting your graphics code to use the GDI API - this could be a fairly big task - I found this thread from 2006 in the VB6 discussion group, where Mike Sutton said in answer to a similar problem:
VB's back-buffer implementation uses a
Device Dependant Bitmap (DDB) to store
the image data, which is quite limited
in how large it can be made. On older
OS' this used to be ~16mb uncompressed
data size, on later OS this has been
expanded but is still quite
restrictive.
A workaround for this is to use a
Device Independent Bitmap (DIB) and
manage the GDI resources yourself,
have a look at the DIB article on my
site for an example of how to work
with them.
I haven't tried it myself.
There's usually a drop-down box of events for your control in the forms code window. You need to pick the paint event:
Private Sub object_Paint()
and fill in your your code for drawing on the PictureBox.

Resources