Đưa một cửa sổ ra phía trước trong WPF


214

Làm cách nào tôi có thể mang ứng dụng WPF của mình ra phía trước máy tính để bàn? Cho đến nay tôi đã thử:

SwitchToThisWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle, true);

SetWindowPos(new WindowInteropHelper(Application.Current.MainWindow).Handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

SetForegroundWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle);

Không ai trong số họ đang thực hiện công việc ( Marshal.GetLastWin32Error()nói rằng các thao tác này đã hoàn thành thành công và các thuộc tính P / Gọi cho mỗi định nghĩa có SetLastError=true).

Nếu tôi tạo một ứng dụng WPF trống mới và gọi SwitchToThisWindowbằng bộ hẹn giờ, nó sẽ hoạt động chính xác như mong đợi, vì vậy tôi không chắc tại sao nó không hoạt động trong trường hợp ban đầu của tôi.

Chỉnh sửa : Tôi đang làm điều này kết hợp với một phím nóng toàn cầu.


Bạn đã xác minh rằng MainWindow là cửa sổ bạn muốn chưa? Từ MSDN: MainWindow được tự động thiết lập với tham chiếu đến đối tượng Window đầu tiên được khởi tạo trong AppDomain.
Todd White

Suy nghĩ tốt, nhưng nó là Cửa sổ duy nhất trong ứng dụng.
Yếu tố huyền bí

Bạn có thể cung cấp thêm một chút mã bối cảnh?
Todd White

Câu trả lời:


314
myWindow.Activate();

Nỗ lực đưa cửa sổ lên nền trước và kích hoạt nó.

Điều đó nên thực hiện các mẹo, trừ khi tôi hiểu lầm và bạn muốn Luôn luôn hành vi hàng đầu. Trong trường hợp đó bạn muốn:

myWindow.TopMost = true;

14
Tôi chỉ đơn giản là sử dụng myWindow.Show () và đôi khi nó không ở trên đỉnh. Tôi đã thực hiện một cuộc gọi đến myWindow.Activate () ngay sau đó và nó đã hoạt động.
Bermo

4
Kích hoạt đôi khi không hoạt động trên Windows XP. Tôi đề nghị câu trả lời của @Matthew Xavier.
Lex Li

Một chút kỳ lạ, vì theo mặc định ShowActivated được bật.
greenoldman

1
Câu trả lời đầu tiên là tốt, cảm ơn vì điều đó! Nhưng dòng mã thứ hai, sử dụng thuộc Topmosttính là một thực tiễn xấu vì nó có thể che khuất các hộp thoại bật lên khác và có hành vi không mong muốn.
Jonathan Perry

2
Trên thực tế nó có thể được thực hiện với điều này: if (myWindow.WindowState == WindowState.Minimized) myWindow.WindowState = WindowState.Normal;kỳ lạ là nó cũng sẽ bảo vệ bất kỳ cửa sổ Tối đa hóa nào và không hoàn nguyên chúng về trạng thái Bình thường.
r41n

168

Tôi đã tìm thấy một giải pháp đưa cửa sổ lên trên cùng, nhưng nó hoạt động như một cửa sổ bình thường:

if (!Window.IsVisible)
{
    Window.Show();
}

if (Window.WindowState == WindowState.Minimized)
{
    Window.WindowState = WindowState.Normal;
}

Window.Activate();
Window.Topmost = true;  // important
Window.Topmost = false; // important
Window.Focus();         // important

1
Gợi ý tuyệt vời! TopMost làm cho điều kỳ diệu xảy ra trên Windows 7 nếu cửa sổ đã mở, nhưng bên dưới các cửa sổ khác.
gsb

Điều này cũng đã lừa tôi. Cảm ơn gsb đã bình luận thêm về việc sử dụng TopMost kỳ lạ như thế nào!
Jen

1
Cảm ơn - bản sửa lỗi ngắn và ngọt ngào.
code4life

2
Trong trường hợp của tôi, Window.Activate () và Window.F Focus () là đủ. Cài đặt Window.TopMost là không cần thiết.
ác

6
Không sử dụng Window.Focus(). Điều này sẽ lấy sự tập trung ra khỏi những gì người dùng hiện đang gõ trong hộp văn bản, điều này gây khó chịu cho người dùng cuối. Các mã ở trên chỉ hoạt động tốt mà không có nó.
Contango

