Как я могу обнаружить, когда Window 10 переходит в режим планшета в приложении Windows Forms?

Обновление

Хотя это не самое элегантное решение, один из методов, который, кажется, работает, - это посмотреть соответствующее значение реестра. Вот пример использования WMI для этого. Я был бы рад услышать от кого-нибудь, если будет лучшее решение, чем это.

using System;
using System.Management;
using System.Security.Principal;
using System.Windows.Forms;
using Microsoft.Win32;

public partial class MainForm : Form
{
    public MainForm()
    {
        this.InitializeComponent();
        this.UpdateModeFromRegistry();

        var currentUser = WindowsIdentity.GetCurrent();
        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));
            var managementEventWatcher = new ManagementEventWatcher(wqlEventQuery);
            managementEventWatcher.EventArrived += this.ManagementEventWatcher_EventArrived;
            managementEventWatcher.Start();
        }
    }

    private void ManagementEventWatcher_EventArrived(object sender, EventArrivedEventArgs e)
    {
        this.UpdateModeFromRegistry();
    }

    private void UpdateModeFromRegistry()
    {
        var tabletMode = (int)Registry.GetValue("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ImmersiveShell", "TabletMode", 0);
        if (tabletMode == 1)
        {
            Console.Write(@"Tablet mode is enabled");
        }
        else
        {
            Console.Write(@"Tablet mode is disabled");
        }
    }
}

Оригинальный вопрос

Мне интересно сделать некоторые оптимизации в моем приложении Windows Forms на основе того, находится ли пользователь в режиме "Tablet Mode" (или нет) с помощью новой функции Windows 10. Continuum.

Есть несколько рекомендаций относительно того, как это сделать в проекте UWP в https://msdn.microsoft.com/en-us/library/windows/hardware/dn917883(v=vs.85).aspx (т.е. проверьте текущий вид UserInteractionMode, чтобы узнать, UserInteractionMode.Mouse или UserInteractionMode.Touch), однако я не уверен, что и как я могу сделать то же самое в Windows Forms.

Можно ли каким-либо образом вызывать необходимые API UWP из моего приложения Windows Forms или есть ли эквивалент Windows Forms, который я могу использовать?

Ответ 1

Чтобы узнать, работает ли система в режиме планшета или нет, запросите метрику системы ConvertibleSlateMode так (не тестировалось, но она должна работать нормально еще в XP):

public static class TabletPCSupport
{
   private static readonly int SM_CONVERTIBLESLATEMODE = 0x2003;
   private static readonly int SM_TABLETPC = 0x56;

   private Boolean isTabletPC = false;

   public Boolean SupportsTabletMode { get { return isTabletPC; }}

   public Boolean IsTabletMode 
   {
       get
       {
           return QueryTabletMode();
       }
   }

   static TabletPCSupport ()
   {
        isTabletPC = (GetSystemMetrics(SM_TABLETPC) != 0);
   }

   [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto, EntryPoint = "GetSystemMetrics")]
   private static extern int GetSystemMetrics (int nIndex);

   private static Boolean QueryTabletMode ()
   {
       int state = GetSystemMetrics(SM_CONVERTIBLESLATEMODE);
       return (state == 0) && isTabletPC;
   }
}

(Документация здесь)

Ответ 2

Я повсюду посмотрел, как узнать, находится ли Windows 10 в режиме планшета, и вот самое простое решение, которое я нашел:

bool bIsTabletMode = false;

var uiMode = UIViewSettings.GetForCurrentView().UserInteractionMode;

if (uiMode == Windows.UI.ViewManagement.UserInteractionMode.Touch)

 bIsTabletMode = true;

else

 bIsTabletMode = false;


// (Could also compare with .Mouse instead of .Touch)

Ответ 3

Согласно в этой статье, вы не можете слушать сообщение WM_SETTINGCHANGE. Вот короткий пример С#:

protected override void WndProc(ref Message m)
        {

            const int WM_WININICHANGE = 0x001A,
                WM_SETTINGCHANGE = WM_WININICHANGE;

            if (m.Msg == WM_SETTINGCHANGE)
            {
                if (Marshal.PtrToStringUni(m.LParam) == "UserInteractionMode")
                {
                    MessageBox.Show(Environment.OSVersion.VersionString);
                }
            }

            base.WndProc(ref m);
        }

Для Windows 10 вы должны выполнить некоторую COM-сопряжение с некоторыми материалами WinRT, чтобы проверить, находитесь ли вы в UserInteractionMode.Mouse(рабочий стол) или UserInteractionMode.Touch(планшет).

Компонент Com Interop выглядит довольно сложно, но, похоже, это единственный способ, если вы находитесь в приложении win32 для акций.