Задать вопрос
Ответы пользователя по тегу Windows
  • Как поизящнее отключить предварительную обработку касаний сенсорного экрана в Windows 8?

    blackstrip
    @blackstrip Автор вопроса
    Кому интересен ответ на этот вопрос или кто наткнется на этот пост в интернете - вот как отключить:

    Для каждого компонента, с которого хотим убрать "сенсорный слой", чтобы стилус/палец мгновенно нажимал на компонент при нажатии и отпускал его при отпускании пальца без задержек, правого клика по долгому нажатию и т.д.:

    1) Вызываем RegisterTouchWindow из user32.dll с двумя параметрами: HWND компонента и флаг TWF_WANTPALM (флаг говорит винде не расчитывать положение нажатия по всей ладони прижатой, а быстро взять первое касание до сенсора, чтоб не тратить время на распознавание средних координат нажатия "ладонью" на экран).

    RegisterTouchWindow(Form1.Handle,TWF_WANTPALM);

    Если хочется для TImage убрать сенсорный слой - то надо указать HWND родительского компонента, на котором лежит TImage.

    Если у вас прога на разные версии Windows, в том числе на XP и более ранние (где этой функции не было), то можно обойти это дело так:

    type TRTW = function(hwnd: HWND; ulFlags: Cardinal): BOOL; stdcall;
    type UTRTW = function(hwnd: HWND): BOOL; stdcall;
    
    const
    TWF_WANTPALM = $00000002;
    
    var
    touchinited:boolean=false;
    HLib:THandle;
    tou:TRTW;
    utou:UTRTW;
    
    procedure TForm1.InitTouch();
    begin
    try
    Hlib:=LoadLibrary('USER32.DLL');
    if HLib>HINSTANCE_ERROR then
    begin
    tou:=GetProcAddress(Hlib,'RegisterTouchWindow');
    utou:=GetProcAddress(Hlib,'UnregisterTouchWindow');
    if Assigned(tou) and Assigned(utou) then touchinited:=true;
    end;
    except
    if HLib>HINSTANCE_ERROR then FreeLibrary(HLib);
    touchinited:=false;
    end;
    end;


    И тогда вызов регистрации будет выглядеть как:

    if touchinited then tou(Form1.Handle,TWF_WANTPALM);


    2. После регистрации компонента как тач-компонент - вызвать эту процедуру, передав ей HWND компонента (она работает в любом Windows, даже в Windows 95, но без предыдущего шага с RegisterTouchWindows - она толком не подействует ни в Windows 8, ни в Windows 10):

    procedure TForm1.DisablePressAndHold(handa:HWND);
    var
      Atom :TAtom;
    const
      tabletAtom = 'MicrosoftTabletPenServiceProperty';
      TABLET_DISABLE_PRESSANDHOLD = $00000001;
      TABLET_DISABLE_PENTAPFEEDBACK      =$00000008;
      TABLET_DISABLE_PENBARRELFEEDBACK   =$00000010;
      TABLET_DISABLE_FLICKS              =$00010000;
      TABLET_DISABLE_TOUCHUIFORCEON      =$00000100;
      TABLET_DISABLE_TOUCHUIFORCEOFF     =$00000200;
      TABLET_DISABLE_TOUCHSWITCH         =$00008000;
      TABLET_ENABLE_FLICKSONCONTEXT      =$00020000;
      TABLET_ENABLE_FLICKLEARNINGMODE    =$00040000;
      TABLET_DISABLE_SMOOTHSCROLLING     =$00080000;
      TABLET_DISABLE_FLICKFALLBACKKEYS   =$00100000;
      TABLET_ENABLE_MULTITOUCHDATA       =$01000000;
      TABLET_ALL = TABLET_DISABLE_PRESSANDHOLD or TABLET_DISABLE_PENTAPFEEDBACK or TABLET_DISABLE_PENBARRELFEEDBACK or TABLET_DISABLE_FLICKS or TABLET_DISABLE_TOUCHSWITCH or TABLET_DISABLE_SMOOTHSCROLLING or TABLET_DISABLE_FLICKFALLBACKKEYS or TABLET_DISABLE_TOUCHUIFORCEON or TABLET_DISABLE_TOUCHUIFORCEOFF;
    begin
      Atom := GlobalAddAtom(tabletAtom);
      if Atom <> 0 then
      begin
        SetProp(handa, tabletAtom, TABLET_ALL);
      GlobalDeleteAtom(Atom);
      end;
    end;


    3. Перед закрытием программы - надо обратно "разрегистрировать" тач-компоненты примерно так:

    UnregisterTouchWindow(Form1.Handle);

    или для случае динамической подгрузки библиотеки:

    if touchinited then utou(Form1.Handle);

    А потом отпустить библиотеку (хотя, по идее, user32.dll так и останется в памяти, т.к. весьма вероятно задействована другими прогами/библиотеками):

    procedure TForm1.FreeTouch();
    begin
    if HLib>HINSTANCE_ERROR then FreeLibrary(HLib);
    end;


    И тогда все зарегенные и обвешанные тач-свойствами компоненты будут резво реагировать на палец/стилус, мгновенно нажиматься, при удерживании - держать как положено мышку в нажатом состоянии левой кнопки, при отпускании - отпускать.

    Все компоненты, которые не обвесили - будут работать как раньше (с правым кликом по долгому удерживанию и т.п.). На дочерние компоненты эта фича не распространяется (нельзя на окошко кинуть такую штуку и все его компоненты чтоб автоматически тоже стали такими с простыми нажатиями стилусом). Поэтому ручками кидаем RegisterTouchWindow и потом DisablePressAndHold на каждый отвязываемый от "тач-оверлея" компонент. И вроде бы все работает. Проверено:
    - на ноутбуке с Win8 и резистивным экраном, на котором хоть стилусом, хоть пальцем, хоть зубочисткой деревянной можно нажимать
    - на планшете с Win10 и электронным стилусом а ля wacom, который даже просто вблизи экрана без касания - уже елозит точкой по экрану

    p.s. в инете рассматривают также вариант отслеживания очереди сообщений с выделением тач-сообщений. Можно подойти с того конца с этой проблемы, но мне хватило и с этого (надо было TImage сделать рисуемым стилусом, и еще десяток TPanel сделать нажимаемыми пальцем).
    Ответ написан
    Комментировать