32

Trong trường hợp bạn cần cửa sổ ở phía trước lần đầu tiên tải thì bạn nên sử dụng như sau:

private void Window_ContentRendered(object sender, EventArgs e)
{
    this.Topmost = false;
}

private void Window_Initialized(object sender, EventArgs e)
{
    this.Topmost = true;
}

1
Nếu bạn phát triển một cái gì đó tương tự Launchy ( launchy.net ) trong C #, bạn sẽ nhận thấy câu trả lời này gần như vô dụng.
Lex Li

21

Để biến nó thành một bản sao chép nhanh dán -
Sử dụng DoOnProcessphương thức 'lớp này để di chuyển cửa sổ chính của quá trình sang tiền cảnh (nhưng không lấy cắp tiêu điểm từ các cửa sổ khác)

public class MoveToForeground
{
    [DllImportAttribute("User32.dll")]
    private static extern int FindWindow(String ClassName, String WindowName);

    const int SWP_NOMOVE        = 0x0002;
    const int SWP_NOSIZE        = 0x0001;            
    const int SWP_SHOWWINDOW    = 0x0040;
    const int SWP_NOACTIVATE    = 0x0010;
    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);

    public static void DoOnProcess(string processName)
    {
        var allProcs = Process.GetProcessesByName(processName);
        if (allProcs.Length > 0)
        {
            Process proc = allProcs[0];
            int hWnd = FindWindow(null, proc.MainWindowTitle.ToString());
            // Change behavior by settings the wFlags params. See http://msdn.microsoft.com/en-us/library/ms633545(VS.85).aspx
            SetWindowPos(new IntPtr(hWnd), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
        }
    }
}

HTH


6
+1 đây là câu trả lời duy nhất hữu ích cho tôi. Tôi có một ứng dụng với một chủ và một số cửa sổ nô lệ nổi. Khi kích hoạt bất kỳ thứ nào trong số này, tất cả các cửa sổ khác cũng sẽ được đưa ra phía trước. Nhưng không được kích hoạt / lấy nét như hầu hết các câu trả lời cho thấy: đó là một thảm họa vì nó làm cho cửa sổ hiện đang nhấp vào không thể nhìn thấy được vì đột nhiên một cửa sổ khác lấy nét.
stijn

Bất kỳ lý do cho việc không sử dụng process.MainWindowHandle?
Sriram Sakth Xoay

Trong trường hợp của tôi, tôi không muốn có cửa sổ chính, nhưng đồng ý, có nhiều cách khác để có được một cửa sổ hWnd. FWIW một HwndSourceđối tượng hoạt động tốt.
tobriand

21

Tôi biết câu hỏi này khá cũ, nhưng tôi vừa gặp kịch bản chính xác này và muốn chia sẻ giải pháp tôi đã thực hiện.

Như đã đề cập trong các bình luận trên trang này, một số giải pháp được đề xuất không hoạt động trên XP, mà tôi cần hỗ trợ trong kịch bản của mình. Mặc dù tôi đồng ý với tình cảm của @Matthew Xavier rằng nói chung đây là một thực hành UX tồi tệ, có những lúc nó hoàn toàn là một UX đáng tin cậy.

Giải pháp đưa cửa sổ WPF lên hàng đầu thực sự được cung cấp cho tôi bằng chính mã tôi đang sử dụng để cung cấp phím nóng toàn cầu. Một bài viết trên blog của Joseph Cooney chứa một liên kết đến các mẫu mã của anh ấy chứa mã gốc.

