Application.OpenForms.Count = 0 всегда

У меня такая ситуация. Application.OpenForms не возвращает правильный результат. т.е. Application.OpenForms.Count = 0 всегда..

Цель получения формы - получить владельца формы, чтобы я мог передать владельца как параметр функции MessageBox.Show().

Ответы

Ответ 1

Там есть ошибка в Windows Forms, которая делает форму исчезающей из коллекции Application.OpenForms. Это произойдет, если после создания окна назначить свойства ShowInTaskbar, FormBorderStyle, ControlBox, Min/MaximizedBox, RightToLeftLayout, HelpButton, Opacity, TransparencyKey, ShowIcon или MdiParent. Эти свойства отличаются тем, что они указаны как флаги стиля в собственном вызове CreateWindowEx(). Эта форма образца демонстрирует ошибку:

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        button1.Click += button1_Click;
    }
    private void button1_Click(object sender, EventArgs e) {
        Console.WriteLine(Application.OpenForms.Count);
        this.ShowInTaskbar = !this.ShowInTaskbar;
        Console.WriteLine(Application.OpenForms.Count);
    }
}

Windows Forms снова вызовет CreateWindowEx(), чтобы сделать измененное свойство эффективным, передав разные флаги стилей. Уничтожение исходного окна сначала имеет побочные эффекты за пределами очень заметного мерцания, один из них заключается в том, что класс приложения теряет следы формы, так как видит, что окно исчезает. С ошибкой, что она не добавляет ее обратно при создании нового окна. Избегайте ошибок, устанавливая свойство только в конструкторе, код, который запускается до вызова CreateWindowEx(), а не в обработчиках событий.

В общем, избегайте использования OpenForms из-за этой ошибки. Дайте классу, которому необходимо отобразить окно сообщения, ссылку на экземпляр формы через его конструктор. MessageBox обычно сам определяет родительское окно правильно btw, он выберет активное окно и вернет 99% времени. Если вам нужно вызвать BeginInvoke() из рабочего потока, обязательно скопируйте SynchronizationContext.Current в свой конструктор и вызовите его метод Post() позже. Обеспечивает, чтобы ваша библиотека также работала с другими библиотеками классов GUI.

Ответ 2

Я получил проблему, когда я использовал ShowInTaskBar = true. Я решил это, используя Windows API вместо .Net свойств. Приложение. Открытые формы остались нетронутыми.

Я не знаю, работает ли он как обходной путь, используя SetWindowLong для изменения свойств, но он работает для ShowInTaskBar = true.

 public static class ShowInTaskBar {

    [DllImport("User32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    [DllImport("User32.dll")]
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    private const int SW_HIDE = 0x00;
    private const int SW_SHOW = 0x05;

    private const int WS_EX_APPWINDOW = 0x40000;
    private const int GWL_EXSTYLE = -0x14;

    public static void ShowWindowInTaskbar(IntPtr pMainWindow) {
        SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow, GWL_EXSTYLE) | WS_EX_APPWINDOW);

        ShowWindow(pMainWindow, SW_HIDE);
        ShowWindow(pMainWindow, SW_SHOW);
    }

    public static void HideWindowFromTaskbar(IntPtr pMainWindow) {
        SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow, GWL_EXSTYLE) & ~WS_EX_APPWINDOW);

        ShowWindow(pMainWindow, SW_HIDE);
        ShowWindow(pMainWindow, SW_SHOW);
    }
}