Content lost when window is repainted - c

I am currently messing around with the windows API in C. I thought it would be funny to make a simple chalkboard. Everything is working fine. It's drawing etc, etc.
The problem is that the contents are lost when the window is repainted/updated/resized...
I thought maybe I should save the HDC or something, but then I don't know how to put it back.
How do I solve this? I figured it shouldn't be a very difficult question to answer, yet I can't really find anything on google somehow.

You need to handle the WM_PAINT event and repaint the invalidated region in its entirety. That's what WM_PAINT is -- a request from the system to redraw a dirty region.
For your specific application it sounds like you should create an off-screen device context (CreateCompatibleDC), a corresponding bitmap (CreateBitmap) of the size of your canvas, do all the drawing operations there and call InvalidateRect on your window. When WM_PAINT fires call BitBlt to transfer the relevant portion of that bitmap to the screen.

Related

Why this BitBlt example doesn't work anymore?

I'm currently getting back to some Windows Programming using Petzold's book (5th edition).
I compiled the following example using BitBlt and it doesn't work as it is supposed to.
It should copy the Window's icon of (CxSource, CySource) size and replicate it on the whole window's surface.
What happens, in reality, using Windows 7 is that the bitmap below the window gets sourced and copied into the drawing surface i.e. hdcClient.
I don't understand why it behaves like this knowing that it's clear the DC passed to BitBlt is hdcWindow, which refers to a device context obtained via a GetWindowDC(hwnd) of the current application.
I first thought it was due to the fact the transparency mode is enabled by default, but deactivating it doesn't change anything. BitBlt seems to always take the surface below the application Window!
I don't get it! :)
Anyone knows why it works that way and how to fix it?
Making screenshots with BitBlt() did not exactly get any easier since the addition of the DWM (Desktop Window Manager, aka Aero). Petzold's sample code suffers from a subtle timing issue, it is making the screenshot too soon. It does so while Aero is still busy animating the frame, fading it into view. So you see what is behind the window, possibly already partly faded depending on how quickly the first WM_PAINT message is generated.
You can easily fix it by disabling the effect:
#include <windows.h>
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
And after the CreateWindow() call:
BOOL disabled = TRUE;
DwmSetWindowAttribute(hwnd, DWMWA_TRANSITIONS_FORCEDISABLED, &disabled, sizeof(disabled));
Another tricky detail is that the first BitBlt matters, the DWM returns a cached copy afterwards that is not correctly invalidated by the animation.
This gets grittier when you need a screenshot of a window that belongs to another process. But that was already an issue before Aero, you had to wait long enough to ensure that the window was fully painted. Notable perhaps is the perf of BitBlt(), it gets bogged-down noticeably by having to do job of composing the final image from the window back-buffers. Lots of questions about that at SO, without happy answers.
It is not supposed to copy the windows icon, it is supposed to copy the windows titlebar part where the icon is located.
There are some issues with this (now 20 year old code):
GetSystemMetrics values cannot be used for window related dimensions anymore since GetSystemMetrics returns the classic sizes, not the Visual Style sizes.
Depending on the Windows version, the DWM might define the window size as something larger than your window (where it draws the window shadow and other effects).
Your example works OK on XP:
(There is a small problem because the titlebar is not square (unlike Windows 98/2000 that this example was designed for) so you see a issue in the top left where it is just white. I also modified the example slightly so it varies the HDC source location)
On a modern version of Windows it seems like the DWM or something is not able to properly emulate a simple window DC and parts of the shadow/border/effects area is part of the DC:
I don't know how to fix this but the example is pretty useless anyway, if you want to draw the window icon you should draw the HICON with DrawIconEx. If you want to draw custom non-client area stuff then you need to find more recent examples, not something that only supports the classic theme.

Windows Runtime equivalent to WriteableBitmap's AddDirtyRect

I'm building an app where I would like to redraw the image on screen around a user's finger touch. System.Windows.Media.Imaging.WriteableBitmap has a method AddDirtyRect(Int32Rect dirtyRect) to indicate to indicate changes my code has made to the back buffer so that the whole image needn't be redrawn. Its Windows Runtime equivalent, the Windows.UI.Xaml.Media.Imaging.WriteableBitmap class, does not.
Can I tell the system which part of the screen to redraw as the result of code changing a Windows.UI.Xaml.Media.Imaging.WriteableBitmap?
No, this API isn't there. You could use a secondary patch bitmap to update only a portion of the rendered output. If you need more control over what gets pushed out to the buffers you'd need to use a SwapChainPanel and DirectX.

Delete or Remove a line using Xlib library

