dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.04k stars 1.16k forks source link

WPF touch function does not work. #7069

Open HouZack opened 2 years ago

HouZack commented 2 years ago

https://user-images.githubusercontent.com/113828370/190896784-37151d1a-f6f1-4448-beeb-59d9798ac2bd.mp4

lindexi commented 2 years ago

@HouZack What is your DPI ? Could you change the system DPI to 100%

HouZack commented 2 years ago

@HouZack What is your DPI ? Could you change the system DPI to 100%

My DPI is always 100%.

lindexi commented 2 years ago

@HouZack Do you have two touch screen?

HouZack commented 2 years ago

@HouZack Do you have two touch screen?

Yes, even if I use the second touch screen, the touch still doesn't work. Some of the tests I summarized in the third point above.

lindexi commented 2 years ago

@HouZack The bad news is maybe it is a known issue. See https://github.com/dotnet/wpf/issues/2054

Could you add new WindowInteropHelper(this).EnsureHandle(); before you show the window to test? Thank you

HouZack commented 1 year ago

@HouZack The bad news is maybe it is a known issue. See #2054

Could you add new WindowInteropHelper(this).EnsureHandle(); before you show the window to test? Thank you @lindexi Because I have rebooted computer and need to wait for next time the problem occurs.

HouZack commented 1 year ago

@HouZack The bad news is maybe it is a known issue. See #2054

Could you add new WindowInteropHelper(this).EnsureHandle(); before you show the window to test? Thank you

@lindexi I add new WindowInteropHelper(this).EnsureHandle(); but touch still not work. Thanks. image

lindexi commented 1 year ago

@HouZack Is your Application TopMost ?

See https://developercommunity.visualstudio.com/content/problem/255063/on-windows-10-1803-all-applications-lost-touch-or.html

HouZack commented 1 year ago

@HouZack Is your Application TopMost ?

See https://developercommunity.visualstudio.com/content/problem/255063/on-windows-10-1803-all-applications-lost-touch-or.html

No, I don't set TopMost. And I try to set it to true or false, touch still not work.

lindexi commented 1 year ago

@HouZack Could you try re-start the touch module by the code:

            var windowInteropHelper = new WindowInteropHelper(this);
            var hwndSource = HwndSource.FromHwnd(windowInteropHelper.Handle);

            object stylusLogic = GetStylusLogic();

            if (stylusLogic == null)
            {
                return;
            }

            Type inputManagerType = typeof(System.Windows.Input.InputManager);
            var wispLogicType = inputManagerType.Assembly.GetType("System.Windows.Input.StylusWisp.WispLogic");

            var windowInteropHelper = new WindowInteropHelper(this);
            var hwndSource = HwndSource.FromHwnd(windowInteropHelper.Handle);

            var unRegisterHwndForInputMethodInfo = wispLogicType.GetMethod("UnRegisterHwndForInput",
                BindingFlags.Instance | BindingFlags.NonPublic);

            unRegisterHwndForInputMethodInfo.Invoke(stylusLogic, new object[] {hwndSource});

            var registerHwndForInputMethodInfo = wispLogicType.GetMethod("RegisterHwndForInput",
                BindingFlags.Instance | BindingFlags.NonPublic);

            registerHwndForInputMethodInfo.Invoke(stylusLogic, new object[]
            {
                InputManager.Current,
                PresentationSource.FromVisual(this)
            });

        private object GetStylusLogic()
        {
            TabletDeviceCollection devices = System.Windows.Input.Tablet.TabletDevices;

            if (devices.Count > 0)
            {
                // Get the Type of InputManager.
                Type inputManagerType = typeof(System.Windows.Input.InputManager);

                // Call the StylusLogic method on the InputManager.Current instance.
                object stylusLogic = inputManagerType.InvokeMember("StylusLogic",
                    BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
                    null, InputManager.Current, null);

                return stylusLogic;
            }

            return null;
        }

Or running my demo: https://github.com/lindexi/lindexi_gd/tree/bdf0e7a0/LeekailawnahelNarjailearyaydi

lindexi commented 1 year ago

@HouZack And I created the tool application which can help us to collect the touch info, see https://github.com/dotnet-campus/ManipulationDemo

HouZack commented 1 year ago

