如何使用Delphi检测Windows 10是否处于平板电脑模式?

时间:2019-05-27 07:31:16

标签: delphi winapi windows-10 tablet-pc

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

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

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

2 个答案:

答案 0 :(得分:1)

我删除了先前的变体(基于[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 中调用。 / p>

注意:构建 .dll 需要 VStudio ,我使用的是 2015 Community 版本,它是免费的,可以从[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
  • Tablet模式(左侧)的 Win 10 VM 上。请注意,我必须复制:
    • App0.exe
    • TabletUtils.dll

Img0

答案 1 :(得分: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?