How to prevent direct2d “stretching” the view when window size changed? - c++

I am rendering text with ID2D1HwndRenderTarget.
When there is a change of the UI window size, I want to prevent the stretch of the text being rendered - so it will be unchanged until I will directly make a rendering command.
On Direct2D documentation the behavior is described:
If EndDraw presents the buffer, this bitmap is stretched to cover the
surface where it is presented: the entire client area of the window
I know the ID2D1HwndRenderTarget::Resize method but I don't want to update the size immediately, just going to use it later on according to my program needs.
How can I ignore windows events to prevent this visual stretch?

You are already ignoring size change messages, and that's why surface size does not match client area size when presenting. You can try to offset this effect by setting target resolution according to "client area / current target size" factor, right before doing EndDraw(). I have no idea if that will help, or what will happen to uncovered window area outside of current target rectangle.

Related

DirectX9 window resize in runtime without device reset

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.

Having trouble keeping my CToolBar subclass sized correctly

My objective is to have a CToolBar derivative which has a single control on it (a CMFCShellTreeCtrl).
Something like:
class CFileTreeBar : public CToolBar
Whenever it is asked to compute its size, I want to respond that it is either a fixed minimum, or the size of the client area of the dock bar to which it is docked. In other words, it should consume the entire height of the dock bar + a fixed width (this is being docked on the left - exactly as Explorer lays out its folder tree on the left).
Hence, in CFileTreeBar::CalcFixedLayout it responds with height based on GetParent()->GetWindowRect(rect), and a width of 250pix.
Then in OnSize, the CFileTreeBar resizes its CMFCShellTreeCtrl to consume our client rect (maximizes our only control).
This works beautifully for when the control bar is initially displayed. And it works great when resizing the window by dragging a corner. The CaclFixedLayout returns a different value from its previous value (because the window size changed) and so it computes that it should consume the entire vertical space and eventually I get an WM_SIZE message telling my control bar to resize, which causes me to update the size of the CMFCShellTreeCtrl.
Where I am struggling is when hitting "maximize" button on the CFrameWnd. In this case, for reasons I don't really understand, the CalcFixedLayout is called but the dock bar has its old size (it hasn't been updated to the new sized based on being maximized yet). This causes my code to respond that the size should be the same as it was previously - which causes MFC frame work to not issue a resize (we're already the size we claim we need to be).
Hence, a moment later the dock bar is expanded to consume the whole vertical space, but my control bar and its underlying shell tree are not resized - but left behind with the stale size.
The problem happens also when going from maximized to restored. At that point the call to CalcFixedLayout indicates that we should be as tall as the maximized window (its current size), and now the frame work kicks off the resizing code which ends up making us larger than the dock bar (once it is resized down to restored size), and we disappear below the bottom of the dock bar (clipped by it's maximum vertical extent).
Questions
Is there a good tutorial or white paper showing the overview of how dockbars and control bars are supposed to interact in MFC? i.e. a complete description of how this frame work is supposed to hang together properly? Understanding how these pieces fit together and are intended to work coherently would go a long way towards avoiding hacking it to work, allowing me to write something round to fit the round hole, so to speak.
Is there an example project similar to this that anyone is aware of? Having to figure this junk out is incredibly time consuming - if there is an example somewhere which does this, then that would be great...
Dockable and resizable toolbar is quite complicated to code, there is one in codeproject which is quite good. You can study the source code to see how the author do it.
http://www.codeproject.com/Articles/6/CSizingControlBar-a-resizable-control-bar

winapi - How to use LayeredWindows properly

I am haveing trouble understanding the concept of the UpdateLayaredWindow api, how it works and how to implement it. Say for example I want to override CFrameWnd and draw a custom, alpha blended frame with UpdateLayeredWindow, as I understand it, the only way to draw child controls is to either: Blend them to the frame's Bitmap buffer (Created with CreateCompatibleBitmap) and redraw the whole frame, or create another window that sits ontop of the layered frame and draws child controls regularly (which defeats the whole idea of layered windows, because the window region wouldn't update anyway).
If I use the first method, the whole frame is redrawn - surely this is inpractical for a large application..? Or is it that the frame is constantly updated anyway so modifying the bitmap buffer wouldn't cause extra redrawing.
An example of a window similar to what I would like to achieve is the Skype notification box/incoming call box. A translucent frame/window with child contorls sitting ontop, that you can move around the screen.
In a practical, commercial world, how do I do it? Please don't refer me to the documentation, I know what it says; I need someone to explain practical methods of the infrastructure I should use to implement this.
Thanks.
It is very unclear exactly what aspect of layered windows gives you a problem, I'll just noodle on about how they are implemented and explaining their limitations from that.
Layered windows are implemented by using a hardware feature of the video adapter called "layers". The adapter has the basic ability to combine the pixels from distinct chunks of video memory, mixing them before sending them to the monitor. Obvious examples of that are the mouse cursor, it gets super-imposed on the pixels of the desktop frame buffer so it doesn't take a lot of effort to animate it when you move the mouse. Or the overlay used to display a video, the video stream decoder writes the video pixels directly to a separate frame buffer. Or the shadow cast by the frame of a toplevel window on top of the windows behind it.
The video adapter allows a few simple logical operations on the two pixel values when combining their values. The first one is an obvious one, the mixing operation that lets some of the pixel value overlap the background pixel. That effect provides opacity, you can see the background partially behind the window.
The second one is color-keying, the kind of effect you see used when the weather man on TV stands in front of a weather map. He actually stands in front of a green screen, the camera mixing panel filters out the green and replaces it with the pixels from the weather map. That effect provides pure transparency.
You see this back in the arguments passed to UpdateLayeredWindow(), the function you must call in your code to setup the layered window. The dwFlags argument select the basic operations supported by the video hardware, ULW_ALPHA flag enables the opacity effect, the ULW_COLORKEY flag enables the transparency effect. The transparency effect requires the color key, that's specified with the crKey argument value. The opacity effect is controlled with the pblend argument. This one is built for future expansion, one that hasn't happened yet. The only interesting field in the BLENDFUNCTION struct is SourceConstantAlpha, it controls the amount of opacity.
So a basic effect available for a layered window is opacity, overlapping the background windows and leaving the partially visible. One restriction to that the entire window is partially opaque, including the border and the title bar. That doesn't look good, you typically want to create a borderless window and take on the burden of creating your own window frame. Requires a bunch of code btw.
And a basic effect is transparency, completely hiding parts of a window. You often want to combine the two effects and that requires two layered windows. One that provides the partial opacity, another on top and owned by the bottom one that displays the parts of the window that are opaque, like the controls. Using the color key to make its background transparent and make the the bottom window visible.
Beyond this, another important feature for custom windows is enabled by SetWindowRgn(). It lets you give the window a shape other than a rectangle. Again it is important to omit the border and title bar, they don't work on a shaped window. The programming effort is to combine these features in a tasteful way that isn't too grossly different from the look-and-feel of windows created by other applications and write the code that paints the replacement window parts and still makes the window functional like a regular window. Things like resizing and moving the window for example, you typically do so by custom handling the WM_NCHITTEST message.

How to efficiently render double buffered window without any tearing effect?

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

Black flicker while resizing translucent Qt widget (only when Aero is enabled)?

I have a top-level Qt widget with the FramelessWindowHint flag and the WA_TranslucentBackground attribute set. It has several children, each of which draws an image on it. They are not in a layout. Instead, I simply move them around when something changes (it is not user-resizable).
There are two states to the window - a big state and a small state. When I switch between them, I resize the window and reposition the children. The problem is that as the window resizes, a black box is briefly flashed on the top-level window before the images are painted over it.
The problem goes away if I disable Aero. I found brief mention of this problem being fixed in an article describing a new release of Qt (this release is long past), but it still doesn't work.
Any ideas why?
Thanks!
I don't have experience with Qt specifically, but I have worked with other windowing toolkits. Typically you see this kind of flashing when you are drawing updates directly to the screen. The fix is to instead use Double buffering, which basically means that you render your updates into an offscreen buffer (a bitmap of some sort, in the purest sense of the word), and then copy the entire updated image to screen in a single, fast operation.
The reason you only see the flickering sometimes is simply an artifact of how quickly your screen refreshes versus how quickly the updates are drawn. If you get "lucky" then all the updates occur between screen refreshes and you may not see any flicker.