@HouZack Could you try re-start the touch module by the code:

            var windowInteropHelper = new WindowInteropHelper(this);
            var hwndSource = HwndSource.FromHwnd(windowInteropHelper.Handle);

            object stylusLogic = GetStylusLogic();

            if (stylusLogic == null)
            {
                return;
            }

            Type inputManagerType = typeof(System.Windows.Input.InputManager);
            var wispLogicType = inputManagerType.Assembly.GetType("System.Windows.Input.StylusWisp.WispLogic");

            var windowInteropHelper = new WindowInteropHelper(this);
            var hwndSource = HwndSource.FromHwnd(windowInteropHelper.Handle);

            var unRegisterHwndForInputMethodInfo = wispLogicType.GetMethod("UnRegisterHwndForInput",
                BindingFlags.Instance | BindingFlags.NonPublic);

            unRegisterHwndForInputMethodInfo.Invoke(stylusLogic, new object[] {hwndSource});

            var registerHwndForInputMethodInfo = wispLogicType.GetMethod("RegisterHwndForInput",
                BindingFlags.Instance | BindingFlags.NonPublic);

            registerHwndForInputMethodInfo.Invoke(stylusLogic, new object[]
            {
                InputManager.Current,
                PresentationSource.FromVisual(this)
            });

        private object GetStylusLogic()
        {
            TabletDeviceCollection devices = System.Windows.Input.Tablet.TabletDevices;

            if (devices.Count > 0)
            {
                // Get the Type of InputManager.
                Type inputManagerType = typeof(System.Windows.Input.InputManager);

                // Call the StylusLogic method on the InputManager.Current instance.
                object stylusLogic = inputManagerType.InvokeMember("StylusLogic",
                    BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
                    null, InputManager.Current, null);

                return stylusLogic;
            }

            return null;
        }

Or running my demo: https://github.com/lindexi/lindexi_gd/tree/bdf0e7a0/LeekailawnahelNarjailearyaydi

@lindexi It will crash in "HwndSource.FromHwnd(windowInteropHelper.Handle)" image

HouZack commented 1 year ago

@HouZack And I created the tool application which can help us to collect the touch info, see https://github.com/dotnet-campus/ManipulationDemo @lindexi these are my application messages and logs. image

log.txt

HouZack commented 1 year ago

@lindexi I followed your blog and try to restart touch, it still not work. https://blog.lindexi.com/post/WPF-%E8%A7%A6%E6%91%B8%E5%A4%B1%E6%95%88-%E8%AF%95%E8%AF%95%E9%87%8D%E5%90%AF%E8%A7%A6%E6%91%B8.html image

lindexi commented 1 year ago

@HouZack I know the reason for this. Because the touch module of the system throws a COM exception.

HouZack commented 1 year ago

@HouZack I know the reason for this. Because the touch module of the system throws a COM exception.

@lindexi Is reboot PC the only solution currently?

lindexi commented 1 year ago

@HouZack WPF will use RealTimeStylus to get the touch by default. But WPF init the RealTimeStylus fail and throw the COM exception.

System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been returned from a call to a COM component.
   at MS.Win32.Penimc.IPimcTablet3.CreateContext(IntPtr handle, Boolean fEnable, UInt32 timeout, IPimcContext3& IPimcContext, Int32& key, Int64& commHandle)
   at System.Windows.Input.PenThreadWorker.WorkerOperationCreateContext.OnDoWork()
lindexi commented 1 year ago

@HouZack I'm guessing the possible reasons are:

More test methods:

        public App()
        {
            AppContext.SetSwitch("Switch.System.Windows.Input.Stylus.EnablePointerSupport", true);
        }
HouZack commented 1 year ago

6. If I use "EnablePointerSupport", touch will be normal. But there are some reason I cannot use "EnablePointerSupport". I write a easy sample code to reproduce as attach video.

@lindexi If set EnablePointerSupport to true, touch will be normal, as above my sixth statement and demo video. But there are other side events with this workaround in our Application.

kircsa08 commented 1 year ago

@HouZack Is there any solution? I am facing with the same issue..

lindexi commented 1 year ago

@kircsa08 You can try the two ways to solve it when you and @HouZack issues are the same.

  1. re-start the touch module: https://github.com/dotnet/wpf/issues/7069#issuecomment-1286364219
  2. Enable the Pointer: https://github.com/dotnet/wpf/issues/7069#issuecomment-1286429945
kircsa08 commented 1 year ago

@kircsa08 You can try the two ways to solve it when you and @HouZack issues are the same.

  1. re-start the touch module: https://github.com/dotnet/wpf/issues/7069#issuecomment-1286364219

  2. Enable the Pointer: https://github.com/dotnet/wpf/issues/7069#issuecomment-1286429945

thank you so much, the 2nd workaround has solved my issue !!

RVPryimak commented 1 year ago

@HouZack I'm guessing the possible reasons are:

  • There is a problem with the touch module of the system

    • Such as the devices
  • Apps are injected with malware

    • You can try to get the module injected by the application by VMMap tool or ProcessExplorer tool
  • The COM conflict

    • Find the CEB1EF24-BB4E-498B-9DF7-12887ED0EB24 in Windows Register

