richelieu7778
asked on
Forcing a process to the be topmost process
I am running a keyboard hook that, when required, launches a process. That process is a simple C# Windows form with a form on which there is a listview . . . nothing fancy.
It is desired that this form immediately have the focus so the user can begin using the keyboard UP/DOWN arrow keys without having to first "activate" the form. I want to remove the requirement that the user first have to left click on the form to give it the focus before they can begin using the UP/DOWN keys.
It seems that no matter what I try, the form is never the topmost window. The user is always forced to have to left click on this window first.
I've tried the following:
Setting the "Topmost" property of the form to "true" in the form's Design mode.
Calling the following in the form's Load() event:
SetFocus(this.Handle)
SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
AllowSetForegroundWindow(S ystem.Diag nostics.Pr ocess.GetC urrentProc ess().Id); //cb#27
SetForegroundWindow((int)t his.Handle );
I've even tried elevating the Priority to "RealTime" when it's launched.
I launch the process using the following:
ProcessStartInfo Prog2 = new ProcessStartInfo();
Prog2.UseShellExecute = false;
Prog2.FileName = "c:\someapp.exe";
Prog2.Arguments = "1";
Process p2 = Process.Start(Prog2);
p2.PriorityBoostEnabled = true;
p2.PriorityClass = ProcessPriorityClass.RealT ime;
p2.WaitForExit();
QUESTION:
The TaskManager has a "SwitchTo" button which always works on any process running. Is there any way to programatically simulate the "Switch To" functionality within the calling program?
Thanks in advance,
It is desired that this form immediately have the focus so the user can begin using the keyboard UP/DOWN arrow keys without having to first "activate" the form. I want to remove the requirement that the user first have to left click on the form to give it the focus before they can begin using the UP/DOWN keys.
It seems that no matter what I try, the form is never the topmost window. The user is always forced to have to left click on this window first.
I've tried the following:
Setting the "Topmost" property of the form to "true" in the form's Design mode.
Calling the following in the form's Load() event:
SetFocus(this.Handle)
SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
AllowSetForegroundWindow(S
SetForegroundWindow((int)t
I've even tried elevating the Priority to "RealTime" when it's launched.
I launch the process using the following:
ProcessStartInfo Prog2 = new ProcessStartInfo();
Prog2.UseShellExecute = false;
Prog2.FileName = "c:\someapp.exe";
Prog2.Arguments = "1";
Process p2 = Process.Start(Prog2);
p2.PriorityBoostEnabled = true;
p2.PriorityClass = ProcessPriorityClass.RealT
p2.WaitForExit();
QUESTION:
The TaskManager has a "SwitchTo" button which always works on any process running. Is there any way to programatically simulate the "Switch To" functionality within the calling program?
Thanks in advance,
ASKER
That didn't help. I had already set the focus to item #1 in the listview control. Setting the focus to the listview itself, as you suggested, didn't help.
Pressing the "Switch To" button on the Task Manager *always* works.
There's go to be some property / method in the Process class where you can force that process to be the topmost process . . . . i.e. exactly what the "Switch To" command does in the Task Manager. . . . . there's got to be one . . . . I just can't find it. . . .something like:
Process p2 = Process.Start(Prog2);
p2.Topmost = true;
I can't find it . . .
Pressing the "Switch To" button on the Task Manager *always* works.
There's go to be some property / method in the Process class where you can force that process to be the topmost process . . . . i.e. exactly what the "Switch To" command does in the Task Manager. . . . . there's got to be one . . . . I just can't find it. . . .something like:
Process p2 = Process.Start(Prog2);
p2.Topmost = true;
I can't find it . . .
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
It works, but not under unique circumstances, i.e. when the process is launched from another process . . .
All I need is the code which programatically executes whatever Task Manager executes when its "Switch To" button is pressed. That's all I need. That works *every* time under *all* circumstances, unique or not.
I hope somebody knows what that is. . . .it can't be that complicated . . . but who knows. . . . it might be a secret held by Microsoft.
All I need is the code which programatically executes whatever Task Manager executes when its "Switch To" button is pressed. That's all I need. That works *every* time under *all* circumstances, unique or not.
I hope somebody knows what that is. . . .it can't be that complicated . . . but who knows. . . . it might be a secret held by Microsoft.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Whoooo Hoooo!!! It *looks* like Dan7el might have it. I was not aware of the "ShowWindowAsync" method.
I can't try it right now. . . . but I'll try it later today and report back . . .
I can't try it right now. . . . but I'll try it later today and report back . . .
Man, I tried launching app from other process. All works just fine:
Process.Start(appPath);
As mentioned above:
1) I subscribed to Shown event of form and set focus to ListView there
2) form itself TopMost = true (you can set this from designer)
Process.Start(appPath);
As mentioned above:
1) I subscribed to Shown event of form and set focus to ListView there
2) form itself TopMost = true (you can set this from designer)
ASKER
Well. . . . I can't get either method to work. "ShowWindowAsync()" works just fine when and only when VS.NET 2008 is running from the debugger but not in an EXE. I'm wondering if it's process priority thing . . . . It seems that not matter what I do, tompost is ignored.
Thad definitely works:
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
// Use like this:
string appName = "WindowsApplication1";
Process[] processes = Process.GetProcessesByName(appName);
if (processes.Length > 0)
{
Process app = processes[0];
SetForegroundWindow(app.MainWindowHandle);
}
ASKER
Already tried that-- . . . . it didn't work . . it’s not that easy in my case.
I've discovered that a complication arises when the calling process (my keyboard hook, in my case) either:
1) has no Windows Form,
2) has a windows form but it's Visible propery is set to False, or
3) even it it has a Windows form, and it's Visible property is set to true but the Windows form doesn't have the current focus at the instant the new process (which does has a Form) is launched.
In other words, a Form of a spawned process is not allowed to have the current focus if the Form from which the process is spawned does *not* have current focus. I think I read somewhere that it is a “feature”, or limitation, depending on how you look at it, of the SetForegroundWindow(). That’s why the AllowSetForegroundWindow() exists; to allow, under *limited* circumstances, a process which would not normally be allowed to call SetForegroundWindow(), to be allowed to call it
But, in my case, AllowSetForegroundWindow() *STILL* didn’t work.
The *only* thing I found, that consistently works, so far in my investigation, is to call the following in the spawned process (the code in between the “extra stuff required” comment is the new stuff:
[STAThread]
static void Main()
{
Application.EnableVisualSt yles();
Application.SetCompatibleT extRenderi ngDefault( false);
//start of extra stuff required
frmSomeForm frm = new frmSomeForm();
frm.Show();
frm.WindowState = FormWindowState.Minimized;
frm.WindowState = FormWindowState.Normal;
frm.TopLevel = true;
frm.TopMost = true;
//end of extra stuff requried
Application.Run(new frmSomeForm ());
}
It flickers a little when first launched, but I can live with that, for now. As I learn more I can pare down the unnecessary stuff.
I've discovered that a complication arises when the calling process (my keyboard hook, in my case) either:
1) has no Windows Form,
2) has a windows form but it's Visible propery is set to False, or
3) even it it has a Windows form, and it's Visible property is set to true but the Windows form doesn't have the current focus at the instant the new process (which does has a Form) is launched.
In other words, a Form of a spawned process is not allowed to have the current focus if the Form from which the process is spawned does *not* have current focus. I think I read somewhere that it is a “feature”, or limitation, depending on how you look at it, of the SetForegroundWindow(). That’s why the AllowSetForegroundWindow()
But, in my case, AllowSetForegroundWindow()
The *only* thing I found, that consistently works, so far in my investigation, is to call the following in the spawned process (the code in between the “extra stuff required” comment is the new stuff:
[STAThread]
static void Main()
{
Application.EnableVisualSt
Application.SetCompatibleT
//start of extra stuff required
frmSomeForm frm = new frmSomeForm();
frm.Show();
frm.WindowState = FormWindowState.Minimized;
frm.WindowState = FormWindowState.Normal;
frm.TopLevel = true;
frm.TopMost = true;
//end of extra stuff requried
Application.Run(new frmSomeForm ());
}
It flickers a little when first launched, but I can live with that, for now. As I learn more I can pare down the unnecessary stuff.
ASKER
To clarify: the keyboard hook *never* has focus since it is just that--a background process which handles keyboard combinations. Since it didn't have focus, the form of the process it launched couldn't have focus (at least without the workaround I stated above).
ASKER
Although my situation was so unique, and nobody provided a solution which worked consistently, for *my situation* both of you tried to help.
I'll split the points.
I'll split the points.
Open in new window