| File: System\Windows\Forms\Application.ThreadWindows.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms\System.Windows.Forms.csproj (System.Windows.Forms) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace System.Windows.Forms; public sealed partial class Application { /// <summary> /// This class enables or disables all windows in the current thread. We use this to disable other windows on the /// thread when a modal dialog is to be shown. It can also be used to dispose all windows in a thread, which we do /// before returning from a message loop. /// </summary> private sealed class ThreadWindows { private readonly List<HWND> _windows; private HWND _activeHwnd; private HWND _focusedHwnd; internal ThreadWindows? _previousThreadWindows; private readonly bool _onlyWinForms = true; internal ThreadWindows(bool onlyWinForms) { _windows = new List<HWND>(16); _onlyWinForms = onlyWinForms; PInvokeCore.EnumCurrentThreadWindows(Callback); } private BOOL Callback(HWND hwnd) { // We only do visible and enabled windows. Also, we only do top level windows. // Finally, we only include windows that are DNA windows, since other MSO components // will be responsible for disabling their own windows. if (PInvoke.IsWindowVisible(hwnd) && PInvoke.IsWindowEnabled(hwnd)) { if (!_onlyWinForms || Control.FromHandle(hwnd) is not null) { _windows.Add(hwnd); } } return true; } // Disposes all top-level Controls on this thread internal void Dispose() { foreach (HWND hwnd in _windows) { if (PInvoke.IsWindow(hwnd)) { Control.FromHandle(hwnd)?.Dispose(); } } } // Enables/disables all top-level Controls on this thread internal void Enable(bool enable) { if (!_onlyWinForms && !enable) { _activeHwnd = PInvoke.GetActiveWindow(); Control? activatingControl = ThreadContext.FromCurrent().ActivatingControl; _focusedHwnd = activatingControl is not null ? activatingControl.HWND : PInvoke.GetFocus(); } foreach (HWND hwnd in _windows) { if (PInvoke.IsWindow(hwnd)) { PInvoke.EnableWindow(hwnd, enable); } } // OpenFileDialog is not returning the focus the way other dialogs do. // Important that we re-activate the old window when we are closing // our modal dialog. // // edit mode forever with Excel application // But, DON'T change other people's state when we're simply // responding to external MSOCM events about modality. When we are, // we are created with a TRUE for onlyWinForms. if (!_onlyWinForms && enable) { if (!_activeHwnd.IsNull && PInvoke.IsWindow(_activeHwnd)) { PInvoke.SetActiveWindow(_activeHwnd); } if (!_focusedHwnd.IsNull && PInvoke.IsWindow(_focusedHwnd)) { PInvoke.SetFocus(_focusedHwnd); } } } } }