我使用Process.Start()
从我的程序打开一个记事本,但新打开的记事本覆盖了屏幕。但我确实希望我的应用程序能够保持其重点。
我同样(使用相同的Process.Start)打开MS Excel和Word,但要将焦点重新放回我的表单,我需要写的是:
this.Focus();
但是用记事本嘲笑:我打开记事本(以及所有其他类似的过程)
Process process = new Process();
process.StartInfo.UseShellExecute = true;
process.EnableRaisingEvents = true;
process.StartInfo.FileName = @"abc.log";
process.Start();
现在记事本成为焦点。
我试过这些:
this.Activate()
,this.Focus()
,不用说了
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern IntPtr SetFocus(HandleRef hWnd);
{
IntPtr hWnd = myProcess.Handle;
SetFocus(new HandleRef(null, hWnd));
}
[DllImport("User32")]
private static extern int SetForegroundWindow(IntPtr hwnd);
[DllImportAttribute("User32.DLL")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
private const int SW_SHOW = 5;
private const int SW_MINIMIZE = 6;
private const int SW_RESTORE = 9;
{
ShowWindow(Process.GetCurrentProcess().MainWindowHandle, SW_RESTORE);
SetForegroundWindow(Process.GetCurrentProcess().MainWindowHandle);
}
另一个较长的解决方案来自here。
所有这些仍然将重点放在记事本上。为什么仅仅将焦点集中到一个窗口是如此困难,那也是应用程序自己的窗口?
编辑:充其量我可以打开最小化的记事本,但在尝试上述所有代码后仍然无法将焦点放在表格上。记事本打开最小化,但焦点仍然在记事本上(有时我们在windows xp中看到的东西)和表单将不在焦点。
答案 0 :(得分:11)
我在互联网上尝试了几乎所有东西(所以肯定:))。充其量我可以把我的形式放在所有其他形式之上,但没有焦点(通过@Hans Passant的方法)。在各地都有大量的代码,我不知怎的感觉这很容易。所以我总是使用SetForegroundWindow()
和其他代码块。从来没有想过只有SetForegroundWindow()
才能做到这一点。
这很有用。
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
private void button1_Click(object sender, EventArgs e)
{
Process process = new Process();
process.StartInfo.FileName = @...\abc.log";
process.Start();
process.WaitForInputIdle(); //this is the key!!
SetForegroundWindow(this.Handle);
}
有时这种方法会关注父窗体(如果我想要的窗体是其父窗体的模态子窗体);在这种情况下,只需将this.Focus()
添加到最后一行..
即便如此:
Microsoft.VisualBasic.Interaction.Shell(@"notepad.exe D:\abc.log",
Microsoft.VisualBasic.AppWinStyle.NormalNoFocus);
提供的解决方案
答案 1 :(得分:2)
我遇到了同样的问题,我最终以编程方式调用alt-tab:
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
private void alttab()
{
uint WM_SYSCOMMAND = 0x0112;
int SC_PREVWINDOW = 0xF050;
PostMessage(Process.GetCurrentProcess().MainWindowHandle, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
}
//编辑:你应该使用process.MainWindowHandle代替课程
答案 2 :(得分:2)
如果您要启动一个过程并集中到表单上,请以最小化状态启动该过程,如下所示:
Dim psi As New ProcessStartInfo("notepad")
psi.WindowStyle = ProcessWindowStyle.Minimized
Process.Start(psi)
答案 3 :(得分:1)
Windows阻止应用程序将窗口推入用户的脸部,您正在看到这一点。应用程序可能窃取焦点的确切规则记录在AllowSetForegroundWindow()的MSDN文档中。
围绕此限制的后门是AttachThreadInput()函数。这段代码工作得很好,我确实找到了拥有前台窗口的线程的线程ID的快捷方式。对记事本来说足够好,可能不适用于其他应用程序。请注意,Raymond Chen 不批准此类黑客行为。
private void button1_Click(object sender, EventArgs e) {
var prc = Process.Start("notepad.exe");
prc.WaitForInputIdle();
int tid = GetCurrentThreadId();
int tidTo = prc.Threads[0].Id;
if (!AttachThreadInput(tid, tidTo, true)) throw new Win32Exception();
this.BringToFront();
AttachThreadInput(tid, tidTo, false);
}
[DllImport("user32.dll", SetLastError = true)]
private static extern bool AttachThreadInput(int tid, int tidTo, bool attach);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
答案 4 :(得分:-1)
试试这个:
public partial class MainForm : Form
{
private ShowForm showForm;
public MainForm()
{
InitializeComponent();
}
private void showButton_Click(object sender, EventArgs e)
{
this.showForm = new ShowForm();
this.showForm.FormClosed += showForm_FormClosed;
this.showForm.Show(this);
}
private void showForm_FormClosed(object sender, FormClosedEventArgs e)
{
this.Focus();
}
}