【问题标题】:Make all forms associated with a program come to the front when one form is selected选择一个表单时,将与程序关联的所有表单置于最前面
【发布时间】:2012-01-25 22:15:52
【问题描述】:

我的应用程序MainFormHexCompare 中有两个表单。如果我点击我的应用程序到另一个窗口,然后我点击两个表单之一,只有其中一个出现在前面。我怎样才能做到这一点,如果我单击两个表单中的任何一个,它会将两者都带到应用程序中所有打开的表单的顶部?现在我需要单独选择每个表单以将它们放在我的窗口堆栈的顶部(这可能非常烦人,因为HexCompareShowInTaskbar 设置为false

以我想要的方式工作的一个很好的例子是大多数“查找”对话框的工作方式。如果单击查找对话框,如果它被另一个应用程序隐藏,它会将主窗体带到前面,如果单击主窗体,如果它被另一个应用程序隐藏,则查找对话框将位于前面。

MainForm 是如何被调用的。

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new MainForm());
}

HexCompare 是如何被调用的

private void lstCaputres_SelectedIndexChanged(object sender, EventArgs e)
{
    var selectedItem = (Tuple<DateTime, byte[]>)lstCaputres.SelectedItem;
    if (hexCompare == null || hexCompare.IsDisposed)
    {
        hexCompare = new HexCompare(selectedItem.Item2);
        hexCompare.Show();
    }
    else
        hexCompare.ChangeValue(selectedItem.Item2);
}

编辑:

看来HexCompareParent 的值是Null。如果我能以某种方式将其设置为 MainForm 会解决我的问题吗?如果可以,我该如何设置?

EDIT2:

我已经使用 Tigran 的解决方案半解决了它,但它会导致闪烁,因为每个表单都被带到前面,如果有更好的解决方案我仍然感兴趣。

//In MainForm.cs
private void MainForm_Activated(object sender, EventArgs e)
{
    hexCompare.BringToFront();
    this.BringToFront();
}

//in HexCompare.cs
private void HexCompare_Activated(object sender, EventArgs e)
{
    parent.BringToFront();
    this.BringToFront();
}

【问题讨论】:

    标签: c# .net winforms .net-4.0


    【解决方案1】:

    您可以使用以下API wrapper 将表单置于 z 顺序的前面,而不会使其失去焦点。这个函数可以在主窗体的 Activated 事件中调用,只需将 HexCompare 窗体作为参数传递给它。这与其他答案没有太大不同,但我从未目睹过您在 cmets 中提到的任何闪烁。

      private const int SW_SHOWNOACTIVATE = 4;
      private const int HWND_TOPMOST = 0;
      private const uint SWP_NOACTIVATE = 0x0010;
    
      [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
      static extern bool SetWindowPos(
           int hWnd,           // window handle 
           int hWndInsertAfter,    // placement-order handle 
           int X,          // horizontal position 
           int Y,          // vertical position 
           int cx,         // width 
           int cy,         // height 
           uint uFlags);       // window positioning flags 
    
      [DllImport("user32.dll")]
      static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    
      public void ShowInactiveTopmost(Form frm)
      {
         ShowWindow(frm.Handle, SW_SHOWNOACTIVATE);
         SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
         frm.Left, frm.Top, frm.Width, frm.Height,
         SWP_NOACTIVATE);
      }
    

    【讨论】:

    • ShowWithoutActivation 是干什么用的?我没有看到它在任何地方使用。但是,您的解决方案在大多数情况下确实消除了闪烁,比BringToFront 好得多。偶尔ListBox 中的选定项目会取消选择然后很快重新选择,但除此之外它是完美的。
    • 抱歉,看来我只是对复制/粘贴过于热心了。我会编辑它。很高兴它有帮助,它帮助了我们很多!
    【解决方案2】:

    对我来说,设置TopMost=true 并在两种表单上调用BringToFront() 似乎就足够了。

    hexCompare = new HexCompare(selectedItem.Item2);
    hexCompare.TopMost = true;
    hexCompare.Show();
    hexCompare.BringToFront();
    

    类似的东西。

    【讨论】:

    • 当它第一次产生时不是问题,如果我将代码放在Activated 中,我可以看到您的解决方案适用于这两种形式,但似乎这个解决方案不适用于一般情况。
    • @ScottChamberlain:为什么不应该这样做?如果不需要,可以避免设置TopMost=true
    • 它可以工作,但它使我的表单在聚焦每个表单时闪烁。这可以工作,但我真的很想看看是否有更好的解决方案。
    • @ScottChamberlain: 可以尝试在SuspendLayout()ResumeLayout() 之间管理每个表单的这段代码。
    • 在调用BringToFront() 时暂停布局仍然会导致闪烁。与表单本身相比,Aero 影响绘图的阴影中的闪烁更多。
    猜你喜欢
    • 1970-01-01
    • 2012-10-07
    • 2010-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多