Tôi đã dọn dẹp và sửa đổi mã một chút và triển khai nó như một phương thức mở rộng cho System.Windows.Window. Tôi đã thử nghiệm điều này trên XP 32 bit và Win7 64 bit, cả hai đều hoạt động chính xác.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace System.Windows
{
    public static class SystemWindows
    {
        #region Constants

        const UInt32 SWP_NOSIZE = 0x0001;
        const UInt32 SWP_NOMOVE = 0x0002;
        const UInt32 SWP_SHOWWINDOW = 0x0040;

        #endregion

        /// <summary>
        /// Activate a window from anywhere by attaching to the foreground window
        /// </summary>
        public static void GlobalActivate(this Window w)
        {
            //Get the process ID for this window's thread
            var interopHelper = new WindowInteropHelper(w);
            var thisWindowThreadId = GetWindowThreadProcessId(interopHelper.Handle, IntPtr.Zero);

            //Get the process ID for the foreground window's thread
            var currentForegroundWindow = GetForegroundWindow();
            var currentForegroundWindowThreadId = GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero);

            //Attach this window's thread to the current window's thread
            AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true);

            //Set the window position
            SetWindowPos(interopHelper.Handle, new IntPtr(0), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);

            //Detach this window's thread from the current window's thread
            AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false);

            //Show and activate the window
            if (w.WindowState == WindowState.Minimized) w.WindowState = WindowState.Normal;
            w.Show();
            w.Activate();
        }

        #region Imports

        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

        [DllImport("user32.dll")]
        private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

        [DllImport("user32.dll")]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

        #endregion
    }
}

Tôi hy vọng mã này sẽ giúp những người khác gặp phải vấn đề này.


Này, nhìn kìa! Tôi đã vật lộn với điều này trong nhiều tháng! Điều này làm việc cho cả tình huống của tôi. Tuyệt vời! (Windows 7 x64)
mdiehl13

Trên thực tế, nó chỉ có vẻ hoạt động nếu tôi làm điều này: App.mainWindow.Show (); SystemWindows.GlobalActivate (App.mainwindow); // Khi tôi xóa .show () đầu tiên, nó sẽ không xuất hiện trước
mdiehl13

+1 cho SetWindowPos (), tôi đang tìm cách chỉ đưa Cửa sổ của mình ra phía trước mà không làm gián đoạn các ứng dụng khác hoặc đánh cắp tiêu điểm. this.Activate () đánh cắp trọng tâm.
Prettyvoid

Điều này đã làm điều đó cho tôi, và trường hợp của tôi là toàn bộ vấn đề là đánh cắp sự tập trung, vì nó rất vui khi người dùng tương tác với một yếu tố nhất định. Vì vậy, cảm ơn rất nhiều điều này dường như làm việc phù hợp! chỉ gọi this.Activate()có vẻ như làm việc một số lần.
Peter

13

Nếu người dùng đang tương tác với một ứng dụng khác, có thể không thể đưa ứng dụng của bạn ra phía trước. Theo nguyên tắc chung, một quy trình chỉ có thể mong đợi để đặt cửa sổ nền trước nếu quy trình đó đã là quy trình nền trước. (Microsoft ghi lại các hạn chế trong mục MSDN SetForegroundWindow () .) Điều này là do:

  1. Người dùng "sở hữu" tiền cảnh. Ví dụ, sẽ vô cùng khó chịu nếu một chương trình khác đánh cắp tiền cảnh trong khi người dùng đang gõ, ít nhất làm gián đoạn tiến trình công việc của cô ấy và có thể gây ra hậu quả không lường trước vì thao tác gõ phím của cô ấy cho một ứng dụng bị hiểu sai cho đến khi cô ấy nhận thấy sự thay đổi .
  2. Hãy tưởng tượng rằng mỗi hai chương trình kiểm tra xem cửa sổ của nó có phải là tiền cảnh hay không và cố gắng đặt nó thành tiền cảnh nếu không. Ngay khi chương trình thứ hai đang chạy, máy tính sẽ vô dụng khi tiền cảnh nảy giữa hai cái ở mỗi chuyển đổi tác vụ.

Điểm tốt. Tuy nhiên, mục đích của mã là kết hợp với một phím nóng toàn cầu và các ứng dụng khác thực hiện bằng cách nào đó.
Yếu tố huyền bí

Phải sử dụng PInvoke trong C # để mô phỏng những gì được mô tả trong bài viết này, codeproject.com/Tips/76427/ trộm
Lex Li

vậy thì tại sao đôi khi các hộp thoại bật lên biểu hiện pha trộn lỗi vẫn hiển thị khi tôi chuyển sang visual studio? : - /
Simon_Weaver

Simon, tôi nghi ngờ rằng các cửa sổ bật lên lỗi mà bạn thấy là các cửa sổ "trên cùng" (một quyết định thiết kế mà tôi không chấp thuận). Có một sự khác biệt giữa cửa sổ nền trước (nhận đầu vào của người dùng) và cửa sổ "trên cùng" theo thứ tự Z. Bất kỳ cửa sổ nào cũng có thể tự làm "trên cùng", đặt nó ở trên tất cả các cửa sổ không phải trên cùng, nhưng không tập trung vào bàn phím cửa sổ, v.v. cách trở thành cửa sổ nền trước.
Matthew Xavier

