Updating hidden window using winapi - c++

I am creating a simple clock application. Whenever I make it disappear and restore it after a while I get an uncomfortable lag effect when my window is redrawing itself after some short period of time. I want to see changes immediately. It seems that window is not getting WM_PAINT messages while being not present on the screen (and this is actually the place I draw stuff). How to force Windows to redraw window just before showing up on the screen rather than afterwards?

Related

How to update the screen once it has lost focus

I'm working on a program that requires WM_ERASEBKGND to be disabled (to avoid flickering).
The problem comes in when my main window loses focus, and another window (another program) gains the focus.
The window that has the focus (not my program) invalidates MY program's window every time it passes over it! The result is, my window's screen turns white everywhere that another window has passed by it, leaving it almost totally blank afterward. Obviously, I cannot have a program where the screen turns white every time it loses focus.
Is there any way to continue my window's drawing operations, (continue calling wm_paint, for example) even after my window has lost focus (WM_KILLFOCUS)?
First of all, from the comments above, never send the WM_PAINT manually with SendMessage or PostMessage. Use InvalidateRect to instruct the window to be repainted.
About the WM_ERASEBKGND, the return value is used to indicate the WM_PAINT handler that the background has been erased, in case the paint procedure can be optimized. To actually prevent the background from being erased, simply do not call DefWndProc() for that message. Or even easier, set the hbrBackground to NULL in the window class.
As others mentioned the focus has nothing to do with repainting, and your window should paint normally even while in the background.

When is WM_PAINT called?

When exactly is WM_PAINT called? Im trying to create a dialog based slot machine application, but i've run into a couple of logical issues. My application will consist of:
"Spin" Button
Exit Button
Three BMP images to display the results of the spin(coin/heart/soldier)
How will i show the final result of the spin using the BMP images? Am i correct in using WM_PAINT to attempt to display the images, how will i refresh the screen each time the user presses the spin button to show the new images? I really appreciate the help!
Dialog boxes normally use DefDlgProc as the window procedure. You can't handle WM_PAINT in your DialogProc (it isn't a window procedure). You can use your own window procedure with a dialog but that's probably more trouble than it's worth.
The simplest way to display a bitmap on a dialog is to use a static control with the SS_BITMAP style.
You can change the displayed bitmap by sending the STM_SETIMAGE message to the static control. The control will take care of repainting itself with the new bitmap.
This is OK if you just want to display the result of a spin, but won't work very well if you want to animate the spinning of the reels. To handle this you could create your own static control (i.e. a window for each reel) that would display a portion of a reel bitmap.

Creating a Transparent Child window on top of non-transparent Parent Window (win32)

I have a program which is not written by me. I dont have its source and the developer of that program is developing independently. He gives me the HWND and HINSTANCE handles of that program.
I have created a child window ON his window, using win32 api.
First thing I need is to make this child window have transparency on some area and opaque on other area(like a Heads up display(HUD) for a game), so that the user may see things in both windows.
The second thing that I need is to direct all the input to the parent window. My child window needs no input.
I know that WS_EX_TRANSPARENT only makes the child draw at the end like in painters algorithm.
I cant use WS_EX_LAYERED because its a child window.
p.s.
I have looked everywhere but didn't find any solution though there were similar questions around the internet.
Actually this is a HUD like thing for that game. I can't draw directly on parent window because of the complexity with multi-threads any many other reasons.
-- EDIT ---------------------------
I am still working on it. I am trying different ways with what you all suggested. Is there a way to combine directX and SetWindowRgn() function or directx with BitBlt() function? I think that will do the trick. Currently I am testing all the stuff as a child window and a Layered window.
You can use WS_EX_LAYERED for child windows from Windows 8 and up.
To support earlier versions of windows, just create a level layered window as a popup (With no chrome) and ensure its positioned over the game window at the appropriate location. Most users don't move the windows they are working with all the time, so, while you will need to monitor for the parent window moving, and re position the HUD, this should not be a show stopper.
Not taking focus (in the case of being a child window) or activation (in the case of being a popup) is more interesting, but still quite do-able:- The operating system does not actually automatically assign either focus, or activation, to a clicked window - the Windows WindowProc always takes focus, or activation, by calling SetFocus, or some variant of SetActiveWindow or SetForegroundWindow on itself. The important thing here is, if you consume all mouse and non client mouse messages without passing them on to DefWindowProc, your HUD will never steal activation or keyboard focus from the Game window as a result of a click.
As a popup window, or a window on another thread, you might have to manually handle any mouse messages that your window proc does get, and post them to the game window. Otherwise, responding to WM_NCHITTEST with HTTRANSPARENT (a similar effect to that which WS_EX_TRANSPARENT achieves) can get the system to keep on passing the mouse message down the stack until it finds a target.
OK friends, finally I did some crazy things to make it happen. but its not very efficient, like using DirectX directly for drawing.
What I dis:
Used (WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_ TOOLWINDOW) and () on CreateWindowEx
After creating the window, removed (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE) from window styles, and also removed (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_APPWINDOW) from extended window styles.
This gives me a window with no borders and its also now shown in the taskbar. also the hittest is passed to whatever that is behind my window.
Subclassed the window procedure of the other window and got the
WM_CLOSE,WM_DESTROY, to send the WM_CLOSE or WM_DESTROY respectively to my window
WM_SIZE,WM_MOVE, to resize and move my window according to the other window
WM_LBUTTONUP,WM_RBUTTONUP,WM_MBUTTONUP, to make my window brought to the top, and still keep focus on the other window, so that my window doesn't get hidden behind the other window
Made the DirectX device have two passes:
In the first pass it draws all the elements in black on top of a white background and copy the backbuffer data to an another surface (so it give a binary image of black & white).
In the second pass it draws the things normally.
Another thread is created to keep making the window transparency by reading that black & white surface, using the SetWindowRgn() function.
This is working perfectly, the only thing is it's not very good at making things transparent.
And the other issue is giving alpha blending to the drawn objects.
But you can easily set the total alpha (transparency) using the SetLayeredWindowAttributes() function.
Thanks for all the help you guys gave, all the things you guys told me was used and they guided me, as you can see. :)
The sad thing is we decided not to use this method because of efficiency problems :(
But I learned a lot of things, and it was an awesome experience. And that's all that matters to me :)
Thank You :)
You can make a hole in the parent window using SetWindowRgn.
Also, just because it is not your window doesn't mean you can't make it a layered window.
http://msdn.microsoft.com/en-us/library/ms997507.aspx
Finally, you can take control of another window by using subclassing - essentially you substitute your Wndproc in place of theirs, to handle the messages you wish to handle, then pass the remainder to their original wndproc.

