Как определить, работает ли Windows 10 в режиме планшета с Delphi? - PullRequest
1 голос
/ 27 мая 2019

Как кто-то может определить, когда пользователь входит в режим планшета на устройстве Windows 10 с кодом Delphi?

Может кто-нибудь показать пример кода для этого?

Я не хочу определять, есть ли у пользователя планшет или нет. Я просто хочу посмотреть, в режиме планшета они или нет. Каков наилучший способ сделать это?

Ответы [ 2 ]

1 голос
/ 28 мая 2019

Вы можете использовать API UIViewSettings.UserInteractionMode.Пожалуйста, обратитесь к блогу @ Raymond: «Как я могу определить, находится ли мой компьютер в режиме планшета?» , есть способы использования UWP и рабочего стола в C ++.

Более подробная информацияВы можете проверить эту ветку .

Но вам нужно узнать, как это сделать в Delphi.Есть некоторые связанные с этим проблемы, которые, надеюсь, будут вам полезны:

delphi - вызов внешней функции WinAPI

Можем ли мы вызывать Native Windows API из Delphi?

1 голос
/ 27 мая 2019

Я удалил предыдущий вариант (на основе [SO]: как я могу определить, когда Windows 10 входит в режим планшета в приложении Windows Forms? (Ответ @ CheeseLover) (на что указывает комментарий @ Remko) ) потому что это совершенно другой сценарий (не имеет ничего общего с Win на настольном компьютере).

Я потратил некоторое время на [MS.DevBlogs]: Raymond - Как я могу определить, находится ли мой компьютер в режиме планшета? (указано в ответе @ RitaHan-MSFT (+1)), и ясно, это путь .

Я не знаю, как "перевести" код в Delphi , так как прошло много лет с тех пор, как я написал в нем значительное количество кода (но я уверен, что это возможно), поэтому я сделал следующая лучшая вещь: написал C ++ .dll (содержащий измененную / улучшенную версию кода Рэймонда), который вызывается из Delphi .

Примечание : VStudio требуется для сборки .dll , я использовал 2015 Community Edition , которая бесплатна и может быть загружена с [VStudio]: Visual 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 с Режим планшета (левая сторона). Обратите внимание, что мне пришлось скопировать:
    • App0.exe
    • TabletUtils.dll

Img0

...