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

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

17 голосов
/ 20 сентября 2010

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

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

Ответы [ 2 ]

39 голосов
/ 20 сентября 2010

В 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 (), чтобы изменение вступило в силу, передавая различные флаги стиля.У уничтожения исходного окна сначала есть побочные эффекты, помимо очень заметного мерцания, одним из них является то, что класс Application теряет форму, так как видит, что окно исчезает.С ошибкой, что он не добавляет его обратно при создании нового окна.Избегайте ошибок, устанавливая свойство только в конструкторе, код, который выполняется до вызова CreateWindowEx (), а не в каких-либо обработчиках событий.

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

1 голос
/ 29 апреля 2013

Я получил проблему, когда использовал 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...