Thủ thuật thất bại cho một vài cửa sổ đặc biệt. Visual Studio và các cửa sổ nhắc lệnh phải có thứ gì đó ngăn cửa sổ khác trở thành cửa sổ nền trước.
Lex Li

9

Tôi biết rằng đây là câu trả lời muộn, có thể hữu ích cho các nhà nghiên cứu

 if (!WindowName.IsVisible)
 {
     WindowName.Show();
     WindowName.Activate();
 }

9

Tại sao một số câu trả lời trên trang này là sai!

  • Bất kỳ câu trả lời sử dụng window.Focus()là sai.

    • Tại sao? Nếu một thông báo thông báo bật lên, window.Focus()sẽ lấy tiêu điểm ra khỏi bất cứ thứ gì người dùng đang gõ vào thời điểm đó. Điều này cực kỳ gây khó chịu cho người dùng cuối, đặc biệt là nếu các cửa sổ bật lên xảy ra khá thường xuyên.
  • Bất kỳ câu trả lời sử dụng window.Activate()là sai.

    • Tại sao? Nó sẽ làm cho bất kỳ cửa sổ cha mẹ có thể nhìn thấy là tốt.
  • Bất kỳ câu trả lời mà bỏ qua window.ShowActivated = falselà sai.
    • Tại sao? Nó sẽ lấy tiêu điểm ra khỏi một cửa sổ khác khi thông báo bật lên rất khó chịu!
  • Bất kỳ câu trả lời nào không sử dụng Visibility.Visible để ẩn / hiển thị cửa sổ là sai.
    • Tại sao? Nếu chúng ta đang sử dụng Citrix, nếu cửa sổ không bị sập khi đóng, nó sẽ để lại một hình chữ nhật màu đen kỳ lạ trên màn hình. Vì vậy, chúng tôi không thể sử dụng window.Show()window.Hide().

Bản chất:

  • Cửa sổ không nên lấy tiêu điểm ra khỏi bất kỳ cửa sổ nào khác khi nó kích hoạt;
  • Cửa sổ không nên kích hoạt cha mẹ của nó khi nó được hiển thị;
  • Cửa sổ phải tương thích với Citrix.

Giải pháp MVVM

Mã này tương thích 100% với Citrix (không có vùng trống trên màn hình). Nó được thử nghiệm với cả WPF và DevExpress bình thường.

Câu trả lời này dành cho mọi trường hợp sử dụng khi chúng tôi muốn có một cửa sổ thông báo nhỏ luôn ở phía trước các cửa sổ khác (nếu người dùng chọn tùy chọn này trong tùy chọn).

Nếu câu trả lời này có vẻ phức tạp hơn các câu trả lời khác, thì đó là bởi vì nó là mã cấp doanh nghiệp mạnh mẽ. Một số câu trả lời khác trên trang này rất đơn giản nhưng không thực sự hiệu quả.

XAML - Tài sản đính kèm

Thêm thuộc tính đính kèm này vào bất kỳ UserControltrong cửa sổ. Các tài sản đính kèm sẽ:

  • Đợi cho đến khi Loadedsự kiện được kích hoạt (nếu không nó không thể tra cứu cây trực quan để tìm cửa sổ cha).
  • Thêm một trình xử lý sự kiện đảm bảo rằng cửa sổ có thể nhìn thấy hay không.

Tại bất kỳ thời điểm nào, bạn có thể đặt cửa sổ ở phía trước hoặc không, bằng cách lật giá trị của thuộc tính được đính kèm.

<UserControl x:Class="..."
         ...
         attachedProperties:EnsureWindowInForeground.EnsureWindowInForeground=
             "{Binding EnsureWindowInForeground, Mode=OneWay}">

C # - Phương thức trợ giúp