More test methods:

  • Using WM_Pointer:
        public App()
        {
            AppContext.SetSwitch("Switch.System.Windows.Input.Stylus.EnablePointerSupport", true);
        }

@lindexi Hi. I had the same issue with touch. After i use following code almost at all devices touch start to work like it's should but I have a new Surface Pro 9 and if i enable this feature on it. Application start to crash with following exception System.ArgumentException: '{0}' must be greater than or equal to '{1}'. (Parameter 'maximum') Could it be that this feature 'Switch.System.Windows.Input.Stylus.EnablePointerSupport= true' not exists at new devices?

lindexi commented 1 year ago

@RVPryimak Could you add more exception info?

RVPryimak commented 1 year ago

@lindexi Actualy that is all what i receive. Also i find out that MoudleDoubleClick command stop work with touch after i run 'AppContext.SetSwitch("Switch.System.Windows.Input.Stylus.EnablePointerSupport", true);'

RVPryimak commented 1 year ago

@lindexi In my case touch stop working well after any dialog is closed. After this Main windows stop react on touch event at least for first 10. Event if I subscribe to TouchDown event its not raise for first 10-15 click After ''AppContext.SetSwitch("Switch.System.Windows.Input.Stylus.EnablePointerSupport", true);'' Events start to raise like it's should but MouseDoubleClick not works and one device throw exception

lindexi commented 1 year ago

@RVPryimak Your problems are beyond imagination. And can you try my demo: https://github.com/dotnet-campus/ManipulationDemo

RVPryimak commented 1 year ago

@lindexi System.ArgumentException: '{0}' must be greater than or equal to '{1}'. (Parameter 'maximum') at System.Windows.Input.StylusPointPropertyInfo..ctor(StylusPointProperty stylusPointProperty, Int32 minimum, Int32 maximum, StylusPointPropertyUnit unit, Single resolution) This error i get from your application. The same what i receive in my after i enable ''AppContext.SetSwitch("Switch.System.Windows.Input.Stylus.EnablePointerSupport", true);''

lindexi commented 1 year ago

@RVPryimak I'm guessing the problem from your touch screen or the system

And It appears that the HID descriptor is incorrect

RVPryimak commented 1 year ago

@lindexi I will try to provide small example with my issue. I will be appreciate if you will have time to look on it

wangtenghong commented 10 months ago

@lindexi I already using the fix suggestion that you mentioned in this post

public App()
        {
            AppContext.SetSwitch("Switch.System.Windows.Input.Stylus.EnablePointerSupport", true);
        }

But our co-work company using a new touch panel in ongoing project and using our product for verification but found our software won't react to click/touch/stylus moving. The error message as following and in attachments. I am wondering if you could do help to check them and give some clues to fix this problem.

10-30-2023 00:56:23 [Exception in LogUnhandledException] exception: System.ArgumentException: '{0}' must be greater than or equal to '{1}'. (Parameter 'maximum') at System.Windows.Input.StylusPointPropertyInfo..ctor(StylusPointProperty stylusPointProperty, Int32 minimum, Int32 maximum, StylusPointPropertyUnit unit, Single resolution) at System.Windows.Input.StylusPointer.PointerStylusPointPropertyInfoHelper.CreatePropertyInfo(POINTER_DEVICE_PROPERTY prop) at System.Windows.Input.StylusPointer.PointerTabletDeviceInfo.TryInitializeSupportedStylusPointProperties() at System.Windows.Input.StylusPointer.PointerTabletDeviceInfo.TryInitialize() at System.Windows.Input.StylusPointer.PointerTabletDeviceCollection.Refresh()

HID_01 HID_02 HID_03 part-of-log.txt

lindexi commented 10 months ago

@wangtenghong The exception as follow says the touch data do not match the HID Descriptors define.

10-30-2023 00:56:23 [Exception in LogUnhandledException] exception: System.ArgumentException: '{0}' must be greater than or equal to '{1}'. (Parameter 'maximum')
at System.Windows.Input.StylusPointPropertyInfo..ctor(StylusPointProperty stylusPointProperty, Int32 minimum, Int32 maximum, StylusPointPropertyUnit unit, Single resolution)

Common issues often involve defining the width and height of touch points in the HID descriptor, but the actual reported touch point data only includes X and Y coordinates, without the width and height information. You can use the BusHound tool to capture packets to understand the touch point data reported by your touch device, and check if there are any definition errors. Additionally, it's also possible that the points you output exceed the maximum and minimum value range defined by your descriptor.

lindexi commented 10 months ago

And from the code of the constructor in StylusPointPropertyInfo, it is evident that there is an error in your data. Your maximum value is less than your minimum value.

https://github.com/dotnet/wpf/blob/c8a6d45e15701297c5c4bb5714d6c76350c6e956/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Common/StylusPointPropertyInfo.cs#L64-L67