当前位置:  开发笔记 > 编程语言 > 正文

C#强制表格焦点

如何解决《C#强制表格焦点》经验,为你挑选了2个好方法。

所以,在询问这个问题之前,我确实搜索了谷歌和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();

表单仍然出现了PowerShell会话.我将继续研究线程.我之前已经生成了线程,但从来没有父线程需要与子线程进行通信,因此我们将看到它是如何进行的.

到目前为止,所有想法都有所帮助.


好吧,线程处理问题.@Quarrelsome,我确实试过了这两个.两者(或两者都没有)都起作用.我很好奇使用线程的坏处是什么?我没有使用Application.Run,​​我还没有遇到问题.我正在使用父线程和子线程都可以访问的中介类.在该对象中,我使用ReaderWriterLock来锁定一个属性,该属性表示我想要在子线程创建的表单上显示的消息.父锁定属性然后写入应显示的内容.子线程锁定属性并读取应将表单上的标签更改为的内容.孩子必须在轮询间隔(我默认为500毫秒)这样做,我真的不高兴,但我找不到一个事件驱动的方式让孩子线程知道这个程度已经改变,



1> Dean Hill..:

我也无法激活并将窗口带到前台.这是最终为我工作的代码.我不确定它是否能解决你的问题.

基本上,调用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);
    }
}



2> Kevin Gale..:

以下是我在一种或另一种形式上使用了几年的一些代码.弹出另一个应用程序窗口有一些问题.一旦你有窗口句柄,执行以下操作:

      if (IsIconic(hWnd))
        ShowWindowAsync(hWnd, SW_RESTORE);

      ShowWindowAsync(hWnd, SW_SHOW);

      SetForegroundWindow(hWnd);

      // Code from Karl E. Peterson, www.mvps.org/vb/sample.htm
      // Converted to Delphi by Ray Lischner
      // Published in The Delphi Magazine 55, page 16
      // Converted to C# by Kevin Gale
      IntPtr foregroundWindow = GetForegroundWindow();
      IntPtr Dummy = IntPtr.Zero;

      uint foregroundThreadId = GetWindowThreadProcessId(foregroundWindow, Dummy);
      uint thisThreadId       = GetWindowThreadProcessId(hWnd, Dummy);

      if (AttachThreadInput(thisThreadId, foregroundThreadId, true))
      {
        BringWindowToTop(hWnd); // IE 5.5 related hack
        SetForegroundWindow(hWnd);
        AttachThreadInput(thisThreadId, foregroundThreadId, false);
      }

      if (GetForegroundWindow() != hWnd)
      {
        // Code by Daniel P. Stasinski
        // Converted to C# by Kevin Gale
        IntPtr Timeout = IntPtr.Zero;
        SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, Timeout, 0);
        SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Dummy, SPIF_SENDCHANGE);
        BringWindowToTop(hWnd); // IE 5.5 related hack
        SetForegroundWindow(hWnd);
        SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Timeout, SPIF_SENDCHANGE);
      }

我不会发布整个单元,因为它做了其他不相关的事情,但这里是上面代码的常量和导入.

//Win32 API calls necesary to raise an unowned processs main window

[DllImport("user32.dll")]

private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern bool IsIconic(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("user32.dll")]
static extern bool BringWindowToTop(IntPtr hWnd);

[DllImport("user32.dll")] 
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, Int32 nMaxCount);
[DllImport("user32.dll")]
private static extern int GetWindowThreadProcessId(IntPtr hWnd, ref Int32 lpdwProcessId);
[DllImport("User32.dll")]
public static extern IntPtr GetParent(IntPtr hWnd); 

private const int SW_HIDE = 0;
private const int SW_SHOWNORMAL = 1;
private const int SW_NORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private const int SW_SHOWMAXIMIZED = 3;
private const int SW_MAXIMIZE = 3;
private const int SW_SHOWNOACTIVATE = 4;
private const int SW_SHOW = 5;
private const int SW_MINIMIZE = 6;
private const int SW_SHOWMINNOACTIVE = 7;
private const int SW_SHOWNA = 8;
private const int SW_RESTORE = 9;
private const int SW_SHOWDEFAULT = 10;
private const int SW_MAX = 10;

private const uint SPI_GETFOREGROUNDLOCKTIMEOUT = 0x2000;
private const uint SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001;
private const int  SPIF_SENDCHANGE = 0x2;


顺便说一句,根据Raymond Chen的说法,这似乎是一种危险的做法,这可能会引起UI冻结:我警告过你:附加输入队列的危险性http://blogs.msdn.com/b/oldnewthing/archive/2008/08/01/ 8795860.aspx你有没有遇到过这个问题凯文?
推荐阅读
落单鸟人
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有