В Windows 10 (да и в восьмёрке, и ранее) нажатия на сенсорный экран обрабатываются в Windows, а потом только передаются окошкам программ. Длительное нажатие и удерживание пальца/стилуса в одном месте экрана, как известно, дает по дефолту короткий "правый клик". При этом о том, что нажали - не сообщается никуда (окошко, над которым это происходит - о нажатии не догадывается), о том что держат - не сообщается никуда, и по прошествии некоторого времени сразу прилетает в прогу "опа, здесь по координатам X:Y произошел короткий правый клик а ля нажатие и через N миллисекунд отпускание". Поэтому нельзя просто взять и сделать такие программы как, например, виртуальное пианино, где при нажатии - прилетит mousedown и клавиша нажмется, при удерживании - она будет нажата (т.к. нажатие было, а отпускания не было), при отпускании - прилетит mouseup и она отпустится. И любые другие проги, где длительное нажатие пальца будет именно честным нажатием и последующим отпусканием. Кто нибудь боролся с этим и как поборол (если поборол)? p.s. поиск в инете по этой проблеме дает в основном "молчание" либо "а зачем тебе нужно длительное нажатие? проектируй прогу так, чтоб там не было такого, а были короткие клики правой и левой кнопкой, а также нажатие с последующим перетягиванием, ибо оно то корректно передается в окно". А так охота пробить этот "сенсорный слой" и получить на окошко события нажатия и отпускания пальца в одном и том же месте окна.
сфера совсем не моя, но вот есть некая структурка https://msdn.microsoft.com/en-us/library/windows/desktop/dd317334(v=vs.85).aspx , которая, судя по всему, как раз подойдет. но хз как работать с ней из допотопной делфи... почему не вариант перейти на более новую версию, в которой по любому есть что-то на этот счет?
Ну та прога, где это нужно, работает в любом Windows от 95 до 10, поэтому и используется Win32 на основе D7 =) Мне б команду "эй винда, вот это окно отключи от своего тач-интерфейса и распознавай нажатие на тачскрин как нажатие левой кнопки, а отпускание тач скрина как отпускание левой кнопки". В идеале. А мурыжить очередь сообщений от тача - можно конечно (если удастся из д7 изловить это дело и при этом спокойно работать и в каком нибудь вин98, не дергая запросы всяких вещей, которые еще не существовали в то время), но неужели не предусмотрели простого программного отрубания всей этой пальце-жесто-обрабатывающей лабуды...
хз, но сомневаюсь нельзя разнести прогу на логику в dll'ке и два интерфейса: один на d7 под 9х/ХР, а второй на более новой под Win7+? имхо так проще получится хотя я не шарю, мож херню написал
ну я и в экзешнике подобное сделать могу через loadlibrary с обработкой для старых виндов ситуации отсутствия библиотеки/ф-ции в библиотеке (вроде бы). и, кстати, нашел msdn статью для XP Tablet PC под отключению правого клика долгим нажатием: https://msdn.microsoft.com/en-us/library/ms812373.aspx Если в восьмерке-десятке работать будет способ по тамошнему vbшному примеру, то и проблема решена тогда, кажись, будет..
Не все оказалось так просто. Кому будет интересно - делать надо так: Для каждого компонента, с которого хотим убрать "сенсорный слой", чтобы стилус/палец мгновенно нажимал на компонент при нажатии и отпускал его при отпускании пальца без задержек, правого клика по долгому нажатию и т.д.: 1) Вызываем RegisterTouchWindow из user32.dll с двумя параметрами: HWND компонента и флаг TWF_WANTPALM (флаг говорит винде не расчитывать положение нажатия по всей ладони прижатой, а быстро взять первое касание до сенсора, чтоб не тратить время на распознавание средних координат нажатия "ладонью" на экран). Code: RegisterTouchWindow(Form1.Handle,TWF_WANTPALM); Если хочется для TImage убрать сенсорный слой - то надо указать HWND родительского компонента, на котором лежит TImage. Если у вас прога на разные версии Windows, в том числе на XP и более ранние (где этой функции не было), то можно обойти это дело так: Code: 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; И тогда вызов регистрации будет выглядеть как: Code: if touchinited then tou(Form1.Handle,TWF_WANTPALM); 2. После регистрации компонента как тач-компонент - вызвать эту процедуру, передав ей HWND компонента (она работает в любом Windows, даже в Windows 95, но без предыдущего шага с RegisterTouchWindows - она толком не подействует ни в Windows 8, ни в Windows 10): Code: 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. Перед закрытием программы - надо обратно "разрегистрировать" тач-компоненты примерно так: Code: UnregisterTouchWindow(Form1.Handle); или для случае динамической подгрузки библиотеки: Code: if touchinited then utou(Form1.Handle); А потом отпустить библиотеку (хотя, по идее, user32.dll так и останется в памяти, т.к. весьма вероятно задействована другими прогами/библиотеками): Code: procedure TForm1.FreeTouch(); begin if HLib>HINSTANCE_ERROR then FreeLibrary(HLib); end; И тогда все зарегенные и обвешанные тач-свойствами компоненты будут резво реагировать на палец/стилус, мгновенно нажиматься, при удерживании - держать как положено мышку в нажатом состоянии левой кнопки, при отпускании - отпускать. Все компоненты, которые не обвесили - будут работать как раньше (с правым кликом по долгому удерживанию и т.п.). На дочерние компоненты эта фича не распространяется (нельзя на окошко кинуть такую штуку и все его компоненты чтоб автоматически тоже стали такими с простыми нажатиями стилусом). Поэтому ручками кидаем RegisterTouchWindow и потом DisablePressAndHold на каждый отвязываемый от "тач-оверлея" компонент. И вроде бы все работает. Проверено: - на ноутбуке с Win8 и резистивным экраном, на котором хоть стилусом, хоть пальцем, хоть зубочисткой деревянной можно нажимать - на планшете с Win10 и электронным стилусом а ля wacom, который даже просто вблизи экрана без касания - уже елозит точкой по экрану p.s. в инете рассматривают также вариант отслеживания очереди сообщений с выделением тач-сообщений. Можно подойти с того конца с этой проблемы, но мне хватило и с этого (надо было TImage сделать рисуемым стилусом, и еще десяток TPanel сделать нажимаемыми пальцем).
"нельзя на окошко кинуть такую штуку и все его компоненты чтоб автоматически тоже стали такими с простыми нажатиями стилусом" - EnumChildWindows?
Ну, конечно, вручную получить дочерние и перебрать можно. А"автоматически" имелись ввиду ожидания "вот укажу окошко, и все его дочерние автоматом получат это", эти ожидания не оправдались) Только "вручную", в цикле ли через enum, совсем вручную на каждый компонент ли.