In C#, how to activate the previously focused window? - c#

I work eg. in Firefox, and my C#.NET app brings its window to the front. That's ok, but when I use SendToBack() to hide the form, it doesn't activate Firefox's window, so altough Firefox is in the foreground, I have to click into the window to be able to scroll, etc. How can I activate the previously focused window in C#?
i have tried these:
[DllImport("User32")]
private static extern int SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll")]
static extern bool AllowSetForegroundWindow(int dwProcessId);
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[...]
AllowSetForegroundWindow(System.Diagnostics.Process.GetCurrentProcess().Id);
SendToBack();
SetForegroundWindow(GetForegroundWindow());
I hoped that after sending my window back, the previous one will be returned by GetForegroundWindow, but it doesn't work.
Secondly, I've tried to override WndProc, and handle the WM_ACTIVATE message to get the previous window from lParam, but it doesn't work either if I use SetForegroundWindow() with this handle.
protected override void WndProc(ref Message msg) {
if (msg.Msg == 0x0006) {
prevWindow = msg.LParam;
}
base.WndProc(ref msg);
}
[...]
SetForegroundWindow(prevWindow);

did you try the SetActiveWindow function? Its separate from the SetForgroundWindow function, although it seems that you may need to use them both.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646311%28v=vs.85%29.aspx
There is also a SetFocus function which sounds like it could work.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646312%28v=vs.85%29.aspx
Update
To get the current Active Window, I would fire off the GetActiveWindow function before moving your application to the front of the stack, that way you have the handle for the window that was active before hand.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646292%28v=vs.85%29.aspx
Another Update
I did a bit more digging around on the site and came up with the following three links, which might work better. The keyboard input functions seem to be dependent on the Window you are trying to set being part of the calling threads message queue, which since we are dealing with two separate application threads, is likely to not be the case.
GetGUIThreadInfo Get the threads information, including active window
GUITHREADINFO The GUITHREADINFO structure
SwitchToThisWindow Another method of window changing
All of these are in the same method stack as the SetForegroundWindow method, which seems to make them more likely to do what you are attempting.

When you call SetFocus() to move your app forward, it returns the handle of the window that had focus before you.

Related

GetWindowText vs Process.MainWindowTitle

I'm trying to obtain process information for the current active application (or window), using .Net/C#.
Currently I'm using
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
To get the current active window.
I understand there's no native way to do this other than use this API function.
From that, I use:
[DllImport("user32")]
private static extern UInt32 GetWindowThreadProcessId(IntPtr hWnd, out Int32 lpdwProcessId);
To get the process name that belongs to that window and then I get further process information.
I also use
[DllImport("user32.dll")]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
To get the current Window Text or caption.
Now, using the Process class, I can use
MainWindowTitle
to get the main Window title as well.
The thing is, MainWindowTitle and GetWindowText does not return the same information.
For example, let's say the main application opened is "Toad" with a connection and an editor open.
Then with GetWindowText I get:
"Toad for Oracle - myConnection - Somequery.sql".
and Process.MainWindowTitle returns
"myConnection".
So, the question is how do I get the exact same text as I get using GetWindowText, but using merely .Net classes?
Edit:
I found out that actually the reason is simply because both functions are not querying the same window handle.
The window handle returned in the GetForegroundWindow, is the number 198982.
And the MainWindowHandle property, which I suppose is the one used in the MainWindowTitle propery is the number 198954.
Using Spy++ I could find and confirm those windows handle captions are the one returned by their corresponding function.
So the "problem", if any, is that the Process class does not correctly identify the most foreground window as the Main Window.
GetForegroundWindow gives you the active window the user is working in and that might be a owned window or a modal dialog, not necessarily the applications main/root window.
MainWindow is a .NET concept, native win32 does not have such a thing and there can be 0, 1 or multiple "main windows" in an application.
Some Delphi/C++Builder applications have a HWND for the taskbar button and each form is a owned window belonging to this "invisible" window. Other UI frameworks may pull similar stunts that might confuse "main window" detection.
You can use UI Automation to inspect other applications if you don't want to use p-invoke. Start with the foreground window and walk up the tree of owned and child windows...

How to restore a window without giving it focus using WPF (or interop)

