C# 强制形成焦点

2024-04-23

所以,在问这个问题之前,我确实搜索了谷歌和SO。基本上我有一个 DLL,其中编译了一个表单。该表单将用于在屏幕上显示信息。最终它将是异步的并公开 dll 中的大量自定义内容。现在我只想让它正确显示。我遇到的问题是我通过在 Powershell 会话中加载 dll 来使用它。因此,当我尝试显示表单并让它到达顶部并获得焦点时,它在所有其他应用程序上显示都没有问题,但我一生都无法让它在 Powershell 窗口上显示。这是我当前用来尝试显示它的代码。我确信一旦我弄清楚了,其中的大部分就不再需要了,这只是代表了我通过谷歌找到的所有东西。

CLass Blah
{
        [DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
        public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, uint pvParam, uint fWinIni);

        [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("User32.dll", EntryPoint = "ShowWindowAsync")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
        private const int WS_SHOWNORMAL = 1;

    public void ShowMessage(string msg)
    {
            MessageForm msgFrm = new MessageForm();
            msgFrm.lblMessage.Text = "FOO";
            msgFrm.ShowDialog();
            msgFrm.BringToFront();
            msgFrm.TopMost = true;
            msgFrm.Activate();

            SystemParametersInfo((uint)0x2001, 0, 0, 0x0002 | 0x0001);
            ShowWindowAsync(msgFrm.Handle, WS_SHOWNORMAL);
            SetForegroundWindow(msgFrm.Handle);
            SystemParametersInfo((uint)0x2001, 200000, 200000, 0x0002 | 0x0001);
    }
}

正如我所说,我确信其中大部分要么是不需要的,要么是完全错误的,我只是想展示我尝试过的东西。另外,正如我所提到的,我计划在某个时候异步显示它,我怀疑这最终需要一个单独的线程。将表单拆分到它自己的线程中是否可以更轻松地使其在 Powershell 会话上获得焦点?


@Joel,谢谢您的信息。这是我根据您的建议尝试的:

msgFrm.ShowDialog();
msgFrm.BringToFront();
msgFrm.Focus();
Application.DoEvents();

表格仍然出现underPowershell 会话。我将继续处理线程。我之前已经生成过线程,但从未在父线程需要与子线程通信的地方生成过,所以我们将看看它是如何进行的。

感谢大家迄今为止提出的所有想法。


好吧,线程化解决了这个问题。 @Quarrelsome,我确实尝试了这两个。两者都不起作用(或两者一起)。我很好奇使用线程有什么坏处?我没有使用 Application.Run 并且还没有遇到问题。我正在使用父线程和子线程都可以访问的中介类。在该对象中,我使用 ReaderWriterLock 来锁定一个属性,该属性代表我想要在子线程创建的表单上显示的消息。父级锁定该属性,然后写入应显示的内容。子线程锁定该属性并读取应将表单上的标签更改为的内容。孩子必须在轮询间隔(我默认为 500 毫秒)上执行此操作,我对此并不满意,但我找不到事件驱动的方式来让子线程知道属性已更改,所以我'我陷入了投票困境。


我在激活窗口并将其带到前台时也遇到了麻烦。这是最终对我有用的代码。我不确定它是否能解决你的问题。

基本上,先调用 ShowWindow(),然后调用 SetForegroundWindow()。

using System.Diagnostics;
using System.Runtime.InteropServices;

// Sets the window to be foreground
[DllImport("User32")]
private static extern int SetForegroundWindow(IntPtr hwnd);

// Activate or minimize a window
[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;

private void ActivateApplication(string briefAppName)
{
    Process[] procList = Process.GetProcessesByName(briefAppName);

    if (procList.Length > 0)
    {
        ShowWindow(procList[0].MainWindowHandle, SW_RESTORE);
        SetForegroundWindow(procList[0].MainWindowHandle);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 强制形成焦点 的相关文章

随机推荐