Draw on screen with GDI+ (or GDI) similar to Inspect - c++

I'm trying to draw on the screen (the whole screen, on top of every other window) using GDI+.
I've passed NULL to GetDC to get a HDC to the screen, and then used that to create a Graphics object, and used DrawRectangle to draw rectangles on the screen.
Everything works..except...the inside of the rectangle won't update.
Like if I draw it over a command prompt, and move the command prompt, the inside of the rectangle remains black.
I expect to see whats under the rectangle.
Here's the code that's doing the drawing..
Pen BluePen(Color(255, 0, 255, 0), 2);
Graphics graphics(screenDC);
graphics.DrawRectangle(&BluePen, myRect);
Pretty simple, so is there something I have to do to get the inside of the rectangle to update when the screen does? Or to get it truely transparent.
================= EDIT =================
Well I had given up on this, and assumed it wasn't possible, until...I realized the Inspect tool that comes with the Windows SDK does this perfectly.
I would like to recreate something similar to the highlight rectangle, and if I select a window (such as Firefox) and then bring Inspect into focus I can move it around freely with everything being updated perfectly.
There's not even any flickering.
So...does anyone know how Inspect manages to do this?
Also answers in GDI instead of GDI+ are fine...

In windows the screen (and the windows ...) surface(s) are ... volatile, like sandboxes. The "overlapping" of windows and the re-painting of uncovered surfaces is an illusion made by proper event management.
Everything is drawn remain there until something else is drawn over it.
"Uncovering" a surface makes the window representing that surface to receive a WM_PAINT message. It's up to that window procedure to react to that message by re-painting everything is supposed to be under it.
Now, unless you intercept somehow the WM_PAINT message that is sent to the desktop window, you have mostly no chance to know the desktop needs a repaint and hence your paint code will not be called and no repaint will happen. Or better it happens following just the desktop window updating code, that's not aware of your paint.

Related

Keep Wingdi graphics permanent

I am making a C++ console application with lots of wingdi graphics mainly revolving around Rectangle() and FillRect() but as it is wingdi, the graphics are not permanent. The graphics get reset when i minimize the console, enlarge it, scroll down and whatsoever. I've seen in some threads that there is no predefined solution so you have to make one of your own.
One thing i tried, was drawing the rectangle once and then attaching a thread with infinite loop that checks the first pixel of rectangle in every iteration, if it's color is black, it draws whole rectangle again. As silly as it sounds, that's all i could think of. I know it's utterly inefficient. Is there any other solution for this?
Although you've been able to use GDI to draw on your application's console window (presumably by calling GetConsoleWindow and then GetDC), it isn't really designed for that. The system has code for the console window that tries to redraw the window itself whenever it needs to update. It's not aware of anything your program does through GDI, so it has no way to preserve that.
If you just need to draw colorful rectangles on a console window, you can do those kinds of things with the Console API. You can set the text colors as needed and draw blocks of spaces or block characters.
If you want to do more general graphics, your program will have to create a (non-console) window, and then you can draw whatever you want whenever your window receives a WM_PAINT message.

Drawing on the screen

I'm currently developing an application with OpenCV to do visual recognition of elements on the screen.
While a visual representation of the process is not needed, it would be very useful for debugging purposes if I could find a way to draw circles, lines and possibly text directly on the screen, without having an app window.
There are certain applications that, for instance, draw HUDs over the screen. How do they go about doing that?
I need a way for my drawing to always be at the front. In general, all the ways I managed to find involve painting on a window (WinAPI, Direct2D, OpenGL). Is there a workaround to make it appear like it's simply a layover on the desktop (including all open windows)?
for the purpose of debugging, just literally draw on the screen. IIRC GetDC(0) will get you a device context for the screen, but check out that whole family of functions. in Windows 7 it doesn't even foul up other applications' displays, and reportedly it's likewise "safe" on the mac.
for example, this draws an ellipse in the upper left of the screen:
#include <windows.h>
int main()
{
HDC const dc = GetDC( 0 );
Ellipse( dc, 10, 10, 200, 200 );
}
the graphic disappears if it's on top of a window and that window is moved.
You can achieve the device context (DC) of the screen, and draw in that DC as usual. The output will be directed to the screen. To achieve that, call WinApi GetDC("DISPLAY"), if i'm not mistaken.

Strange winAPI behaviour

I have sub classed a tab control to give it a background. I have used the clipping functions to clip the drawing area to the update region. This works, except for when I move the window of the screen and back again.
When it does this, it occasionally sets the clipping region to the whole screen. This is fine except that none of the controls redraw and end up hidden behind the background. How do I know whether or not to redraw the background when I get this update region. It would be 100x easier to develop this if I saw the source code for the tab control, but that isn't going to happen.
All help or suggestions welcome, but I really do need a straight-forward answer.
By "clipping region" I assume you mean the area that has to be redrawn that windows passes to you.
Try this: The paint message handler should bitblit the area of the background image that corresponds to the part of the window that needs to be refreshed (so you don't draw over things that don't need updating). Then let the base class handle the rest.
If it's setting the repaint region to the entire window the tab control code should redraw everything after you've painted the background.
Having code to look at would help

Getting empty update rectangle in OnPaint after calling InvalidateRect on a layered window

I'm trying to figure out why I've been getting an empty update rectangle when I call InvalidateRect on a transparent window. The idea is that I've drawn something on the window (it gets temporarily switched to have an alpha of 1/255 for the drawing), and then I switch it to full transparent mode (i.e. alpha of 0) in order to interact with the desktop & to be able to move the drawing around the screen on top of the desktop.
When I try to move the drawing, I get its bounding rectangle & use it to call InvalidateRect, as such:
InvalidateRect(m_hTarget, &winRect, FALSE);
I've confirmed that the winRect is indeed correct, and that m_hTarget is the correct window & that its rectangle fully encompasses winRect.
I get into the OnPaint handler in the class corresponding to m_hTarget, which is derived from a CWnd. In there, I create a CPaintDC, but when I try to access the update rectangle (dcPaint.m_ps.rcPaint) it's always empty. This rectangle gets passed to a function that determines if we need to update the screen (by using UpdateLayeredWindow in the case of a transparent window).
If I hard-code a non-empty rectangle in here, the remaining code works correctly & I am able to move the drawing around the screen.
I tried changing the 'FALSE' parameter to 'TRUE' in InvalidateRect, with no effect. I also tried using a standard CDC, and then using BeginPaint/EndPaint method in my OnPaint handler, just to ensure that CPaintDC wasn't doing something odd ... but I got the same results.
The code that I'm using was originally designed for opaque windows. If m_hTarget corresponds to an opaque window, the same set of function calls results in the correct (i.e. non-empty) rectangle being passed to OnPaint. Once the window is layered, though, it doesn't seem to work right.
I think I've figured it out - it's a combination of a limitation of Windows + some odd code in the internal framework I'm using. I have to ignore the empty rectangle & use the entire screen's rectangle instead - it seems to work fine.
Sorry if I wasn't clear enough with my initial question - I'll try to be more precise the next time.

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...