AFX_WM_DRAW2D messages when screen is asleep - c++

I have a problem with a progress bar that is implemented through adding a D2D object in MFC library.
I set up a message map to my function that keeps redrawing the progress bar based on some calculations:
BEGIN_MESSAGE_MAP(CProgressControl, CStatic)
ON_WM_PAINT()
ON_REGISTERED_MESSAGE(AFX_WM_DRAW2D, &CProgressControl::OnDraw2D)
END_MESSAGE_MAP()
My problem is that when the user locks out of the computer and the screen is asleep my drawing function does not seem to be called. It seems that the D2D notification message AFX_WM_DRAW2D is never sent to redraw when the screen is asleep.
I have tried to search for information on this online but did not find anything good about what might happen differently when the screen is asleep. I would appreciate any insight anyone might have on this.

Seems to me like this could be a normal behavior. Do you get any messages when your app is minimized or the computer is locked? I suspect that not.
Anyways, why should this bother you? Obviously your progress bar is invisible at the time, so why bother with the panting? You should be happy - Windows has an optimization for your program.
However if you do anything else besides painting in the painting messages, then I'd advise moving it elsewhere, as it is not that right place for it anyway. Paint message handlers should ONLY contain paint logic, and be prepared to be called at any time (or not at all).

Search the MFC sources for AFX_WM_DRAW2D and you'll see in wincore.cpp that the message is sent from a method called CWnd::DoD2DPaint() inbetween the render target's BeginDraw and EndDraw calls.
Therefore call DoD2DPaint to force a repaint. I did this on the sample CMFCD2DWalkthroughView (http://msdn.microsoft.com/en-us/library/gg482848.aspx) in the OnSize method to ensure that the gradient is updated and painted when the window is resized instead of the size/paint being out of sync.

Related

GLFW Window poll events lag

I have a problem handling GLFW poll events. As far as I know, all user input events are handled via callbacks or via constantly checking keyboard / mouse states. The latter is not so efficient an can even result in missing some input (e. g. when button pressed and then released between checking state). What is more, some events like window resizing cannot be handled without callbacks.
So, the problem is that whenever user starts resizing window (presses mouse button but doesn't move mouse), the app seems to freeze. This is, assuming resize callback is enabled and defined validly (even when copied right from GLFW API). And the problem is not that window doesn't redraw. Redraw on callback can be done with creating and calling own render() function in callback function.
The actual problem is that even when I handle resize event properly and redraw on callback, there is still some lag. This lag is after mouse press on decorated window border and when mouse is not moving. Here's a demonstration (button click is highlighted green):
Sorry for messed up GIF. All callbacks listed in GLFW API are enabled and handled (window-, input-, joystick- and monitor-callbacks) and redraw is called in each one. It seems that I'm missing some of the callbacks or GLFW just works like that.
According to this answer, this can't be done without threading:
That only works when the user moves the mouse while holding - just holding left-click on the resize window part still stalls. To fix that, you need to render in a separate thread in addition to this. (No, you can't do that without threading. Sorry, this is how GLFW works, no one except them can change it.)
So, the questions are:
How can I fix this issue without threading? If I can't, I guess I can emulate resizing with different cursors shapes and resizing zones or smth like that...
If this is still impossible to solve in GLFW, do other GLFW alternatives have this issue?
Are there any problems with GLFW similar to this one?
GLFW is not at fault here. It's how the operating system handles certain user input events like mouse down on the decorator resize handles of a window or moving the whole window.
See this answer for a more elaborate detail: Win32: My Application freezes while the user resizes the window
GLFW uses the standard Windows PeekMessage -> TranslateMessage/DispatchMessage loop which you will find in any GUI Windows application. This will get invoked when you call glfwPollEvents() and it processes all Window event messages that the OS has accumulated so far for all windows in this process. After all messages so far have been processed, the call to glfwPollEvents() will return and will allow your own window/game loop to continue.
What happens is that once the user clicks down the window decoration's resize handles, effectively the call to glfwPollEvents() will block within the OS itself in order for the OS / window-manager to intercept the mouse and keyboard messages to do its window resizing/reshaping thing.
I'm afraid that even though Windows will inform the process about the start of a window resize or move action (after which the OS will have control of the window message processing) and GLFW already handling these events internally, right now GLFW will not notify the client application about this. It would be possible though for GLFW to provide an appropriate event callback to the application, so that the application can start a timer or thread only for as long as the window resize/move action happens (as is also mentioned in the linked other Stackoverflow answer).
So, the only thing that you can do in order to keep rendering while the user holds onto the resize handles or while the user moves the window around, is to render in a separate thread.

When resizing, make the window transparent with a dotted-line border

I'm asking this question ahead of time, since I haven't gotten around to attempting an actual, real implementation yet. Win32 (C++) is turning out to be a colossal pain to program. But, my question is this:
I want to make my application's window become fully transparent with a dotted perimeter when resizing the window. How would I accomplish this? Think of what happens in Windows 3/3.1 (I believe it was this version) when resizing a window. Everything goes transparent, with a dotted-outline where the mouse is moving, then it repaints the entire contents. That's what I'm trying to achieve.
A while ago, I tried handling the WM_(ENTER/EXIT)SIZEMOVE messages and make use of SetWindowLong() to set the WS_EX_TRANSPARENT extended style, but my window became (indefinitely) pass-through, and when the window's focus was killed, it could never again regain focus.
Do I need to handle other messages like WM_NCLBUTTON(DOWN/UP)? I have a boolean flag to tell me when to halt drawing during resizing, and the logic for determining when I'm resizing works perfectly, but I cannot get the visuals to work. I'm not sure which parts of the Win32 API to actually use. I've done some research, and uxtheme.lib/.h seems promising, but I'm not sure how that would work with WM_NCPAINT, which I have been using with (some) luck.
EDIT
I need to clarify something, in case anyone was confused or unsure of what I meant. What I meant by the Windows 3.1/3 resizing scenario is that once WM_ENTERSIZEMOVE has occurred, the window (controls, caption, frame) should be made entirely invisible, and the window's nonclient-region's perimeter should display a dotted-outline of sorts. Then, only until the resize has been finished, when WM_EXITSIZEMOVE has occurred should the entire window (controls, caption, frame) be fully redrawn, updated, and returned to its normal, functional state. Sorry for any miscommunication!
I found the answer... After so long, finally found it. Here's where I found it! http://www.catch22.net/tuts/win32/docking-toolbars-part-2# - Hope it helps anyone else possibly in my shoes!
And it turns out that the solution was rather simple. In fact, the core concept of what is explained is near-completely what I was thinking, yet I just had no idea how to implement it. The solution involves overriding the default WM_NCLBUTTONDOWN, WM_MOUSEMOVE, WM_LBUTTONUP (specifically when initiating a window movement) messages, and drawing a patterned rectangle which follows the position of the cursor. Then, afterwards, calling SetWindowPos or some other similar function to relocate the window.
Basically, block Windows from attempting to display anything graphics related until the resizing has been finished. Then, and only then, make Windows move the entire window in one huge, foul swoop.
Based on Remy's comment, there is a global option and corresponding registry setting for this, so perhaps try setting the registry setting when the move starts and restoring it when the move finishes.
Unfortunately this doesn't work as Windows appears only to pick up the setting on restart, broadcasting WM_SETTINGCHANGE also doesn't trigger it, which is a pity as doing something yourself that the OS already has an implementation of do is rather a poor state of affairs.

Detect when window gets overlapped by another window from the same or different process

Background
We are running our application in XenDesktop mode and our window shows some real time information. But if some other application is also launched in that XenDekstop and that application is overlapping our window then we want to stop rendering. And once its moved out of our window then we want to start rendering again. Unfortunately, right now these kind of notifications are not supported by Citrix.
Question
How can we detect when a part or the whole of the application window has been overlapped by other windows, and also detect when that's no longer the case?
I found the WindowFromPoint family of functions when Googling, however, that is not practical for my purpose because I'd need to keep polling all co-ordinates that my window covers.
Bonus points: For a start, it's enough if I can just detect when such overlapping occurs. However, if I can detect exactly which area(s) of my window is/are covered that would be great.
There is no such API function. And usually the it isn't needed. WM_PAINT cares for itself.
If you get a WM_PAINT message you receive a region and a update rectangle of the area that needs a repaint. But it is a rectangle only, no complex region. Also there is a clipping region too.
But it should be possible to calculate the region by yourself. If we are talking about a top level window.
Create a rectangular region that is consists of your window rect
Walk all top level windows from back to front
Ignore all windows until you find your top level window
For each visible top level window create a rectangular region and XOR it with your current one.
Should be easy with GetWindow GW_HWNDNEXT
The resulting region is what you are searching for.
Again: There is no such function or message that determine, that is fired or can be executed to find such overlapping. There is no need for such an information. The system cares for itself with the appropriate WM_PAINT message. If an area is covered. There is no need for an action. If an area is uncovered WM_PAINT gets fired.
I think you should be able to get this kind of information when processing the WM_PAINT message, since normally the clipping region would be set accordingly. Calls to the RectVisible() function should tell you, for any part of your window, whether it "should be painted" (and so, whether it was just uncovered).
Despite this is not a solution to the OP's problem, I want to remark that once an overlapping window reveals part of your window (and also if you drag more area of your window back to screen), you will get a WM_ERASEBKGND message before the WM_PAINT.

Can I run code *after* a built-in wxWidgets event is handled?

I suspect there must be a built-in way to do this, but my Google-fu has failed me.
I'm using a wxScrolledWindow, and I have to paint an unscrolled background picture behind the contents each time the window is scrolled. I've made a scroll handler like this...
void homewindow_t::onScroll(wxScrollEvent &evt) {
Refresh();
evt.Skip();
}
...which works to force it to redraw the entire window each time. Unfortunately, it draws the window before the scroll is handled, so the background is repainted and then scrolled up or down, screwing up the alignment. The documentation suggests that Refresh just invalidates the screen, meaning that the scroll handler must be forcing a redraw.
The only way around this that I can see is to handle the scrolling code myself, which I'd rather not do if I don't have to.
Ideas, suggestions, clues...?
The only general solution I've found to running code after an event is handled is to post a second, different event to the event queue before skipping the current event (so that it gets handled by the default handler), and handle that when it comes up.
However, perusing the wxWidgets source code, I've found an answer to my specific problem: there's a function, wxScrolledWindow::EnableScrolling. Although it's not obvious from the name, this will enable or disable the "physical scrolling," which is what forces the instant redraw. So calling EnableScrolling(false, false); in the window's constructor solves the issue entirely.
To paint a "fixed" background in wxScrolledWindow you should just offset the DC origin to compensate for scrolling before drawing it (and then reset it back, of course), there is really no need to deal with events at all.
However if you really need to define a "post handler", then there is a way to do it, see this blog post. While the API described in it will only be available in wx 2.9.5, you do the same thing in the previous wx versions manually using wxEVT_IDLE.

ESRI Map object - Is it possible to disable the MouseWheel event handler?

I've posted this on the ESRI support forum, but no one has come back with a solution as yet.
Background: I'm maintaining a C++ map display application that makes use of ESRI ArcGIS components (version 9.3.1 SP1). It instantiates a Map object (esriCarto::Map), queries for the IActiveView interface, and calls Activate to pass in the view window client area (and a whole bunch of other properties are also set via various interfaces). It is then used in the middle of a sequence of drawing operations to render the final display image.
Problem: The WM_MOUSEWHEEL event seems to be picked up in the Map object (or a child object?), and is causing odd behaviour. What's supposed to happen in the app is that the view window receives this message, then calls a 'zoom' method to trigger appropriate redrawing. What actually happens is that the message passes through the view window's PreTranslateMessage, then the display area glitches, then view window's OnMouseWheel handler is called to handle the zoom.
By 'glitches', I mean the view window turns white briefly, then the previous image is redisplayed. This did not happen in a previous version of the app that integrated with ArcGIS 9.2, and none of the app's own drawing code is being called while this glitching effect is happening. It also doesn't happen if the window's zoom function is called via an alternative context menu option.
Having read around the reference info for a while, I suspect that the Map's child ScreenDisplay object is responding to the mouse wheel event and doing something we don't want it to do to the view area - I also suspect there's a way of telling it not to, but I can't seem to find it. I do have a workaround, i.e. to handle the zoom in the view window's PreTranslateMessage, and prevent the message going any further, but that feels like a bit of a hack.
So, can any kind and clever person please point me at a way of telling the Map object to ignore mouse wheel events?
Better late than never...you can disable the mouse wheel on a MapControl by calling IMapControl4::put_AutoMouseWheel(VARIANT_FALSE) on your MapControl object.