Вызов формы showdialog не является модальным

У меня есть 2 формы, 1 MainForm и 1 Form2. Я пытаюсь отобразить Form2 как модальную форму и фон из MainForm. Вот что у меня есть до сих пор.

Появится основная форма по умолчанию, и через 5 секунд она покажет Form2 как модальную форму из фонового потока. Я закрываю Form2, и если та же форма Form2 появляется снова с помощью ShowDialog, форма не является модальной. Как сделать так, чтобы отображаемая форма Form2 всегда была модальной?

Public Class MainForm
    Dim frm2 As Form2
    Private Sub MainForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        frm2 = New Form2()
        Dim frmHandle As IntPtr = frm2.Handle
        frm2.Button1.Text = "test"

        System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf DoSomething), 0)
    End Sub

    Private Sub DoSomething()

        'call show dialog first time
        Threading.Thread.Sleep(5000)
        If frm2.InvokeRequired Then
            frm2.Invoke(New Action(AddressOf frm2.ShowDialog))
        Else
            frm2.ShowDialog()
        End If

        'call show dialog second time
        If frm2.InvokeRequired Then
            frm2.Invoke(New Action(AddressOf frm2.ShowDialog))
        Else
            frm2.ShowDialog()
        End If

    End Sub
End Class

person user1670418    schedule 16.06.2015    source источник
comment
Доступ к frm2.Handle в обработчике событий Load был случайным хаком, чтобы заставить его работать с первого раза. Второй раз не получится. Просто не используйте хак, чтобы заставить этот код работать, вместо этого вы можете просто использовать Me.Invoke().   -  person Hans Passant    schedule 16.06.2015


Ответы (1)


в showDialog вы можете установить родительскую форму, которая сделает дочернюю форму модальной:

Public Class MainForm
Dim frm2 As Form2
Private Sub MainForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    frm2 = New Form2()
    Dim frmHandle As IntPtr = frm2.Handle
    frm2.Button1.Text = "test"

    System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf DoSomething), 0)
End Sub

Private Sub DoSomething()
    Dim myAction as Action(Of System.Windows.Forms.IWin32Window)

    'call show dialog first time
    Threading.Thread.Sleep(5000)
    If Me.InvokeRequired Then
        myAction = AddressOf frm2.ShowDialog
        Me.Invoke(myAction(Me))
    Else
        frm2.ShowDialog(Me)
    End If

    'call show dialog second time
    If Me.InvokeRequired Then
        myAction = AddressOf frm2.ShowDialog
        Me.Invoke(myAction(Me))
    Else
        frm2.ShowDialog(Me)
    End If

End Sub
End Class

Вы можете сократить код, используя:

New Action(Of System.Windows.Forms.IWin32Window)(AddressOf frm2.ShowDialog), Me)
person Keith Mifsud    schedule 16.06.2015
comment
Последний frm2.ShowDialog(Me) возвращает ошибку. Недопустимая межпоточная операция: доступ к элементу управления «MainForm» осуществляется из потока, отличного от потока, в котором он был создан. - person user1670418; 16.06.2015
comment
на последнем frm2.InvokeRequired он возвращает true? - person Keith Mifsud; 16.06.2015
comment
Последний frm2.InvokeRequired возвращает false. - person user1670418; 16.06.2015
comment
есть ли код между двумя вызовами? (между ShowDialogs) В основном вам нужно frm2.InvokeRequired вернуть true, и это происходит только в том случае, если дескриптор элемента управления был создан в потоке, отличном от вызывающего потока (указывая, что вы должны выполнять вызовы элемента управления через метод вызова); в противном случае ложно. - person Keith Mifsud; 16.06.2015
comment
Между двумя ShowDialogs нет кода. Код, который я предоставил, это именно то, что я скомпилировал. Первый результат InvokeRequired — true, однако второй результат InvokeRequired — false. Как я могу заставить InvokeRequired возвращать true для второго вызова? - person user1670418; 16.06.2015
comment
Хорошо, я читал об этой проблеме и, по-видимому, когда диалоговое окно модели закрывается, дескриптор теряется, поэтому InvokeRequired возвращает false. Альтернативой является использование Me.InvokeRequired - person Keith Mifsud; 16.06.2015
comment
Для второго диалога Invoke или BeginInvoke нельзя вызвать для элемента управления, пока не будет создан дескриптор окна. - person user1670418; 17.06.2015