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.
Related
I have an app that mixes OpenGL with Motif. The big main window that has OpenGL in it redraws fine. But, the sub windows sitting on top of it all go black. Specifically, just the parts of those subwindows that are right on top of the main window. Those subwindows all have just Motif code in them (except for one).
The app doesn't freeze up or dump core. Data is still flowing, and as text fields, etcetera of various subwindows get updated, those parts redraw. Dragging windows across each other or minimizing/unminimizing also trigger redraws. The timing of the "blackout" is random. I run the same 1-hour dataset every time and sometimes the blackout happens 5 minutes into the run and sometimes 30 minutes in, etc.
I went through the process of turning off sections of code until the problem stopped. Narrowed it down more and more and found it had to do with the use of the depth buffer. In other words, when I comment out the glEnable(GL_ENABLE_DEPTH_TEST), the problem goes away. So the problem seems to have something do with the use of the depth buffer.
As far as I can tell, the depth buffer is being cleared before redrawing is done, as it should. There's if-statements wrapped around the glClear calls, so I put messages in there and confirmed that the glClear of the depth buffer is indeed happening even when the blackout happens. Also, glGetError didn't return anything.
UPDATE 6/30/2014
Looks like there's still at least one person looking at this (thanks, UltraJoe). If I remember correctly, it turned out that it was sometimes swapping buffers without first defining the back buffer and drawing anything to it. It wasn't obvious to me before because it's such a long routine. There were some other minor things I had to clean-up, but I think that was the main cause.
How did you create the OpenGL window/context. Did you just get the X11 Window handle of your Motif main window and created the OpenGL context on that one? Or did you create a own subwindow within that Motif window for OpenGL?
You should not use any window managed by a toolkit directly, unless this was some widget for exclusive OpenGL use. The reason is, that most toolkits don't create a own sub-window for each an every element and also reuse parts of their graphics resources.
Thus you should create a own sub-window for OpenGL, and maybe a further subwindow using glXCreateWindow as well.
This is an old question, I know, but the answer may help someone else.
This sounds like you're selecting a bad visual for your OpenGL window, or you're creating a new colormap that's overriding the default. If at all possible, choose a DirectColor 24-plane visual for everything in your application. DirectColor visuals use read-only color cells, but 24 planes will allow every supported color to be available to every window without having to overwrite color cells.
I have a wxWidgets application that has a number of child opengl windows. I'm using my own GL canvas class, not the wx one. The windows share their OpenGL context.
I don't think the fact it is wxwidgets is really relevant here.
The opengl windows are children of a windows that are siblings of one another, contained within a tab control. Kind of an MDI style interface, but it is not an MDI window.. Each one can be individually resized. All works lovely unless Aero is enabled and the DWM is active.
Resizing any window (not even the opengl ones) causes all of the opengl windows to flicker occasionally with a stale backing-store view that contains whatever rubbish has been on the screen at that point that is not opengl. This ONLY happens with Aero enabled.
I'm pretty certain that this is the DWM not actually having the opengl contents on its drawing surface backing store and the window not being repainted at the right moment.
I've tried so many things to get round this, I do have a solution but it is not very nice and involves reading the framebuffer with glReadPixels into a DIB and then blitting it to the paint DC in my onPaint routine. This workaround is only enabled if DWM is active but I'd rather not have to do this at all as it hurts performance slightly (but not too bad on a capable system - the scenes are relatively simple 3d graphs). Also mixing GDI and opengl is not recommended but this approach works, surprisingly. I can live with it for now but I'd rather not have to. I still have to do this in WM_PRINT if I want to take a screenshot of the child window anyway, I don't see a way around that.
Does anyone know of a better solution to this?
Before anyone asks I definitely do the following:
Window class has CS_OWNDC
WM_ERASEBACKGROUND does nothing and returns TRUE.
Double Buffering is enabled.
Windows have the WS_CLIPSIBLINGS and WS_CLIPCHILDREN window styles.
In my resize event handler I immediately repaint the window.
I've tried:
Setting PFD_SUPPORT_COMPOSITION in the pixel format descriptor.
Not using a wxPaintDC in the paint handler and calling
::ValidateRect(hwnd, NULL) instead.
Handling WM_NCPAINT and excluding the client area
Disabling NC paint via the DWM API
Excluding the client area in the paint event
Calling glFlush and/or glFinish before and after the buffer swap.
Invalidating the window at every paint event (as a test!) - still
flickers!
Not using a shared GL context.
Disabling double buffering.
Writing to GL_FRONT_AND_BACK
Disabling DWM is not an option.
And as far as I am aware this is even a problem if you are using Direct3D instead on OpenGL, though I have not tested this as it represents a lot of work.
This is a longshot, but I just solved exactly this same problem myself.
The longshot part comes in because we're doing owner draw of the outline of a captionless group box that surrounds our OpenGL window (i.e., to make a nice little border), and that may not describe your case.
What we found caused the problem was this:
We had been using a RoundRect() call (with a HOLLOW_BRUSH) to draw the outline of the group box. Changing it to a MoveToEx() and LineTo() calls to ensure JUST the lines are drawn and nothing gets done inside the group box kept the GDI from trying to unexpectedly repaint the whole content of the control. It's possible there's a difference in invalidation logic (or we had a bug somehow in loading the intended hollow brush). We're still investigating.
-Noel
My app has only a single OpenGL window (the main window) but I ran into some nasty DWM tearing issues on window resize and I wonder if one of the solutions may work for you.
First of all, I found that during window resize there are at least two different bad guys who want to "help" you by modifying your client area before you have a chance to update the window yourself, creating flicker.
The first bad guy dates back to a XP/Vista/7 BitBlt inside the SetWindowPos() that Windows does internally during window resize, and can be eliminated with a trick involving intercepting WM_NCCALCSIZE or another trick involving intercepting WM_WINDOWPOSCHANGING.
In Windows 8/10 we still have that problem but we have a new bad guy, the Aero DWM.exe window manager, who will do his own different kind of BitBlt when he thinks you are "behind" updating the screen.
I suspect that the rubbish pixels you are seeing might actually be an intentional and very very poor attempt by DWM to fill in something "acceptable" while it waits for you to draw. I discovered that DWM extends the edge pixels of old client area data when it blits the new client area, which is insane.
Unfortunately, I don't know of any 100% solution to prevent DWM from doing this, but I do have a timing hack that greatly reduces the frequency of it.
For source code to the WM_NCCALCSIZE/WM_WINDOWPOSCHANGING hack as well as the DWM timing hack, please see:
How to smooth ugly jitter/flicker/jumping when resizing windows, especially dragging left/top border (Win 7-10; bg, bitblt and DWM)?
Hmm, maybe you have ran into the same issue: if you are using "new" MFC
it will create and application with Tabs and Window Spliter.
The splitter has some logic (I am guessing somewhere around transparent window and drawing XOR
lines for the split) that causes this behavior. Remove the splitter to confirm it resolve
your issue. If you need split functionality -- put in a different splitter.
Also Tabs allow docking and again splitting the windows that has the same issue -- remove/replace.
Good luck,
Igor
I want to create my own tiny windowless GUI system, for that I am using GDI+. I cannot post code here because it got huge(c++) but bellow is the main steps I am following...
Create a bitmap of size equal to the application window.
For all mouse and keyboard events update the custom control states (eg. if mouse is currently held over a particular control e.t.c.)
For WM_PAINT event paint the background to offscreen bitmap and then paint all the updated controls on top of it and finally copy entire offscreen image to the front buffer via Graphics::DrawImage(..) call.
For WM_SIZE/WM_SIZING delete the previous offscreen bitmap and create another one with new window size.
Also there are some checks to prevent repeated drawing of controls i.e. controls are drawn only when it needs repainting in other words when the state of a control is changed only then it is painted e.t.c.
The system is working fine but only with one exception...when window is being resizing something sort of tearing effect appears. Now what I mean by tearing effect I shall try to explain ...
On the sizing edge/border there is a flickering gap as I drag the border.It is as if my DrawImage() function returns immediately and while one swap operation is half done another image drawing starts up.
Now you may think that it is common artifact that happens in many other application for the fact that resizing backbuffer is not always as fast as resizing window are but in other applications I noticed in other applications that although there is a leg between window size and client area size as window grows in size nothing flickers near the edge (its usually just white background that shows up as thin uniform strips along the border).
Also the dynamic controls which move with window resize acts jerky during sizing.
At first it seemed to me that using a constant fullscreen size offscreen surface could minimize the artifact but when I tried it results are not that satisfactory. I also tried to call Sleep() during sizing so that the flipping is done completely before another flip starts but strangely even that won't worked for me!
I have heard that GDI on vista is not hardware accelerated, could that might be the problem?
Also I wonder how frameworks such as Qt renders windowless GUI so smoothly, even if you size a complex Qt GUI window very fast negligibly little artifact appears. As far as I know Qt can use opengl for GUI rendering but that is second option.
If I use directx then real time resizing is even harder, opengl on the other hand seems to be nice for resizing without any problem but I will loose all the 2d drawing capability of GDI+.
If any of you have done anything like this before please guide me. Also if you have any pointer that I should consider for custom user interface design then provide me the links.
Thanks!
I always wished to design interfaces like windows media player 11 but can someone tell me that there is a straight forward solution for a c++ programmer (I want to know how rather than use some existing framework etc.)? Subclassing, owner drawing, custom drawing nothing seems to give you such level of control, I dont know a way to draw semitransparent control with common controls, so I think this question deserves some special attention . Thanks again.
Could it be a WM_ERASEBKGND message that's causing it?
see this question: GDI+ double buffering in C++
Also, if you need fast response from your GUI I would advise against GDI+.
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.
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...