public static class HideAndShowWindowHelper
{
    /// <summary>
    ///     Intent: Ensure that small notification window is on top of other windows.
    /// </summary>
    /// <param name="window"></param>
    public static void ShiftWindowIntoForeground(Window window)
    {
        try
        {
            // Prevent the window from grabbing focus away from other windows the first time is created.
            window.ShowActivated = false;

            // Do not use .Show() and .Hide() - not compatible with Citrix!
            if (window.Visibility != Visibility.Visible)
            {
                window.Visibility = Visibility.Visible;
            }

            // We can't allow the window to be maximized, as there is no de-maximize button!
            if (window.WindowState == WindowState.Maximized)
            {
                window.WindowState = WindowState.Normal;
            }

            window.Topmost = true;
        }
        catch (Exception)
        {
            // Gulp. Avoids "Cannot set visibility while window is closing".
        }
    }

    /// <summary>
    ///     Intent: Ensure that small notification window can be hidden by other windows.
    /// </summary>
    /// <param name="window"></param>
    public static void ShiftWindowIntoBackground(Window window)
    {
        try
        {
            // Prevent the window from grabbing focus away from other windows the first time is created.
            window.ShowActivated = false;

            // Do not use .Show() and .Hide() - not compatible with Citrix!
            if (window.Visibility != Visibility.Collapsed)
            {
                window.Visibility = Visibility.Collapsed;
            }

            // We can't allow the window to be maximized, as there is no de-maximize button!
            if (window.WindowState == WindowState.Maximized)
            {
                window.WindowState = WindowState.Normal;
            }

            window.Topmost = false;
        }
        catch (Exception)
        {
            // Gulp. Avoids "Cannot set visibility while window is closing".
        }
    }
}

Sử dụng

Để sử dụng tính năng này, bạn cần tạo cửa sổ trong ViewModel:

private ToastView _toastViewWindow;
private void ShowWindow()
{
    if (_toastViewWindow == null)
    {
        _toastViewWindow = new ToastView();
        _dialogService.Show<ToastView>(this, this, _toastViewWindow, true);
    }
    ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(_toastViewWindow);
    HideAndShowWindowHelper.ShiftWindowIntoForeground(_toastViewWindow);
}

private void HideWindow()
{
    if (_toastViewWindow != null)
    {
        HideAndShowWindowHelper.ShiftWindowIntoBackground(_toastViewWindow);
    }
}

Liên kết bổ sung

Để biết các mẹo về cách đảm bảo rằng cửa sổ thông báo luôn chuyển trở lại màn hình hiển thị, hãy xem câu trả lời của tôi: Trong WPF, làm thế nào để chuyển cửa sổ lên màn hình nếu màn hình tắt? .


5
"Mã cấp doanh nghiệp" và một vài dòng sau catch (Exception) { }. Vâng đúng ... Và nó sử dụng mã thậm chí không được hiển thị trong câu trả lời như _dialogServicehoặc ShiftWindowOntoScreenHelper. Cộng với yêu cầu tạo cửa sổ ở phía viewmodel (về cơ bản phá vỡ toàn bộ mẫu MVVM) ...
Kryptos

@Kryptos Đây là mã cấp doanh nghiệp. Tôi đã gõ nó ra khỏi bộ nhớ và kỹ thuật chính xác này được sử dụng trong một công ty FTSE100 lớn. Cuộc sống thực có phần ít nguyên sơ hơn so với các mẫu thiết kế hoàn hảo mà tất cả chúng ta đang hướng tới.
Contango

Tôi không thích việc chúng ta giữ một phiên bản của cửa sổ trong mô hình khung nhìn, như Kryptos đã đề cập, phá vỡ toàn bộ quan điểm của mvvm, có lẽ nó đã được thực hiện trong codebehind?
Igor Meszaros

1
@Igor Meszaros Đồng ý. Bây giờ tôi có nhiều kinh nghiệm hơn, nếu tôi phải làm lại, tôi sẽ thêm Hành vi và điều khiển nó bằng cách sử dụng một Func<>ràng buộc với ViewModel.
Contango

7

Tôi đã gặp vấn đề tương tự với ứng dụng WPF được gọi từ ứng dụng Access thông qua đối tượng Shell.

Giải pháp của tôi là bên dưới - hoạt động trong XP và Win7 x64 với ứng dụng được biên dịch cho mục tiêu x86.

Tôi muốn làm điều này hơn là mô phỏng một tab alt.

