Override handling of taskbar command "Close all Windows" - c#

I have a WPF-application with multiple unrelated Windows, i.e. there is always one MainWindow and optionally many others with no owner.
If these windows get grouped in the taskbar, windows will provide the action "Close all Windows" in the taskbar context menu.
If it is clicked, each Window of my application gets an individual close-command in an order I cannot control.
Problem:
Some of my windows may ask before closing, if it's okay to cancel pending changes. This is annoying and confusing if there are many of those.
What I want is: If the MainWindow is asked for closing, I want to prompt once, if that's ok. If yes, all windows should close silently, otherwise stay open.
But my MainWindow is not the first one, to process the closing procedure.
I have already found out, that I probably need to check the Windows Message Loop of my MainWindow for some WM_SYSCOMMAND with wparam SC_CLOSE.
(see How can I distinguish between "Close All Windows" and "Close" individual windows in MFC with Windows 7?)
But how can I evaluate this, before I execute the closing-routine for any other window?
ComponentDispatcher.ThreadPreprocessMessage in my mainwindow comes too late, it fires after some other window has started the closing procedure.
This question is somehow related to this one:
Odd form closing behavior when using taskbar's Close All Windows

Personally, I would just leave things as they are. I can see how having several prompts to save/cancel changes could be annoying, but it doesn't seem confusing to me. And while annoying, it seems like a minor annoyance, and frankly one that might teach the user to not use the "Close all windows" option when they have left a bunch of these windows open. That said…
As the question you've found points out, there is no built-in way to distinguish the "Close all windows" from a regular "Close window" command. The system is simply sending the messages to the windows in sequence.
In MFC (i.e. the context of the other question), you can call AfxGetCurrentMessage() to retrieve information about what actually instigated the SC_CLOSE message. If it was user input that was translated to a close command, there will be some type of user input (keyboard, mouse, etc.) as the current message. Otherwise, you'll just see the WM_SYSCOMMAND itself.
But you can't apply the same approach in WPF, because WPF doesn't provide a GetCurrentMessage() method or its equivalent (as far as I know). The only access to window messages you get is to override the Control.WndProc() method, and by the time you get the close command, the most recent window message there will always be the SC_CLOSE.
It seems to me that the best you can do is use the WndProc() override to track incoming messages, so that you can reset a flag when non-close-command messages come in.
Then, when you get the close command and display the user prompt, you can check that flag. If it's set true, then you can ignore the prompt and just use whatever the user most recently selected. Since you're clearing the flag any time non-close-command messages come in, the first close command received will always display the prompt.
Another alternative would be pre-emptively close all the remaining windows. Here you'd still have the prompt have some kind of "apply to all other windows" option for the user, but instead of setting of just relying on the flag, you could actually close all the other windows explicitly.
Neither of these are ideal, from a user-interface perspective. The main problem is when the user tries to close just a single window. In the first approach, the user will see the "apply to all other windows" option in the prompt even though there won't be any other windows to close. The second approach is a bit more self-consistent, but adds a feature you may or may not want: the user can close all windows in the program any time they are closing just one window.
Neither of these behaviors are exactly standard Windows user interface behaviors. I.e. in trying to save the user some annoyance (and confusion, though like I said, I don't see that part being the case), you introduce what itself could be potentially confusing to the user.
Given that it involves additional work coding, and may simply exchange one annoying/confusing result for another, the best solution may be simply to not try to address the issue at all.

Related

Force to close current window first in WPF

I'm working WPF application, Currently it has one window and at specific time (As per my requirement). It's displayed on top most priority.
this.Visibility = Visibility.Visible;
this.Topmost = true;
Now, I want like user should close first this windows(WPF application window), till cannot access any other thing from system.(user cannot able access even other application also) Seems like to force close first this window
I've been searched, but not getting anything.
How Can i do that?
You can't.
Imagine another application tried to do the same thing at the same time - you can't close window A before window B, but you can't close window B before window A, but...
Edit: the short version above can be misunderstood, so in more detail:
Let's say, your application has this very important message for the user, so it opens a special window. The special property of this window is that as long as it exists, the user can't access any other window. This also means, the user cannot close any other window.
Now while the user reads the message, another application has an important message, so it opens a window, using the same method as you to block access to other windows until it is closed.
The user cannot close the second window, because the first window is special and must be closed first. The user cannot close the first window, because the second window is special and must be closed first => the UI is completely locked. The poor user must use Task Manager to kill one of the two applications or reboot the system.
See also Raymond Chen's more detailed discussion of this principle.

Are actions on active window through c# possible?

I want to write some code, that can automatically do actions on active windows.
For example, if i want to press the ignore button once the window that pops if I insert a new DOK.
i thought of a code that once a specific (known) window pops, it presses a few TABs, and presses Enter.
Can I implement such a code? preferrable in C#.
I thought of several answers to your question because it isn't clear what you are asking. One of these topics might be an area for research:
If you want to press keys for the active window in an application other than the one you are running, you might read about elevated privileges, interprocess communication, and accessing the keyboard with Windows function calls. You can not normally do anything to other applications other than to cause Windows to send it various messages. Thought: how will you indicate when the press the keys if your application is not the active window?
If the active window is one within your application, then you will be better off in the long run by finding a solution that fits C#'s object-oriented model. If you want certain code to be run at times for certain windows (when one is active), you can share code by putting it into a common superclass and having your window classes inherit it. Looking at it this way will be instructive, but you may have to find a somewhat different solution, since it sounds like your window should be inheriting Window's Window class (you can only have one parent class in C#). You could look up "class inheritance" and perhaps "interfaces."
Another solution that isn't so object-oriented for sharing code is to put it into a static function and call this function as needed in the code of your active windows. But ideally, it is code in the active window class that should be manipulating the window. You can put it into a function and then call the function from anywhere in the application that has the "this" reference for the active window.

Determine if a dialog is showing

In my WPF application, I have multiple classes each of which implements a message loop. All of these message loops then run in parallel when I create objects of these classes. These objects may show a dialog box at times. The main application thread must keep an eye on these objects and make sure none of them is stuck with the dialog (and press Cancel (Escape key) if it determines such cases). What is the correct way to determine the active foreground window of a thread? I know there is a GetForegroundWindow() API, but it appears as if it works at system level and not thread level.
There's no such thing as the per-thread active foreground window. So what you are explicitly asking for does not have an answer.
Probably the right way to go here, using Win32 at least, is to enumerate top-level windows with EnumWindows. Then use GetWindowThreadProcessId to identify that the window is associated with one of your threads. Finally use GetClassName to identify that the window is a file dialog. Then feel free to do whatever dastardly thing it is you want to do to the window!
On the other hand, this sounds like a perfect candidate for UIAutomation. You are automating testing of UI. UIAutomation will be able to find these file dialog windows and press buttons on them.

Alternative way to notify the user of an error

I have a winform software that communicates with hardware through a protocol.
Sometimes error in communication happens and i would like to notify the user. Errors could be for example: timeouts, crc errors, physical disconnection etc...
I have a communication window in which i show these errors, but by default this is hidden. The user can open it though the menubar.
Popups are annoying to the user (and to myself) so i would like a un-invasive way to notify the user that an error has occurred. Perhaps a info bubble like when XP tells you updates are ready for your computer? I know that NotifyIcon can help put things in the system tray, which i do not wish to have. I'd rather keep it within my MDI.
I'm open to other creative ideas as well.
There are several alternatives that can be employed when an error occurs, each with their own advantages and disadvantages:
MessageBox popups
Display a message box popup to the user.
Advantage: since it is modal, the user has to acknowledge the error to continue.
Disadvantage: since it is modal, it interrupts the user from whatever they were doing. Multiple errors are also inconvenient, requiring multiple confirmations.
Show the communication window
If your existing communication window is hidden, display it to make the logged error visible.
Advantage: uses the existing familiar communication mechanism.
Disadvantage: if the user does not really care about the errors, it could be annoying that the communication window continually reappears.
Status bar messages
Show messages in the status bar of the application.
Advantage: will always be visible on screen, but is "out of the way" of the main window.
Disadvantage: hard to display multiple messages and may be missed by the user.
Balloon notifications
Show an Outlook/MSN Messenger style notification message near to the notification icons.
Advantage: is obvious enough for a user to notice, but does not necessarily require a notification icon. Could also collate multiple messages into a single popup.
Disadvantage: could be annoying to the user.
Notification icons
Show a notification icon (perhaps with a balloon notification).
Advantage: is obvious to the user, but still unobtrusive.
Disadvantage: is yet another notification icon to clutter up the user's desktop.
Personally, I would choose option 2 as it requires the least amount of effort to achieve. If it is unacceptable once people start to encounter it, review the other alternatives.
For examples of balloon notifications that do not require a notification icon, see this for Windows Forms and this for WPF.
One (relatively) common paradigm is to place a message on the status bar ("[x] New Messages"), and make the appearance of the message window a user action.
If your MDI window is open/visible, then you could have a comms status icon on it - this would be green when everything is fine, orange for warnings (like corrupt packets have been detected, but comms is still working and the system has recovered), and red for errors (like no decodable comms received for 5 seconds). This allows it to be fairly subtle when things are wokrking, but quite noticeably "different" is a problem occurs.
For a serious error (e.g. disconnection) you may want to get more "invasive" because there comes a point where not bringing the problem to the user's attention is worse than bothering them with the error report.
If your window is not guaranteed to be visible then (despite your dislike of the idea) a system-tray icon (to show this status) is a standard and rather clean solution - it can be permanently visible or simply appear when it is relevant, it's about as non-invasive as you can get while still bringing information to the user's attention, and easy for the user to check periodically to reassure themselves that they have a "green light".
An alternative to visual indicators is to use audio alarms.
(For example, we use a monitor on our build server. It simply has a green icon when the builds are good, and a red icon if a build has failed. This is perfect, as it doens't bother me at all but I can check the build status in an instant.
Alternative example: I have an email app that shows an "envelope" icon in the system tray when I have new email, and nothing if I don't. In practice with this system I notice pretty soon (within a minute or two) when mail has arrived, but I am not bothered by constant popups or message boxes.
I think these are both examples that show how much better a system tray icon is than a popup or balloon window. Popups are irritating and with most of them if you aren't watching when they appear, you miss the information. I'm forever spotting popups just as they disappear and then having to open the app to find out if they were telling me anything useful. Which usually they weren't. The same goes for audio notifications: I keep hearing random noises from my IM application and wonder what the heck they mean).
Depends on your scenarios: If the event requires user interaction to resolve, then a modal dialog may well be the best approach because you can't continue until the user, for example, inserts the device into a USB port (or whatever).
For other unusual notifications that the user may need to be aware of but may not disrupt the workflow, I suggest using an in-app popup-toast or updating the status window.
If the user doesn't need to change/interrupt what they're doing, then don't warn/notify them: your device and app should "just work" - the user should only be interrupted if there's something that truly requires their attention or that will cause them disruption "soon".
this put a small red circle at rightside of control. its kinda datagridview cell erroText style
var errorProvider1 == new ErrorProvider();
protected void textBox1_Validating (object sender, System.ComponentModel.CancelEventArgs e)
{
try
{
int x = Int32.Parse(textBox1.Text);
// Clear the error.
errorProvider1.SetError(textBox1, "");
}
catch (Exception ex)
{
errorProvider1.SetError(textBox1, "Not an integer value.");
// additionally, if you wantto prevent user leaving textbox
// until he satisfies condition. uncomment below.
// e.handled = true;
}
}
From: Microsoft

Prevent Process 'A' from spawning Process 'B' which then shows up on top of what should be the "TopMost" Process 'C'

I have a windows form application which needs to be the TopMost. I've set my form to be the TopMost and my application works as I'd like it to except for in one case.
There is a 3rd party application (referred to as player.exe) that displays SWF movie files on a portion of the screen that popup on top of my application.
Using Process Monitor I determined that player.exe application calls
flash.exe <PositionX> <PositionY> <Width> <Height> <MovieFile>
in my case:
flash.exe 901 96 379 261 somemovie.swf
Since flash.exe is being spawned in a new process after my form has been set to the TopMost it is appearing on top of my application.
First thing I did was make my application minimize the player.exe main application window hoping that this would prevent the Flash from appearing also. But, unfortunately it doesn't... even with the window minimized whenever the flash movie starts it shows up at the pixel location (901,96). I then tried creating a timer to keep setting the form.TopMost property to true every 10ms. This sort of works but you still see a very quick blip of the swf file.
Is there some type of Windows API call which can be used to temporarily prevent player.exe from spawning child processes which are visible? I admit it sounds a little far fetched. But, curious if anyone else has had a similar problem.
Addendum:
This addendum is to provide a reply to some of the suggestions layed out in Mathew's post below.
For the emergency situation described in the comments, I would look at possible solutions along these lines:
1) How does the third party application normally get started and
stopped? Am I permitted to close it
the same way? If it is a service, the
Service Control Manager can stop it.
If it is a regular application,
sending an escape keystroke (with
SendInput() perhaps) or WM_CLOSE
message to its main window may work.
Easiest way to close the app is to CTRL-ALT-DEL, then kill process. -OR-
The proper way is to Hold ESC while clicking the left mouse button... then input your username and password, navigate some menu's to stop the player.
There is no PAUSE command... believe it or not.
I don't think using WM_CLOSE will help since minimizing the application doesn't. Would that kill the process also? If not, how do you reopen it.
2) If I can't close it nicely, am I permitted to kill it? If so,
TerminateProcess() should work.
I can't kill the process for two reasons. 1) Upon relaunch you need to supply username/password credentials... There may be a way to get around this since it doesn't prompt when the machine is rebooted but... 2) Whenever I kill the process in task manager it doesn't die gracefully and asks if you want to send an error report.
3) If I absolutely have to leave the other process running, I would try
to see if I can programmatically
invoke fast user switching to take me
to a different session (in which there
will be no competing topmost windows).
I don't know where in the API to start
with this one. (Peter Ruderman
suggests SwitchDesktop() for this
purpose in his answer.)
I got really excited by this idea... I found this article on CodeProject which provides a lot of the API Wrapper methods. I stopped implementing it because I think that in order for desktop's to work you must have explorer.exe running (which I do not).
EDIT2: On second thought... maybe explorer.exe isn't needed. I'll give it a try and report back.
Edit3: Was unable to get the code in that article working. Will have to put this on hold for a moment.
Answer Summary
As one might have expected, there is no simple answer to this problem. The best solution would be to problematically switch to a different desktop when you need to guarantee nothing will appear over it. I was unable to find a simple C# implementation of desktop switching that worked and I had a looming doubt that I would just be opening a whole new set of worms once it was implemented. Therefore, I decided not to implement the desktop switching. I did find a C++ Implementation that works well. Please post working C# virtual desktop implementations for others.
Setting the TopMost property (or adding the WS_EX_TOPMOST style to a window) does not make it unique in the system. Any number of topmost windows may be created by any number of applications; the only guarantee is that all topmost windows will be drawn 'above' all non-topmost windows. If there are two or more topmost windows, the Z-order still applies. From your description, I suspect that flash.exe is also creating a topmost window.
Aside from periodically forcing your window to the top of the Z-order, I think there is little you can do. Be warned, however, that this approach is dangerous: if two or more windows are simultaneously trying to force themselves to the top of the Z-order, the result will be a flickering mess that the user will likely have to use the task manager to escape.
I recommend that your program not attempt to meddle with other processes on the computer (unless that is its explicit purpose, e.g. a task manager clone). The computer belongs to the user, and he may not value your program more highly than all others.
Addendum:
For the emergency situation described in the comments, I would look at possible solutions along these lines:
How does the third party application normally get started and stopped? Am I permitted to close it the same way? If it is a service, the Service Control Manager can stop it. If it is a regular application, sending an escape keystroke (with SendInput() perhaps) or WM_CLOSE message to its main window may work.
If I can't close it nicely, am I permitted to kill it? If so, TerminateProcess() should work.
If I absolutely have to leave the other process running, I would try to see if I can programmatically invoke fast user switching to take me to a different session (in which there will be no competing topmost windows). I don't know where in the API to start with this one. (Peter Ruderman suggests SwitchDesktop() for this purpose in his answer.)
You can use the Process class to start flash.exe directly - and use an appropriate ProcessStartInfo settings to show the window in a hidden state - or with a WindowStyle of hidden or minimized.
You could also consider using the SetWindowsHookEx API to intercept the process start API calls, and when the process is flash.exe run some code to restore you window to top-most status.
Matthew's answer is excellent, but I suspect you may be asking the wrong question. Why does your application need to be topmost? If you're trying to create a kiosk or some such, then topmost is not the way to go.
Edit: After reading your response to Matthew's comment, I'd suggest creating a new desktop and switching to it before displaying your alert. (See CreateDesktop and SwitchDesktop in MSDN.)

Categories

Resources