【问题标题】:How to detect if Windows 10 is in tablet mode with Delphi?如何使用 Delphi 检测 Windows 10 是否处于平板电脑模式?
【发布时间】:2019-05-27 07:31:16
【问题描述】:

当用户在带有 Delphi 代码的 Windows 10 设备上进入平板电脑模式时,有人会如何检测?

有人可以展示一个代码示例吗?

我不想检测用户是否有平板电脑。我只是想看看他们是否处于平板电脑模式。最好的方法是什么?

【问题讨论】:

  • 可能重复(不是 Delphi,而是同一个问题):stackoverflow.com/questions/31153664/…
  • @Remko 我看过这个问题,但我的问题是 Delphi 特有的。
  • 答案适用于Delphi,有时你必须去原生。

标签: delphi winapi windows-10 tablet-pc


【解决方案1】:

您可以使用 UIViewSettings.UserInteractionMode API。请参考@Raymond blog: "How can I detect whether my PC is in tablet mode?",C++中有UWP和桌面方式可以参考。

更多详细信息可以查看this thread

但是您需要了解如何在 Delphi 中进行操作。有一些相关的问题希望对你有帮助:

delphi - call external WinAPI function

Can we call Native Windows API from Delphi?

【讨论】:

    【解决方案2】:

    我删除了之前的变体(基于[SO]: How can I detect when Windows 10 enters tablet mode in a Windows Forms application? (@CheeseLover's answer)(@Remko 的评论指出))因为这是一个完全不同的场景(与桌面上运行的 Win 没有任何关系) .

    我在[MS.DevBlogs]: Raymond - How can I detect whether my PC is in tablet mode? 上花了一些时间(在@RitaHan-MSFT 的回答 (+1) 中指出),很明显,这就是要走的路

    我不知道如何将代码“翻译”成 Delphi,因为我已经在其中编写了大量代码(但我确信这是可能的)已经过去了很多年,所以我做了下一个最好的事情:编写了一个 C++ .dll(包含 Raymond 代码的修改/改进版本),从 Delphi 调用。

    注意VStudio是构建.dll所必需的,我用的是2015 社区,它是免费的,可以从[VStudio]: Visual Studio 2015 and other Products 下载(不过你需要一个MS 帐户)。

    dll.cpp

    #include <wrl/client.h>
    #include <windows.ui.viewmanagement.h>
    #include <UIViewSettingsInterop.h>
    #include <wrl/wrappers/corewrappers.h>
    
    
    namespace WRL = Microsoft::WRL;
    namespace VM = ABI::Windows::UI::ViewManagement;
    
    
    class Backend {
    public:
        static Backend &instance() {
            static Backend m_instance;
            return m_instance;
        }
    
        WRL::ComPtr<IUIViewSettingsInterop> interop() { return m_interop; }
    
    private:
        Backend() {
            HRESULT res = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
            m_comInit = (res == S_OK) || (res == S_FALSE);
            if (m_comInit || (res == RPC_E_CHANGED_MODE)) {
                res = Windows::Foundation::GetActivationFactory(WRL::Wrappers::HStringReference(
                    RuntimeClass_Windows_UI_ViewManagement_UIViewSettings).Get(), &m_interop);
            }
        }
    
        Backend(const Backend &other) = delete;
        Backend &operator =(const Backend &other) = delete;
    
        ~Backend() {
            if (m_interop) { m_interop.Reset(); }
            if (m_comInit) { CoUninitialize(); }
        }
    
        bool m_comInit = false;
        WRL::ComPtr<IUIViewSettingsInterop> m_interop = nullptr;
    };
    
    
    /*!
        Gets Tablet mode value.
        \param hwnd Window handle to get the mode for
        \returns:
             1 - Tablet mode ON
             0 - Tablet mode OFF
            -X - Error
    */
    extern "C" __declspec(dllexport) int GetTabletMode(HWND hwnd) {
        WRL::ComPtr<IUIViewSettingsInterop> interop = Backend::instance().interop();
        if (!interop) { return -3; }
    
        WRL::ComPtr<VM::IUIViewSettings> viewSettings;
        HRESULT res = interop->GetForWindow(hwnd != NULL ? hwnd : GetConsoleWindow(), IID_PPV_ARGS(&viewSettings));
        if (!viewSettings) { return -2; }
    
        VM::UserInteractionMode currentMode;
        res = viewSettings->get_UserInteractionMode(&currentMode);
    
        int ret = -1;
        switch (currentMode) {
            case VM::UserInteractionMode_Mouse: ret = 0; break;
            case VM::UserInteractionMode_Touch: ret = 1; break;
            default: ret = -1;
        }
    
        viewSettings.Reset();
        return ret;
    }
    

    下面是Delphi的相关代码(只有单元,因为其他的很容易制造,这里没有意义)。

    Unit0.pas

    unit Unit0;
    
    interface
    
    uses
        Forms, Dialogs, Controls, StdCtrls, Classes;
    
    
    type
        TForm0 = class(TForm)
        CheckButton: TButton;
            procedure CheckButtonClick(Sender: TObject);
        private
            { Private declarations }
        public
            { Public declarations }
    end;
    
    var
        Form0: TForm0;
    
    
        function GetTabletMode(hwnd: THandle): Integer cdecl; external 'TabletUtils.dll';
    
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm0.CheckButtonClick(Sender: TObject);
    var
        TabletModeStr: String;
    begin
        case GetTabletMode(Self.Handle) of
            0 : TabletModeStr := 'OFF';
            1 : TabletModeStr := 'ON';
            else TabletModeStr := 'ERROR';
        end;
        MessageDlg('Tablet Mode: ' + TabletModeStr, mtInformation, [mbOK], 0);
    end;
    
    end.
    

    输出

    [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q056321591]> sopr.bat
    *** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***
    
    [prompt]> "c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" x86
    
    [prompt]> dir /b
    App0.cfg
    App0.dof
    App0.dpr
    App0.exe
    App0.res
    dll.cpp
    other
    Unit0.dcu
    Unit0.ddp
    Unit0.dfm
    Unit0.pas
    
    [prompt]> cl /nologo /DDLL /DNDEBUG /DUSRDLL /D_WINDOWS /MT dll.cpp  /link /NOLOGO /DLL /OUT:TabletUtils.dll ole32.lib runtimeobject.lib
    dll.cpp
       Creating library TabletUtils.lib and object TabletUtils.exp
    
    [prompt]> dir /b
    App0.cfg
    App0.dof
    App0.dpr
    App0.exe
    App0.res
    dll.cpp
    dll.obj
    other
    TabletUtils.dll
    TabletUtils.exp
    TabletUtils.lib
    Unit0.dcu
    Unit0.ddp
    Unit0.dfm
    Unit0.pas
    
    [prompt]> App0.exe
    
    [prompt]>
    

    在下面的屏幕截图中,我运行了应用程序:

    • 在我的笔记本电脑 (Win 10) 上使用 桌面模式(右侧)
    • Win 10 VM 上使用 平板电脑模式(左侧)。请注意,我必须复制:
      • App0.exe
      • TabletUtils.dll

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-07
      • 2013-10-19
      • 2014-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多