Приложение для планшета, функция автоматического поворота и высота панели задач - PullRequest
0 голосов
/ 29 августа 2018

Самостоятельно отвечу и надеюсь помочь другим тоже работать с планшетными устройствами в Windows.

  1. Я в режиме планшета или нет.

  2. Блокировка ориентации. В моем случае в планшет встроен сканер, который находится в той же плоскости, что и горизонтальный режим планшета. Мы не хотели, чтобы пользователи продолжали переворачивать экран, когда они могут перемещаться между местоположениями и сканированием.

  3. Эта классная виртуальная клавиатура. По-видимому, виртуальную клавиатуру можно закрепить в области панели задач и, таким образом, изменить видимое пространство основных связанных с Windows измерений для ваших экранов. Затем виртуальная клавиатура исчезает, а размеры, связанные с Windows, снова изменяются.

Чтобы разрешить поворот планшета, я благодарен Как заблокировать поворот экрана планшета в приложении UWP? здесь, на S / O.

Ниже приведены критические фрагменты процесса. Надеюсь, что это поможет окружающим найти себе подобную информацию для нужд своего развития.

public class MyWindow : Window
{
    public MyWindow()
    {
        DetectForTabletMode();

        // Turn OFF auto-rotation for duration of my primary application window
        MyUser32.SetAutoRotation(false);

        // Hooks for detecting screen bounds / taskbar height impact to form
        // the "SystemEvents" is a static instance and always available.  I have added
        // so each window can adjust itself as needed.  I have actually hooked into
        // both User preferences and Display Settings
        SystemEvents.UserPreferenceChanged += MyWindow_DisplaySettingsChanged;
        SystemEvents.DisplaySettingsChanged += MyWindow_DisplaySettingsChanged;

        // hook to closed event so I can clean up when window is finished
        Closed += MyWindow_Closed;
    }

    private void MyWindow_Closed(object sender, EventArgs e)
    {
        // Disconnect event handler for detecting when in/out of tablet mode
        if(_tabletWatch != null )
        {
            _tabletWatch.EventArrived -= tabletWatch_EventArrived;
            _tabletWatch.Stop();
        }

        // When closing my main window, re-enable the auto-rotation
        MyUser32.SetAutoRotation(true);

        // Disable screen resolution impact to prevent memory leaks 
        // must release on closing window or memory leaks per MS documentation
        // https://docs.microsoft.com/en-us/dotnet/api/microsoft.win32.systemevents.displaysettingschanged?view=netframework-4.7.2
        SystemEvents.UserPreferenceChanged -= MyWindow_DisplaySettingsChanged;
        SystemEvents.DisplaySettingsChanged -= MyWindow_DisplaySettingsChanged;


        // under your control, probably only want to turn back on at the END of the APPLICATION
        // and not just all windows individually
        MyUser32.SetAutoRotation(true);

    }

    #region Detect / Set / Handle tablet mode

    private bool _inTabletMode;
    public bool InTabletMode
    {
        get { return _inTabletMode; }
        private set
        {
            _inTabletMode = value;
            // do anything you want when changing in/out of tablet mode
        }
    }

    private ManagementEventWatcher _tabletWatch;


    private void DetectForTabletMode()
    {
        var currentUser = WindowsIdentity.GetCurrent();
        // to capture event when user swaps between normal and tablet modes.
        if (currentUser != null && currentUser.User != null)
        {
            var wqlEventQuery = new EventQuery( string.Format(
                @"SELECT * 
                    FROM 
                        RegistryValueChangeEvent 
                    WHERE 
                            Hive='HKEY_USERS' 
                        AND KeyPath='{0}\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ImmersiveShell' 
                        AND ValueName='TabletMode'", currentUser.User.Value ));

            _tabletWatch = new ManagementEventWatcher(wqlEventQuery);
            _tabletWatch.EventArrived += tabletWatch_EventArrived;
            _tabletWatch.Start();
        }
    }

    private void tabletWatch_EventArrived(object sender, EventArrivedEventArgs e)
    {
        Dispatcher.Invoke(() =>
        {
            InTabletMode = 1 == (int)Registry.GetValue("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ImmersiveShell", "TabletMode", 0);
        });
    }

    #endregion Detect / Set / Handle tablet mode

    #region Display and Orientation settings
    private System.Drawing.Rectangle _lastDimensions;

    // typical mode is landscape such as desktop / notbook mode anyhow.
    private bool _isLandscapeMode = true;   
    public bool IsLandscapeMode { get { return _isLandscapeMode; } }

    private bool _isPortraitMode { get { return !_isLandscapeMode; } }
    public bool IsPortraitMode { get { return _isPortraitMode; } }


    private void MyWindow_DisplaySettingsChanged(object sender, EventArgs e)
    {
        // get WINDOWS primary screen boundary dimensions
        var psb = System.Windows.Forms.Screen.PrimaryScreen.Bounds;

        // only if coming in and different than a previous setting
        if (_lastDimensions != null)
        {
            // Compare height and width of screen and act accordingly for orientation
            _isLandscapeMode = (psb.Height < psb.Width);

            // did dimensions change, such as from height of taskbar area shrinking
            // available real estate for YOUR Window.
            if (_lastDimensions.Height == psb.Height
                && _lastDimensions.Width == psb.Width)
                // same dimensions, get out, nothing more to do...
                return;

            // allow virtual method per form to handle itself as needed
            // and pass in the new dimensions.
            WinDimensionsChanged(psb);
        }
        // always preserve latest dimensions IN-CASE changes, such as taskbar, etc..
        _lastDimensions = psb;
    }

    protected virtual void WinDimensionsChanged(System.Drawing.Rectangle newestDimensions)
    {
        // do whatever you want per child-declared window

    }

    #endregion Display and Orientation settings

}
...