im using SetPixel to make stuff on my window which is the easyest because i only want to set one pixel at a time. SetPixel is great but i need to remove the color every time i update it, i could overwrite the color by black but.. it's a really big waste of time is there some way i can over write all of the colors to black? (i would like something that is faster then reseting them all to black). i make a window and then color with setpixel (there is other ways (to draw on the window) but i only want to set one pixel/color at a time)
You should typically create a bitmap, lock it, set and unset its pixels directly - possibly by direct access rather than using API calls, if there are a lot of updates - unlock and then invalidate the window so that your paint handler can blit the bitmap later.
If you want to restore pixels, you can keep two bitmaps and store the values to restore in one bitmap.
Related
In: C++\Win32 application (not in fullscreen)\DX9
How can i redraw window content during resize fast and nice enough? Resize == user drag window border.
Different approaches:
Reset device on each WM_SIZE\WM_PAINT. Adequate resolution, but black stripes appears on fast upscale.
Reset device on WM_EXITSIZEMOVE and pause rendering on WM_ENTERSIZEMOVE. Best speed, but to ugly ~ black stripes during resize.
Can't find out how to use dx9's swapchain in this case
Keep rendering and swapping buffers during resize; reset on WM_EXITSIZEMOVE. Exactly what occurs in official demos from 2010 SDK. Looks fast and acceptable nice. But [suddenly] on slow computer black stripes reappeared. Thin and rare, but real. Actually, thats very strange: synchronous rendering and Present(,,,) on every WM_SIZE and\or WM_PAINT excludes that at first glance. And at the second. Perhaps i dont understand something important?
So, when last method failed i decided to ask here. Is that possible somehow make dx9 surface securely glued to window border. No black stripes. Prefer to slow scale speed down, but sync it somehow with DX.
I allocate a backbuffer large enough for the maximum client size of the window, and set a viewport that matches the current window client size on WM_SIZE. Then I render to resp. present from that viewport only. This way no device reset is required.
I have to display an image and text overlay, when text overlay contains many strings, but only one changes from frame to frame. I want to avoid redraw of the entire overlay and only update what has changed.
I tried wglCreateLayerContext but my GPU seems to not support it (PIXELFORMATDESCRIPTOR bReserved is 0).
What is the most efficient way to redraw only part of text overlay?
Redrawing the whole framebuffer is the canonical way in OpenGL. You can use Framebuffer Objects (FBO) to create several off-screen drawing surfaces, to which you render the individual layers. Then you composit the layers into a composite image presented on screen.
but only one changes from frame to frame. I want to avoid redraw of the entire overlay
Why? Figuring out what parts need redraw, masking them, do only a partial clear, updating it, etc. takes more time and effort than to simply redraw the whole text overlay.
I'm thinking of creating a drawing program with layers, and using GDI+ to display them. I want to use GDI+ because it supports transparency.
The thing is, drawing lines to the DC is very fast, but drawing directly to a bitmap is very slow. It is only fast if you lock the bits and start setting pixels. Can I draw to multiple DC's in my WM_PAINT event, then just do DrawBitmap for each layer to the MemDC? What's the best way of going about this?
Thanks
GDI+ is certainly fast enough for a drawing program. I use it (from C#) for high-speed animation (>30 fps).
It appears that you want to be able to manipulate individual pixels. This is very fast with LockBits, and although it's slightly clunky to use in C# (requiring a pointer and the unsafe tag), it doesn't seem like it would be as difficult in C++.
You probably don't want to copy from multiple layers directly to your control surface inside a paint event. Instead, this rendering should be done to an off-screen buffer (B1). After B1 is drawn with all copying/drawing operations completed, copy it to a second off-screen buffer (B2) and then invalidate/refresh your control surface. In the control's paint event, you copy from B2 to the visible surface.
You don't want to draw directly on the visible surface with a multi-step drawing operation, since a form of flickering will result (sometimes the screen will repaint itself while your code is only partway through a multi-step operation, so the user sees an occasional half-finished frame).
You can render to a single off-screen buffer, and copy from it to the visible surface in the paint event. The main complication here is that you have to deal in some way with "stray" paint events, i.e. events not caused by your intentionally invalidating the control but by something else (like a user dragging another window over yours). If you copy from the off-screen buffer to the surface and the buffer is only halfway-drawn, you'll get flicker. If you block in the paint event until the buffer drawing is completed, you'll see "form trails" on your control, which looks even worse.
The solution is the double-buffered approach described above. Stray (or non-stray ones when you invalidate) paint events will copy from B2, which is always fully-rendered and up-to-date - thus no flicker. Double-buffering does use more memory, but in a drawing program that has multiple layers anyway, this isn't a big deal.
I'm creating a non-intrusive popup window to notify the user when processing a time-consuming operation. At the moment I'm setting its transparency by calling SetLayeredWindowAttributes which gives me a reasonable result:
alt text http://img6.imageshack.us/img6/3144/transparentn.jpg
However I'd like the text and close button to appear opaque (it doesn't quite look right with white text) while keeping the background transparent - is there a way of doing this?
In order to do "proper" alpha in a layered window you need to supply the window manager with a PARGB bitmap by a call to UpdateLayeredWindow.
The cleanest way to achieve this that I know of is the following:
Create a GDI+ Bitmap object with the PixelFormat32bppPARGB pixel format.
Create a Graphics object to draw in this Bitmap object.
Do all your drawing into this object using GDI+.
Destroy the Graphics object created in step 2.
Call the GetHBITMAP method on the Bitmap object to get a Windows HBITMAP.
Destroy the Bitmap object.
Create a memory DC using CreateCompatibleDC and select the HBITMAP from step 5 into it.
Call UpdateLayeredWindow using the memory DC as a source.
Select previous bitmap and delete the memory DC.
Destroy the HBITMAP created in step 5.
This method should allow you to control the alpha channel of everything that is drawn: transparent for the background, opaque for the text and button.
Also, since you are going to be outputting text, I recommend that you call SystemParametersInfo to get the default antialiasing setting (SPI_GETFONTSMOOTHING), and then the SetTextRenderingHint on the Graphics object to set the antialiasing type to the same type that is configured by the user, for a nicer look.
I suspect you'll need two top level windows rather than one - one that has the alpha blend and a second that is display above the first with the opaque text and button but with a transparent background. To accomplish this with a single window you'll need to use the UpdateLayeredWindow API call, but using this will cause your buttons to not redraw when they are interacted with (hover highlights, focus etc.)
It is possible that if this application is for Vista only there is a new API call that you can use, but I do not believe it is available in XP or earlier.
I can't say for sure, you'll need to try it, but since everything is a window, you could try setting the layered attributes for your button to make it opaque.
As for the text, you may be able to put that in its own frame with a set background and foreground color, and modify its layered attributes to make the background color transparent...
But since these are child windows and not the top-level window, I really don't know that it'll work.
When drawing child controls containing bitmaps with per-pixel alpha channels, we are getting quite a lot of flickering whenever they need to be redrawn. The actual blending is working correctly. I've found a lot of info about reducing flicker (such as this question or this site), but I can't seem to find anything that applies specifically to this situation.
For example, I've got a button with a few different bitmaps that are alpha blended and blitted to the window, depending on the state of the button. When their state changes and I need to draw a different bitmap, I need to redraw the background first, or else it blends with pixels left over from the previous state's bitmap. This is where I am getting some flickering, where I get a bit of the background tearing in occasionally.
The problem is made more complicated by having the top-level parent windows drawing a bitmap background, rather than a solid color, along with the possibility of having child controls overlapping; just multiplying the underlying color into the child's bitmap is out of the question, as is using WS_CLIPCHILDREN.
Since the windows have a bitmap background, I'm returning true on WM_ERASEBKGND, to avoid drawing a color that will just be overwritten.
Of course, double buffering would seem to solve all of this, but I have not been able to get it to work right. I've set WS_COMPOSITED for top-level windows, and WS_TRANSPARENT for child windows. When it comes time to redraw a child window with a new bitmap, I am having a few issues (most likely from me not understanding how the draw order is working in this situation):
If I call InvalidateRect() and pass the child handle, the child window is indeed redrawn, but the background is not redrawn, and so the pixels accumulate on top of each other, blending together.
If I call InvalidateRect() and pass in the parent handle, with a rectangle consisting of the child window's dimensions, the background is redrawn, but the child window is not.
If I do both of the above, then the background is redrawn as well as the child window, and it looks exactly as I'd want -- except that by doing so, I've managed to make it flicker again (which isn't really surprising, since it seems terribly hackish to call InvalidateRect() twice like that, as I'd guess that each call is probably causing the buffers to flip, which defeats the purpose).
What I've come to conclude is that I don't really understand how I need to modify my program to handle double buffering, or if double buffering will even help with this situation. I feel like it definitely would, but I don't quite understand how I need to modify things to get everything to play nicely again.
Are you using layered windows? If not maybe try it out.
Also for double buffering consider this technique.
This could be completely off base - my gui days were a long long time ago...
But couldn't you just precompute the blends for your different states? I assume your button can be enabled/disable and up/down, so that's only 4 combinations. Why not precompute the combined bitmaps?
Or is the problem the interaction of already combined bitmaps with the existing state?