Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 打开流程(记事本)后如何将焦点设置回窗体?_C#_Winforms_Process_Focus_Windows Shell - Fatal编程技术网

C# 打开流程(记事本)后如何将焦点设置回窗体?

C# 打开流程(记事本)后如何将焦点设置回窗体?,c#,winforms,process,focus,windows-shell,C#,Winforms,Process,Focus,Windows Shell,我使用Process.Start()从程序中打开记事本,但新打开的记事本覆盖了屏幕。但我确实希望我的应用程序保持其焦点 同样地,我(使用相同的Process.Start)打开MS Excel和Word,但为了让焦点回到我的表单,我需要写的是: this.Focus(); 但记事本的怪癖是:我打开记事本(以及所有其他类似的过程) 现在记事本成为焦点 我试过这些: this.Activate(),this.Focus(),不用说 另一个较长的解决方案来自 所有这些仍然保持着对记事本的关注。为什

我使用
Process.Start()
从程序中打开记事本,但新打开的记事本覆盖了屏幕。但我确实希望我的应用程序保持其焦点

同样地,我(使用相同的Process.Start)打开MS Excel和Word,但为了让焦点回到我的表单,我需要写的是:

this.Focus();
但记事本的怪癖是:我打开记事本(以及所有其他类似的过程)

现在记事本成为焦点

我试过这些:

  • this.Activate()
    this.Focus()
    ,不用说

  • 另一个较长的解决方案来自

  • 所有这些仍然保持着对记事本的关注。为什么仅仅获得一个窗口的焦点如此困难,以至于应用程序自己的窗口也如此困难


    编辑:我最多可以打开记事本最小化,但在尝试了以上所有代码后,它仍然无法将焦点放在表单上。记事本打开时最小化,但焦点仍在记事本上(我们在windows xp中有时会看到这种情况),窗体将失去焦点。

    我也遇到了同样的问题,我最终以编程方式调用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,而不是Windows。Windows阻止应用程序将其窗口推到用户的脸上,您在工作中看到了这一点。应用程序窃取焦点的确切规则记录在AllowSetForeGroundIndow()的MSDN文档中

    围绕此限制的后门是AttachThreadInput()函数。这段代码运行得很好,我在查找拥有前台窗口的线程的线程ID时使用了快捷方式。对于记事本来说已经足够好了,可能不适合其他应用。请注意,雷蒙德·陈不赞成这种黑客行为

        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();
    

    我在互联网上尝试了几乎所有的东西(非常确定:))。充其量我可以把我的表格放在所有其他表格之上,但没有重点(按照@Hans Passant的方法)。通过大量的代码,我不知何故觉得这并不容易。因此,我总是将
    setForeGroundIndow()
    与其他代码块一起使用。从来没有想过仅仅
    setforegroundindow()
    就能做到这一点

    这起作用了

    [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);
    

    提供的解决方案请尝试以下方法:

    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();
        }
    }
    

    如果要启动流程并将焦点放回表单,请使用最小化状态启动该流程,如下所示:

    Dim psi As New ProcessStartInfo("notepad")
    psi.WindowStyle = ProcessWindowStyle.Minimized
    Process.Start(psi)
    

    在最小化状态下启动窗口可以吗?可以,但仍然不能工作。我会在我的问题中更新你试过这个吗?谢谢但我怀疑BringToFront是否真的在这里有效。这不只是一种使控件在另一个控件上方可见的措施吗?不是吗。激活是一个更好的选择吗?还有谁是陈雷蒙?要批准这个吗BringToFront()调用setForeGroundIndow(),只需编写代码即可轻松查看。Raymond Chen是一名微软程序员,拥有一个广受欢迎的博客。把答案也贴在这里,我不想惹他生气。Hans:这段代码允许我的表单显示在记事本上,但现在的焦点既不在表单上,也不在记事本上。我试过这个。激活这个。聚焦,但应用程序上仍然没有聚焦。这对我们的客户来说是一个严肃的要求。这是如何回答这个问题的?这是有效的,并回答了所问的问题,但更好的解决方案是首先防止启动的流程窃取焦点,而不是让调用方在失去焦点后重新获得焦点。看,实际上,我错过了你的第二个命令已经做了我在之前的评论中建议的事情,这是由和它的旗帜提供的。
    Microsoft.VisualBasic.Interaction.Shell(@"notepad.exe D:\abc.log", 
                                            Microsoft.VisualBasic.AppWinStyle.NormalNoFocus);
    
    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();
        }
    }
    
    Dim psi As New ProcessStartInfo("notepad")
    psi.WindowStyle = ProcessWindowStyle.Minimized
    Process.Start(psi)