Constraining window position to desktop working area

I want to allow a user to drag my Win32 window around only inside the working area of the desktop. In other words, they shouldn't be able to have any part of the window extend outside the monitor(s) nor should the window overlap the taskbar.
I'd like to do it in a way that does cause any stuttering. Handling WM_MOVE messages and calling MoveWindow() to reposition the window if it goes off works, but I don't like the flickering effect that's caused by MoveWindow().
I also tried handling WM_MOVING which prevents the need to call MoveWindow() by altering the destination rectangle before the move actually happens. This resolves the flickering problem, but another issue I run into is that the cursor some times gets aways from the window when a drag occurs allowing the user to drag the window around while the cursor is not even inside the window.
How do I constrain my window without running into these issues?
Windows are, ultimately, positioned via the SetWindowPos API.
SetWindowPos starts by validating its parameters by sending the window being sized or moved a WM_WINDOWPOSCHANGING message, and then a WM_WINDOWPOSCHANGED message notifying the window proc of the changed size and/or position.
DefWindowProc handling of these messages is to, in turn, send WM_GETMINMAXINFO and then WM_SIZE or WM_MOVE messages.
Anyway, handle WM_WINDOWPOSCHANGING to filter both user, and code, based attempts to position a window out of bounds.
Keep in mind that users with multi-monitor setups may have a desktop that extends into negative x- and y-coordinates, or that is not rectangular. Also, some users use alternative window managers such as LiteStep, which implement virtual desktops by moving them off-screen; if you try to fight this, your application will break for these users.
You can do this by handling the WM_MOVING message and changing the RECT pointed to by the lParam.
lParam: Pointer to a RECT structure with the current position of the window, in screen coordinates. To change the position of the drag rectangle, an application must change the members of this structure.
you may also want to handle WM_ENTERSIZEMOVE to know when the window is beginning to move, and WM_EXITSIZEMOVE
WM_GETMINMAXINFO is what you seem to be looking for.

OpenGL window cleared with no WM_PAINT message

I have an application with three MDI windows, all of them showing OpenGL content. On XP, everything works fine. But on Vista/Win7 the mdi child windows don't refresh properly.
After startup, all windows show their content properly. But when I change the focus from one mdi window to the next, those two windows are cleared (i.e., they only show white, no content). I have no idea why the windows get cleared, they don't receive any WM_* message when that happens, and of course don't receive a WM_PAINT message either.
When resizing those windows, I correctly get the WM_PAINT message (after WM_SIZE) and redraw the content, but then the window gets cleared too, which results in a strange flicker while resizing. After resizing stopped, the window stays cleared (white) until I manually force a refresh.
This happens independently of Aero enabled or disabled.
Any idea why this happens?
I'm surprised it works on XP. In my (limited) experience dabbling with OpenGL, WM_PAINT is not always the best place to redraw OpenGL scenes. Most likely the content is getting wiped out at the driver level. You can check for this by seeing what happens when one of your MDI windows happens to span two monitors connected to two different video cards.
Try the following:
Reinitialize your OpenGL contexts after WM_SIZE occurs.
Draw on-demand instead of in WM_PAINT. In your handler for WM_PAINT, do nothing. Use a timer or some other mechanism to periodically trigger updates of your displays.
Flicker is usually caused by interference via WM_ERASEBKGND. If you haven't already, intercept WM_ERASEBKGND and do nothing in the regions where you are displaying OpenGL content.
Use the CS_OWNDC window style on any windows hosting OpenGL content so that the HDC doesn't change per-message/per-call during the lifetimes of your MDI windows.
Other rarer causes of interference that might apply (since you are using MDI windows)
WM_NCPAINT and other related Non-Client drawing messages- you can workaround these by moving your OpenGL content to a child window with no border, inside the MDI windows.
Incorrect/Incompatible default features for OpenGL on your video card that explicitly require overlays or implicitly use them (frequent cause of issues in overlapping contexts). Unfortunately, diagnosing this out of my realm of knowledge, but some testing may shed some additional light here.