I need to restore ("un-minimize") a WPF window that has already been created but the window that's currently on top (not necessarily WPF) can't lose focus or activation. I have tried using all WIN32 functions I can find, to no avail. Getting really frustrated by now, would really appreciate any pointers and tips.
Obviously just changing to WindowState.Normal in WPF doesn't cut it as this makes the window receive focus and activation as-well. I have also tried all sorts of combinations with setting Hidden and IsEnabled while restoring.
I have tried WIN32 SetWindowPos with HWND_TOP, HWND_TOPMOST etc. but this function is not intended to restore windows and will only change position of already "displayed" windows.
Tried WIN32 ShowWindow and SetWindowPlacement but no luck there either. Tried a desperate attempt at adding a HwndHook to try and listen for WM_SETFOCUS and restoring focus to the original window but i only get zero for the last focused window handle..
Edit - Solution with window extension after tip from Joel Lucsy:
public static class RestoreWindowNoActivateExtension
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, UInt32 nCmdShow);
private const int SW_SHOWNOACTIVATE = 4;
public static void RestoreNoActivate(this Window win)
{
WindowInteropHelper winHelper = new WindowInteropHelper(win);
ShowWindow(winHelper.Handle, SW_SHOWNOACTIVATE);
}
}
Call ShowWindow passing the SW_SHOWNOACTIVATE flag.

How to keep window always on top

How I can keep my window staying always on top even if there is a window of another application with Topmost = true option activated and trying to stay in front of my window?
You can do a platform invoke on BringWindowToTop to achieve this:
[DllImport("user32.dll", SetLastError=true)]
static extern bool BringWindowToTop(IntPtr hWnd);
[DllImport("user32.dll", SetLastError=true)]
static extern bool BringWindowToTop(HandleRef hWnd);
And call to it when the FocusLost event fires.
It should be possible by setting the Focus on window, from OnFocusLost event handler.
Easiest way(assuming you allready have topmost promery set) would be calling
myform.BringToFront();
on FIXED but relativly small time intervals(see Timer class), through all the time form must stay on top.
If calling this was conected to event that inform you of losing privileg of beeing on top, that could possibly cause resource-fihgts between multiple applications. Price of beeing safe is that some other program might be cheating by lisstening to informations when he is overthroned by your program, but the only solution for you wolud than be to kill that other program if you want to stay on top all the time :D

c# Maximize Window from System Tray

I am having trouble trying to bring my application window to the front (i.e on top of all other windows). I want the user to be able to double click the notifyIcon in the system tray, and If the application already has a window open for it to be bought to the front. I have tried using the following two P/inovkes but neither seem to work consistently. Does anybody have any idea how to bring a window to the front/top?
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
tatic extern bool SetForegroundWindow(IntPtr hWnd);
ShowWindowAsync(ADProcess.MainWindowHandle, SW_RESTORE);
SetForegroundWindow(ADProcess.MainWindowHandle);
Given the little info you have provided the best guess I can make is that you have a timing issue with the call to ShowWindowAsync which runs asynchronously followed by the call to SetForgroundWindow.
Have you tried using ShowWindow to see if that works correctly?

How to make a windows form to come front in windows application done in c#?

I have done a global mouse event in my windows application. When i click the center button of my mouse, i want to make a particular form topmost...
There are some applications which runs in the full screen mode, so i need to do this, in order to make my form visible to the users, because this is the only way to view it. Since Alt + Tab is disabled. This is a Kiosk application.
I tried using Topmost = true for that particular form and
I tried using below code...But no use. I am not getting my form in front.
[DllImport("User32.dll")]
public static extern Int32 SetForegroundWindow(int hWnd);
[DllImport("user32.dll")]
public static extern int FindWindow(string lpClassName, string lpWindowName);
private void BringToFront(string className,string CaptionName)
{
SetForegroundWindow(FindWindow(className,CaptionName));
}
The global hotkey which has to trigger this form to bring front is working perfectly.
How to make my form come front ??? Thanks.
I solved it, doing this:
this.TopMost = true;
this.TopMost = false;
Not my thing but have you tried messing with:
this.BringToFront();
this.Activate();
get the handle of the window and do this
SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE| SWP_SHOWWINDOW);
You need set the fullscreen form's topmost to false, then continue on.
You may not be calling your BringToFront method correctly. For the FindWindow API function, lpClassName would be your application's name (e.g. "MyApplication.exe"), while lpWindowName refers to the caption in the particular form's title bar (e.g. "Form1"). Usually with FindWindow you pass in one or the other, eg:
FindWindow("MyApplication.exe", null);
// or
FindWindow(null, "Form1");
I'm not sure what happens when you pass both.
You may also just need to do something simple to achieve this, like calling the particular form's Activate() method.

Categories