2

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

有人可以为此显示一个代码示例吗?

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

4

2 回答 2

1

我删除了以前的变体(基于[SO]:如何检测 Windows 10 何时在 Windows 窗体应用程序中进入平板电脑模式?(@CheeseLover 的回答)(由@Remko 的评论指出))因为它是一个完全不同的场景(doesn与在桌面上运行的Win没有任何关系)。

我在 [MS.DevBlogs] 上花了一些时间: Raymond - 如何检测我的 PC 是否处于平板电脑模式?(在@RitaHan-MSFT 的回答 (+1) 中指出),显然,这是要走的路

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

注意:构建.dll需要VStudio,我使用的是2015社区,它是免费的,可以从[VStudio]:Vi​​sual Studio 2015 和其他产品下载(不过你需要一个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上(左侧)。请注意,我必须复制:
    • 应用0.exe
    • TabletUtils.dll

图像0

于 2019-05-27T15:58:14.243 回答
1

您可以使用 UIViewSettings.UserInteractionMode API。请参考@Raymond 博客:“如何检测我的 PC 是否处于平板模式?” ,C++中有UWP和桌面方式可以参考。

更详细的信息你可以查看这个线程

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

delphi - 调用外部 WinAPI 函数

我们可以从 Delphi 调用 Native Windows API 吗?

于 2019-05-28T01:28:43.580 回答