Assume that we draw a line in Xlib using the XDrawLine API, what is the best way to remove or delete the line?. Are there any dedicated API's for this or do we have to use a special implementation of the the same XDrawLine API?
Thanks in Advance for your responses.
You can draw a line the color of the background (e.g, white) over the top of another line to "erase" it, but there's no way to restore the original graphics that were there before you drew the first line — Xlib does not keep a history.
In general, though, your application should be able to do a full "repaint" of the window at any time (e.g, if the window is resized or minimized, or if it is "damaged" by another window crossing over it). What you're asking makes it sound like your application may not be able to do this right now, which will prevent it from working correctly in some situations.
The best way would be to draw to off-screen pixmap and remember state (or pixmap copy) before you draw the line. Delete line == draw offline pixmap to that state ( or just copy saved pixmap back to screen )

GTK: Get pointer position on scroll-event AFTER scrolled_window has scrolled

I've got a drawing area inside a scrolled window (with convenience viewport),
and this drawing area updates itself according to incoming motion-notify-events.
When I scroll the area though obviously no motion events are emitted,
but I wanted to work around this, and so tried to connect the drawing area's
"scroll-event" signal to the same motion-notify callback.
The problem I'm facing here is that this signal is emitted before the scrolled window
has update its viewport, so in the callback, I end up with pointer coordinates that were true just before scrolling, making it look like the drawing area is always "lagging a step behind" the actual pointer when scrolling while not moving the pointer itself.
I thought I could compensate for this by manually extracting the coordinates with gdk_window_get_pointer, but then I realized this cannot work as the pointer is technically still at its old position when the callback is commencing.
I also tried using g_signal_connect_after in hopes it would have the callback get called after the viewport was scrolled, but it didn't help.
My last hope would be to start a timer on scroll-events, and have the callback fire after a minimal amount of time, but this sounds realllly ugly, and I'd like to avoid that at any cost.
Any ideas as to how this could be realized?
Thanks in advance!
A solution would be to connect to the "value-changed" signal of the GtkScrolledWindow
adjustments.
Source: https://mail.gnome.org/archives/gtk-app-devel-list/2011-September/msg00014.html

WPF performance issue when resizing the window with lots of controls

I have a WPF window that contains a fancy image with roughly 200 controls (derived from buttons), all of which use one of my 5 templates (paths, shadow effects, etc). Agreed, it is a heavy window to draw. I can live with that.
My problem comes from resizing the window. Maximize/Restore take about 1-2 seconds, but manually dragging the bottom-left corner causes the system to hang for about 5-10 seconds. In that delay, the window is black & contains partial leftovers until the final result is shown. It looks amateurish and that, I can't live with.
Remote connection : using a remote account, I found that the window resize always takes 1-2 seconds, but doesn't draw the "intermediate" stages while I'm dragging the window borders. The result is as snappy as I would expect.
My conclusion is this: It's the redraws during the resize that are bottlenecks.
The inevitable question is this : how can I prevent redrawing the window until the resize is finished?
Thanks in advance for any ideas...
#Seb: I'm beginning to think WPF is
not designed for interfaces that go
beyond 2-3 controls at a time
Visual Studio 2010 and Expression Blend should be good counterexamples. Though Visual Studio sometimes freezes the bottleneck is definitely not in the WPF rendering.
#Seb: The inevitable question is this : how
can I prevent redrawing the window
until the resize is finished?
Simply set the window's content visibility to Visibility.Collapsed before the resize/maximize and make it visible afterwards. Though I think you asked the wrong question. Here is the right one
How to make my controls measure/arrange extremely fast?
And to answer it you should take a look at your code. Maybe you intensively use dependency properties in the measuring/arrange algorithm? Or maybe you picked wrong panels (e.g. Grid is slower than Canvas)? Or maybe... I stop guessing here :).
By the way, it's always better to launch your app under profiler and prove the bottleneck rather than assuming the place where it might be. Check Eqatec Profiler it's free yet powerful enough. VS 2010 also offers nice profiling features, though it's far from being free. And you may want to check WPF Performance Suite.
Hope this helps.
Let me know how this works... I am assuming that your root visual item is stretching to horizontally and vertically to fill your window with auto height/width. Get rid of the Auto height/width. On app start up set the dimensions of the root element. There is a FrameworkElements have a size changed event. Register for this on your Application.Current.MainWindow (maybe be a typo, that was from memory). Whenever this event fires, start a timer with a small interval. If you get another resize while the timer is running, ignore it and reset the timer. Once the timer fires, you now know the new size the user desires and that they have (at least for a short period) stopped resizing the window.
Hope that helps!
From Ragepotato's answer and your comment about needing to see roughly what the interface would look like while resizing, as long as you don't have your objects dynamically re-locating themselves (like a Wrap Panel) - you could take a screenshot of the window contents and fill your frame with it.
Set it to stretch both height and width, and you'd get a (slightly fuzzy) idea of what a particular size would be. It wouldn't be live while resizing, but for those few seconds that probably wouldn't matter..

Resources