void Window_Loaded(object sender, RoutedEventArgs e)
{
    // make sure the window is normal or maximised
    // this was the core of the problem for me;
    // even though the default was "Normal", starting it via shell minimised it
    this.WindowState = WindowState.Normal;

    // only required for some scenarios
    this.Activate();
}

4

Chà, vì đây là một chủ đề nóng như vậy ... đây là những gì làm việc cho tôi. Tôi đã gặp lỗi nếu tôi không làm theo cách này vì Activate () sẽ báo lỗi cho bạn nếu bạn không thể nhìn thấy cửa sổ.

Xaml:

<Window .... 
        Topmost="True" 
        .... 
        ContentRendered="mainWindow_ContentRendered"> .... </Window>

Mã ẩn:

private void mainWindow_ContentRendered(object sender, EventArgs e)
{
    this.Topmost = false;
    this.Activate();
    _UsernameTextBox.Focus();
}

Đây là cách duy nhất để tôi có được cửa sổ hiển thị trên đầu trang. Sau đó kích hoạt nó để bạn có thể gõ vào hộp mà không phải đặt tiêu điểm bằng chuột. control.F Focus () sẽ không hoạt động trừ khi cửa sổ là Active ();


2

Vâng, tôi đã tìm ra một công việc xung quanh. Tôi đang thực hiện cuộc gọi từ một móc bàn phím được sử dụng để thực hiện một phím nóng. Cuộc gọi hoạt động như mong đợi nếu tôi đặt nó vào BackgroundWorker với một khoảng dừng. Đó là một loại bùn, nhưng tôi không biết tại sao nó không hoạt động ban đầu.

void hotkey_execute()
{
    IntPtr handle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
    BackgroundWorker bg = new BackgroundWorker();
    bg.DoWork += new DoWorkEventHandler(delegate
        {
            Thread.Sleep(10);
            SwitchToThisWindow(handle, true);
        });
    bg.RunWorkerAsync();
}

Chỉ quan tâm: Bạn đã thử Window.Activate (như được đề xuất bởi Morten) và các đề xuất khác? Họ có vẻ ít hack hơn so với bùn thừa nhận này.
Simon D.

Điều này đã được cách đây khá lâu, nhưng đúng vậy, tại thời điểm tôi đã thử nó
Yếu tố huyền bí

Điều này không hoạt động trên Windows XP của tôi. Tôi đề nghị câu trả lời của @Matthew Xavier.
Lex Li

2

Để hiển thị BẤT CỨ cửa sổ hiện đang mở, nhập các DLL đó:

public partial class Form1 : Form
{
    [DllImportAttribute("User32.dll")]
    private static extern int FindWindow(String ClassName, String WindowName);
    [DllImportAttribute("User32.dll")]
    private static extern int SetForegroundWindow(int hWnd);

và trong chương trình Chúng tôi tìm kiếm ứng dụng có tiêu đề được chỉ định (viết tiêu đề không có chữ cái đầu tiên (chỉ số> 0))

  foreach (Process proc in Process.GetProcesses())
                {
                    tx = proc.MainWindowTitle.ToString();
                    if (tx.IndexOf("Title of Your app WITHOUT FIRST LETTER") > 0)
                    {
                        tx = proc.MainWindowTitle;
                        hWnd = proc.Handle.ToInt32(); break;
                    }
                }
                hWnd = FindWindow(null, tx);
                if (hWnd > 0)
                {
                    SetForegroundWindow(hWnd);
                }

"Tiêu đề của ứng dụng của bạn KHÔNG CÓ BÀI ĐẦU TIÊN" Oof, hacky hacky hacky. Tại sao không sử dụng IndexOfđúng cách, thay vào đó?
Các cuộc đua nhẹ nhàng trong quỹ đạo

1

Vấn đề có thể là luồng xử lý mã của bạn từ hook không được khởi chạy bởi bộ thực thi nên việc gọi các phương thức thời gian chạy không hoạt động.

Có lẽ bạn có thể thử thực hiện một Invoke để sắp xếp mã của bạn vào luồng UI để gọi mã của bạn đưa cửa sổ lên phía trước.


1

Các mã này sẽ hoạt động tốt mọi lúc.

Đầu tiên, đặt trình xử lý sự kiện được kích hoạt trong XAML:

Activated="Window_Activated"

Thêm dòng dưới đây vào khối xây dựng Cửa sổ chính của bạn:

public MainWindow()
{
    InitializeComponent();
    this.LocationChanged += (sender, e) => this.Window_Activated(sender, e);
}

Và bên trong trình xử lý sự kiện được kích hoạt sao chép mã này:

private void Window_Activated(object sender, EventArgs e)
{
    if (Application.Current.Windows.Count > 1)
    {
        foreach (Window win in Application.Current.Windows)
            try
            {
                if (!win.Equals(this))
                {
                    if (!win.IsVisible)
                    {
                        win.ShowDialog();
                    }

                    if (win.WindowState == WindowState.Minimized)
                    {
                        win.WindowState = WindowState.Normal;
                    }

                    win.Activate();
                    win.Topmost = true;
                    win.Topmost = false;
                    win.Focus();
                }
            }
            catch { }
    }
    else
        this.Focus();
}

Các bước này sẽ hoạt động tốt và sẽ đưa ra phía trước tất cả các cửa sổ khác vào cửa sổ cha mẹ của chúng.


0

Nếu bạn đang cố gắng để ẩn cửa sổ, ví dụ bạn thu nhỏ cửa sổ, tôi đã thấy rằng bằng cách sử dụng

