In an application that I am currently working on, a requirement is to bring a window of an external application to the foreground. Making Win32 API calls such as BringWindowToTop and SetForeground window do not work all the time. This is due to some restrictions within Windows XP. What I would like to do instead is send simulate a mouse click the window's button on the taskbar which I am hoping will bring the window to the front. Does anyone know how this is possible?
Check out the section "How to steal focus on 2K/XP" at http://www.codeproject.com/KB/dialog/dlgboxtricks.aspx, as this is exactly what you need. I wouldn't go the taskbar route as the taskbar could be hidden or simply not there.
It's possible. But it's extremely sketchy. Your application may also break with the next version of Windows, since it's undocumented. What you need to do is find the window handle of the taskbar, then find the window handle of the child window representing the button, then send it a WM_MOUSEDOWN (I think) message.
Here's a bit on finding the window handle of the taskbar:
http://www.codeproject.com/
FWIW, the restrictions on BringWindowToTop/SetForeground are there because it's irritating when a window steals focus. That may not matter if you're working on a corporate environment. Just keep it in mind. :)
I used this in a program where I needed to simulate clicks and mouse movements;
Global Mouse and Keyboard Library
To be honest I've never had an issue bringing a window to the foreground on XP/Vista/2003/2000.
You need to make sure you do the following:
Check if IsIconic (minimized)
If #1 results in true then call
ShowWindow passing SW_RESTORE
Then call SetForegroundWindow
I've never had problems that I can think of doing it with those steps.
Related
I need help handling minimized programs when using a custom/self made explorer.exe file .. because unless properly handled, minimized programs will just shrink to something like 100x50px and stay on screen. I worked out a Timer in C# to check for "iconic" processes, list their mainWindowHandler, and move them outside the screen with "MoveWindow". To bring them back I use the handler and the "ShowWindow" function wich works AWESOME .. but as I said, it involves a constantly running Timer, so there must be a cleaner/easier way of achieving this.
Any ideas? Some way to hook and raise an event when a window is minimized?
*please note: show and movewindow are functions from user32.dll. I'm not trying to catch when MY forms are minimized, but when the OTHERS programs are.
You can create a hook to check when windows are being minimized.
I found a CodeProject article that uses hooks to check when the user opens a system menu (ALT+SPACE) on any window, and then appends an extra item to it. You can use that code to check when the user hits the minimize button, and run whatever code you need there.
The CodeProject article is written in C++, but you can adapt the same method for C# (or use P/Invoke).
I need to draw something on a window (that isn't mine - it's user-defined, if it matters).
I've already managed to draw on the window by getting the device context using GetDC and drawing normally, the problem is that I don't know when to draw to the window - the window is constantly redrawing itself (for example, a game).
I've got a few ideas but so far they're no good or bad/no implementation.
Using a timer. This was the worst idea, but I'll try anything right now. obviously, since the window is redrawn constantly it would flicker. I thought of forcing the window to redraw before my drawings, but still it's no good. can't really think of a good implementation with a timer...
Hook WM_PAINT message. using SetWindowsHookEx WM_GETMESSAGE hook I can use an event that receive WM_PAINT message whenever the other window receives it, but WM_PAINT is sent before drawing is done. I found on MSDN that instead of WH_GETMESSAGE Windows Hook you can use WndProcRetHook which is called after processing windows messages and recieves a structure containing the message information, but so far no luck - I can't get it to work...
Hooking drawing functions. I've tried hooking the painting function (or functions) such as ReleaseDC and/or EndPaint which invalidate the window, so I can do my last-minute drawings. this time, I got it to work pretty good - but it still flickers a little and on some windows hooking ReleaseDC somehow prevents from the window to render - it doesn't even erase it's background. sometimes even the entire process crashes.
So I'm looking for a good method to be the last to draw on a window before it is displayed on the screen. I prefer avoiding hooks not being done with SetWindowsHookEx (such as: external DLL) but that would be fine too.
Thanks.
An alternative approach might be to avoid painting directly on the window, and instead create a transparent layered window that you keep positioned on top of the main one. That way, the drawing on your window doesn't interfere with the drawing on the main window, and vice-versa.
You may need to take certain steps to that mouse clicks will go through your window to the main window; eg. handle WM_NCHITTEST with HTTRANSPARENT and use the WS_EX_TRANSPARENT style.
Since, under Windows, windows are required to draw on demand, the only way to do this is to use SetWindowsHookEx() to hook the WM_PAINT window for that window.
This is a non-trivial process that requires that your paint code reside in a DLL (so the DLL can be loaded into the target app's address space).
In general, this is not a very good idea unless you have a very good reason to do this.
I want my C# program to shut down a certain legacy application before proceeding. The legacy app may be shut down immediately using ctrl+x. I could do this using Sendkeys, but I've been told that sendkeys can be a little flaky. Is there an alternative way for me to send this key combination and shut the legacy app down?
If you know what the window's title is on the caption bar, such as 'Foo', then you can use p/invoke to find the window and get the handle from it 'FindWindow'. Once you get the handle, then you can use 'SendMessage' to that handle sending a 'WM_KEYUP' that denotes Ctrl+X together.
Hope this helps,
Best regards,
Tom.
If this is a GUI application. It may also respond to Alt+F4 via SendKeys.
Unlike ctrl+x, Alt+F4 will not depend on which window has focus. This is a standard accelerator for windows applications and most older GUI applications will support it. The main reason SendKey is considered flakey is because keystrokes get delivered to the focus window, which may or may not understand them. But Alt+F4 is an accelerator, so it should work regardless of which window has focus.
If you can get the handle to the main window. (use FindWindow if you don't have it already). You can
PostMessage(hwndApp, WM_SYSCOMMAND, SC_CLOSE, 0);
This is equivalent to choosing the close option from the system menu on the window. SendMessage should work as well, but PostMessage is safer since your application doesn't wait for the message to be delivered.
WM_SYSCOMMAND
Other options include:
System.Diagnostics.Process.Kill
System.Diagnostics.Process.CloseMainWindow
If the latter works, use it. If not, and you lose nothing by killing the process directly, then Kill().
I've got an app running maximized in a borderless window and need access to the windows taskbar on a given user event.
How would I bring the taskbar in foreground in .NET while running maximized?
Also an hint with regards to how to make it reliably go away wouldn't hurt! :)
EDIT: please note that I don't want the taskbar always on, I want it popping up on foreground just on a given user event, and then I want it to go away at will!
Um, don't run fullscreen? Maybe run maximized? Fullscreen app with taskbar is not a standard UI pattern.
What you could try doing is run maximized without the UI chrome (borderless window). Would let the taskbar in on the fun while still looking like a fullscreen app.
Interestingly enough, your desired solution seems to be the problem that caused this question. See my answer there. You may have to experiment a little with setting the FormBorderStyle and WindowState properties in a certain order, and try to minimize disturbance for the user.
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.)