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

aurhwmvo  于 2023-08-04  发布在  Windows
关注(0)|答案(2)|浏览(142)

当用户在使用 Delphi 代码的Windows 10设备上进入平板电脑模式时,人们将如何检测到?
有没有人能给出一个代码示例?
我不想检测用户是否有平板电脑。我只是想看看他们是否在平板电脑模式或没有。最好的办法是什么?

rlcwz9us

rlcwz9us1#

我删除了之前的变体(基于[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 * 调用。

注意.dll 需要 VStudio 来构建,我使用的是 2015CommunityEdition,它是免费的,可以从[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 上,使用 *Tablet模式 *(左侧)。请注意,我不得不复制:
  • App0.exe
  • TabletUtils.dll

x1c 0d1x的数据

oo7oh9g9

oo7oh9g92#

可以使用UIViewSettings.UserInteractionMode API。请参考@Raymond博客:“如何检测我的电脑是否处于平板电脑模式?”,C++中有UWP和桌面方式你可以参考。
更多详细信息,您可以查看this thread
但是你需要了解如何在 Delphi 中做。这里有一些相关的问题希望对你有所帮助:
delphi - call external WinAPI function
Can we call Native Windows API from Delphi?

相关问题