    this.Hide();

sẽ ẩn nó một cách chính xác, sau đó chỉ cần sử dụng

    this.Show();

sau đó sẽ hiển thị cửa sổ là mục hàng đầu nhất một lần nữa.


0

Chỉ muốn thêm một giải pháp cho câu hỏi này. Việc triển khai này hoạt động theo kịch bản của tôi, nơi CaliBurn chịu trách nhiệm hiển thị Cửa sổ chính.

protected override void OnStartup(object sender, StartupEventArgs e)
{
    DisplayRootViewFor<IMainWindowViewModel>();

    Application.MainWindow.Topmost = true;
    Application.MainWindow.Activate();
    Application.MainWindow.Activated += OnMainWindowActivated;
}

private static void OnMainWindowActivated(object sender, EventArgs e)
{
    var window = sender as Window;
    if (window != null)
    {
        window.Activated -= OnMainWindowActivated;
        window.Topmost = false;
        window.Focus();
    }
}

0

Hãy nhớ không đặt mã hiển thị cửa sổ đó bên trong trình xử lý PreviewMouseDoubleClick vì cửa sổ đang hoạt động sẽ chuyển trở lại cửa sổ đã xử lý sự kiện. Chỉ cần đặt nó vào trình xử lý sự kiện MouseDoubleClick hoặc ngừng tạo bọt bằng cách đặt e.Handled thành True.

Trong trường hợp của tôi, tôi đã xử lý PreviewMouseDoubleClick trên Listview và không đặt e.Handled = true thì nó đã nâng phù thủy sự kiện MouseDoubleClick trở lại cửa sổ ban đầu.


-1

Tôi đã xây dựng một phương thức mở rộng để sử dụng lại dễ dàng.

using System.Windows.Forms;
    namespace YourNamespace{
        public static class WindowsFormExtensions {
            public static void PutOnTop(this Form form) {
                form.Show();
                form.Activate();
            }// END PutOnTop()       
        }// END class
    }// END namespace

Gọi trong Trình xây dựng biểu mẫu

namespace YourNamespace{
       public partial class FormName : Form {
       public FormName(){
            this.PutOnTop();
            InitalizeComponents();
        }// END Constructor
    } // END Form            
}// END namespace

Chào Mike. Bạn đang trả lời câu hỏi này khá muộn. Bạn có thể giải thích trong câu trả lời của mình tại sao cách tiếp cận này khác (và có lẽ tốt hơn) với các câu trả lời rất hay đã được đăng cho câu hỏi này không?
Noel Widmer

Chỉ muộn khi tôi chỉ cần làm điều này, và tôi đã xem qua điều này và muốn chia sẻ cách tôi giải quyết vấn đề mà người khác muốn sử dụng nó.
Mike

Chắc chắn, tôi đã được chọn để xem lại bài viết của bạn và muốn làm cho bạn biết. Luôn luôn tốt để cung cấp một câu trả lời mới nếu bạn nghĩ rằng đó là một đóng góp tốt cho cộng đồng.
Noel Widmer

2
Câu hỏi này đặc biệt về WPF, nhưng giải pháp của bạn là dành cho WinForms.
Brian Reichle
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.