There are seven ways in which a 'dormant' application can become the 'active' one, based upon the combinations of whether it is minimised or simply obscured, and whether it is re-activated via alt-tab, a mouse-click of its icon, re-activated by it being sent a windows message from another program, or is simply 'discovered' to be the top-most application on the desktop when the application obscuring it is closed (or minimised).
In all cases I need to know that my app is now the active (e.g. top-most on the desktop) application so that I can refresh its data from the database.
I do know that apps 'know' when they are the top-most, as I can see the border changing to the active colour as soon as they become top-most.
If I trap WM_ACTIVATE_APP messages, this works most of the time, but doesn't seem to when my app was minimised and is restored to the active state.
I need to be told that my app is now top-most and active before the user does anything.
Any suggestions? Thanks, Dave
Try the following:
After such a time has elapsed that the data from the database should be considered out of date, call InvalidateRect() on your window (or the WinForms equivalent). If your window is not obscured it will get an immediate WM_PAINT. But if the window is completely obscured, it shouldn't get the WM_PAINT until the OS actually needs to display it - i.e. when the obscuring window is moved. Refresh the data from the database in response to the WM_PAINT message.
It turns out Raymond Chen blogged about this back in 2003.
After investigating, I found the cause and solution to my problem.
I found out that the WM_ACTIVATEAPP message was being sent (and received) OK, but this happened while the app was still in it minimized state (i.e. before it was restored).
Because I had an if test to not do anything when the app is minimized ( which is pointless as the user wouldn't see the results!), no action was being taken.
The WM_ACTIVATEAPP message is sent when the app gets 'uncovered', and that is okay since the app isn't minimized.
I now also respond to the WM_WINDOWPOSCHANGED which gets fired upon restore,
and this combination seems to cover all seven ways in which my app can be re-activated.
Related
WM_MOUSEMOVE is sent when the mouse is moved over my window, regardless of whether a mouse button is held down or not.
However, the above is not true if the user is in the process of carrying a file into my window.
How can I get notified of this special case?
I'm ok with requiring a minimum of Windows 7, or even Windows 10.
I found this question which is almost the same, but I can't implement the IDropTarget COM interface, because my project has not been created as an "ATL COM" app nor as an "MFC application that contains ATL support".
Edit: I'll try WH_MOUSE_LL from the above-linked question.
A little background
Our application (AppA) is calling a 3rd party application (AppB). We are simulating AppB's window as being modal to our application.
pseudo
while AppB_Running
If AppA_focused
SetForeGroundWindow(AppB_Hwnd)
HandleMessage
SetForegroundWindow(AppA_HWnd)
This has been working for years without incidents, that is, until we started rolling out Windows 10. We started receiving reports that a random app (AppC) was sometime getting the focus when we closed AppB (Actually, given our user's tech expertise, the report were more along the line "Closing AppB kills AppA" but I digress). That behavior can be reproduced occasionnaly(<5%) on dev machine (But not yet while debugging...)
So far, test result suggest AppC is the application that had the focus before AppA.
Is there a way I can ensure AppA gets the focus back when AppB closes?
Extra notes
The problem can be reproduced even if AppA only ever loses focus to AppB. (AppC never being focused after AppA started)
While this does not directly answer my original question, it does give some more insight on the problem and might be useful to someone else.
Part of the issue was an oversight on our end. More specifically, the way we obtained AppB_HWnd. We basically picked the first top level window we encountered. In our current test case, that window happens to be an invisible windows ('MSCTFIME UI'). Calling SetForegroundWindow on an invisible window doesn't seem to cause problems per se, Windows seems to just bring to front one of the process' visible window. It is when said process does not have any visible windows left that things seems to go awry. That usually happen in our case between the moment AppB's main window is closed and the moment the process ends.
So... Don't call SetForegroundWindow on an invisible window
As for why we didn't have any trouble in Win7? Maybe the first window was always a visible one. Or maybe SetForegroundWindow behaved differently back then.
When I debug my program, which consists of looping over thousands of entries in vectors multiple times, it simply freezes the program but does not provide any error messages whatsoever. Does Visual Studio have some sort of auto-time out that I am experiencing?
Check may be your program is going into infinite loop Or doing some heavy task that makes your UI unresponsive(if you have windows form). Since you are debugging this program then why dont you set breakpoint in code and check where your program is causing issue.
And yes there is no time out for Visual Studio,But for program window.This is known as Hang Status.
When an application (or more accurately, a thread) creates a window on the desktop, it enters into an implicit contract with the Desktop Window Manager (DWM) to process window messages in a timely fashion. The DWM posts messages (keyboard/mouse input and messages from other windows, as well as itself) into the thread-specific message queue. The thread retrieves and dispatches those messages via its message queue. If the thread does not service the queue by calling GetMessage(), messages are not processed, and the window hangs: it can neither redraw nor can it accept input from the user. The operating system detects this state by attaching a timer to pending messages in the message queue. If a message has not been retrieved within 5 seconds, the DWM declares the window to be hung. You can query this particular window state via the IsHungAppWindow() API.
Detection is only the first step. At this point, the user still cannot even terminate the application - clicking the X (Close) button would result in a WM_CLOSE message, which would be stuck in the message queue just like any other message. The Desktop Window Manager assists by seamlessly hiding and then replacing the hung window with a 'ghost' copy displaying a bitmap of the original window's previous client area (and adding "Not Responding" to the title bar). As long as the original window's thread does not retrieve messages, the DWM manages both windows simultaneously, but allows the user to interact only with the ghost copy. Using this ghost window, the user can only move, minimize, and - most importantly - close the unresponsive application, but not change its internal state.
A nice article is written in this following link.
How program window works
I'm making an application that hooks itself in to a target application and, when activated by the user, prevents all keyboard and mouse window messages from reaching the target application's window proc. My application does this by translating the incoming input messages, such as WM_MOUSEMOVE, to WM_NULL, so that the window proc is unaware input happened.
The problem is that Windows also automatically sends WM_SETCURSOR and WM_NCHITTEST to the window proc (e.g. when the application calls PeekMessage) when mouse input occurs. These messages aren't posted to the window's message queue, so I can't change them to WM_NULL.
I initially worked around this by subclassing the window proc and simply ignoring WM_SETCURSOR and WM_NCHITTEST there, but subclassing seems to have compatibility issues with some of the applications I'm hooked in to.
My question is: How do I prevent WM_SETCURSOR and WM_NCHITTEST from being generated in the first place OR how do I prevent them from reaching the application's window proc.
Some Ideas to Try
I just finished implementing a global/system wide CallWndRetProc with a WH_CALLWNDPROCRET Windows Hook (like it describes in the past post of the link below).
http://help.lockergnome.com/windows2/Igor-SetCursor-SetWindowsHookEx--ftopict285504.html
Using that in combination with hiding all the system cursors using SetSystemCursor has effectively hidden the cursor for most applications.
If you wanted to continue hacking at this target application, you could try using API Monitor to diagnosis what is going on: http://www.rohitab.com/apimonitor
The guy at rohitab hints at releasing his source code eventually; his site seems to have some of the better forums about Hooking, Subclassing, Injecting, etc.
It sounds like you successfully used SetWindowLongPtr(), but there are a few different ways to get into the address space of the program you are working on...
Have you tried SetCapture()?
Other Links
Here are a few other links that may be useful:
http://support.microsoft.com/kb/31747
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646262(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633569%28v=vs.85%29.aspx#winproc_subclassing
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648395(v=vs.85).aspx
Hope that helps. Good luck.
By now everyone writing for Windows probably knows that applications cannot (officially) steal focus from foreground processes, and why. But I have just managed to steal focus, inadvertently, and don't understand how this is even possible.
I have a Delphi app that user brings up with a hotkey (or by a mouse click, or by Alt+Tab), selects a piece of text and hits Enter. My app then minimizes (hides to the tray, even), and pastes the text user just selected into the active window. Nothing new here, plenty of similar projects out there - clipboard extenders, glossaries, macro programs, etc.
What is puzzling to me is that after doing all the above and then sleeping for 1500 ms, I restore my main form and it gets the focus back! It becomes the foreground window, even though it wasn't 1500 ms ago (tested; Windows 7 32-bit.).
In fact, I don't want this at all, so before restoring my main form I record which window has foreground and I give it back to that window after it's been given to me. I'm just curious why my app gets to be in the foreground when by rules it should not. Maybe I don't understand the rules as fully as I thought I did?
If you look at the documentation for SetForegroundWindow you see a list of conditions for the call to succeed, one of them is "The process received the last input event." So if the user does not do anything after pressing enter in your app you still have the right to steal focus. I don't know if Delphi calls SetForegroundWindow for you when the window is restored but it might be something to look into.
I don't know how you restore your window but using SW_SHOWNOACTIVATE with ShowWindow might help...